From 939fcf7b8691b9e9ac80e92eedeb14476069021b Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Mon, 18 Sep 2023 13:34:08 +0000 Subject: [PATCH 001/295] drm/etnaviv: Replace strncpy with strscpy_pad `strncpy` is deprecated for use on NUL-terminated destination strings [1]. We should prefer more robust and less ambiguous string interfaces. A suitable replacement is `strscpy_pad` due to the fact that it guarantees NUL-termination on the destination buffer whilst maintaining the NUL-padding behavior that strncpy provides. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Cc: Bo YU Signed-off-by: Justin Stitt Reviewed-by: Kees Cook Reviewed-by: Christian Gmeiner [lst: changed subject according to suggestion from Kees] Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_perfmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c index bafdfe49c1d8..dc9dea664a28 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c @@ -511,7 +511,7 @@ int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, domain->id = domain->iter; domain->nr_signals = dom->nr_signals; - strncpy(domain->name, dom->name, sizeof(domain->name)); + strscpy_pad(domain->name, dom->name, sizeof(domain->name)); domain->iter++; if (domain->iter == nr_domains) @@ -540,7 +540,7 @@ int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, sig = &dom->signal[signal->iter]; signal->id = signal->iter; - strncpy(signal->name, sig->name, sizeof(signal->name)); + strscpy_pad(signal->name, sig->name, sizeof(signal->name)); signal->iter++; if (signal->iter == dom->nr_signals) From 4c6e6c01d82fc0edd8b47cb1ffbd05289029b005 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Mon, 2 Oct 2023 19:12:03 +0800 Subject: [PATCH 002/295] drm/etnaviv: Drop the second argument of the etnaviv_gem_new_impl() The mentioned second parameter is the 'u32 size', but it is not get used by the etnaviv_gem_new_impl() function, so drop it. No functional change. Signed-off-by: Sui Jingfeng Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index b5f73502e3dd..be2f459c66b5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -542,7 +542,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = { .vm_ops = &vm_ops, }; -static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags, +static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags, const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj) { struct etnaviv_gem_object *etnaviv_obj; @@ -591,8 +591,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, size = PAGE_ALIGN(size); - ret = etnaviv_gem_new_impl(dev, size, flags, - &etnaviv_gem_shmem_ops, &obj); + ret = etnaviv_gem_new_impl(dev, flags, &etnaviv_gem_shmem_ops, &obj); if (ret) goto fail; @@ -627,7 +626,7 @@ int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags, struct drm_gem_object *obj; int ret; - ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj); + ret = etnaviv_gem_new_impl(dev, flags, ops, &obj); if (ret) return ret; From 4cb91cc2cd0d31ffc690b23c88901f4f315b9d78 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Mon, 2 Oct 2023 19:12:04 +0800 Subject: [PATCH 003/295] drm/etnaviv: Fix coding style 1) Keep the curly brace aligned. 2) No indentation by double tabs where single tab indentation is enough. Signed-off-by: Sui Jingfeng Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index a8d3fa81e4ec..a3a17316a328 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -79,7 +79,7 @@ static int etnaviv_open(struct drm_device *dev, struct drm_file *file) drm_sched_entity_init(&ctx->sched_entity[i], DRM_SCHED_PRIORITY_NORMAL, &sched, 1, NULL); - } + } } file->driver_priv = ctx; @@ -233,11 +233,11 @@ static int show_each_gpu(struct seq_file *m, void *arg) } static struct drm_info_list etnaviv_debugfs_list[] = { - {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs}, - {"gem", show_unlocked, 0, etnaviv_gem_show}, - { "mm", show_unlocked, 0, etnaviv_mm_show }, - {"mmu", show_each_gpu, 0, etnaviv_mmu_show}, - {"ring", show_each_gpu, 0, etnaviv_ring_show}, + {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs}, + {"gem", show_unlocked, 0, etnaviv_gem_show}, + { "mm", show_unlocked, 0, etnaviv_mm_show }, + {"mmu", show_each_gpu, 0, etnaviv_mmu_show}, + {"ring", show_each_gpu, 0, etnaviv_ring_show}, }; static void etnaviv_debugfs_init(struct drm_minor *minor) From a10a43eee8589221d79b9050556aed2c5842d8b8 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Mon, 2 Oct 2023 19:12:05 +0800 Subject: [PATCH 004/295] drm/etnaviv: Add helper functions to create and destroy platform device The newly introduced functions are etnaviv_create_platform_device() and etnaviv_destroy_platform_device(). Those two function are pure function and can be shared for other use case. Currently, the benefit is that we no longer need to call of_node_put() for three different cases, we only need to call it once in the etnaviv_init() function. Signed-off-by: Sui Jingfeng Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 57 ++++++++++++++++++--------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index a3a17316a328..8fe39e31d22d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -655,11 +655,43 @@ static struct platform_driver etnaviv_platform_driver = { }, }; +static int etnaviv_create_platform_device(const char *name, + struct platform_device **ppdev) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); + if (!pdev) + return -ENOMEM; + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ret; + } + + *ppdev = pdev; + + return 0; +} + +static void etnaviv_destroy_platform_device(struct platform_device **ppdev) +{ + struct platform_device *pdev = *ppdev; + + if (!pdev) + return; + + platform_device_unregister(pdev); + + *ppdev = NULL; +} + static struct platform_device *etnaviv_drm; static int __init etnaviv_init(void) { - struct platform_device *pdev; int ret; struct device_node *np; @@ -680,23 +712,12 @@ static int __init etnaviv_init(void) for_each_compatible_node(np, NULL, "vivante,gc") { if (!of_device_is_available(np)) continue; - - pdev = platform_device_alloc("etnaviv", PLATFORM_DEVID_NONE); - if (!pdev) { - ret = -ENOMEM; - of_node_put(np); - goto unregister_platform_driver; - } - - ret = platform_device_add(pdev); - if (ret) { - platform_device_put(pdev); - of_node_put(np); - goto unregister_platform_driver; - } - - etnaviv_drm = pdev; of_node_put(np); + + ret = etnaviv_create_platform_device("etnaviv", &etnaviv_drm); + if (ret) + goto unregister_platform_driver; + break; } @@ -712,7 +733,7 @@ module_init(etnaviv_init); static void __exit etnaviv_exit(void) { - platform_device_unregister(etnaviv_drm); + etnaviv_destroy_platform_device(&etnaviv_drm); platform_driver_unregister(&etnaviv_platform_driver); platform_driver_unregister(&etnaviv_gpu_driver); } From f5cc0cbc2796627d8b9c561a8e135fe34615b654 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Mon, 2 Oct 2023 19:12:06 +0800 Subject: [PATCH 005/295] drm/etnaviv: Add a helper to get the first available GPU device node This patch make the code in the etnaviv_pdev_probe() less twisted, and it also make it easier to drop the reference to device node after finished. Before apply this patch, there is no call to of_node_put() when done. We should call of_node_put() when done. Signed-off-by: Sui Jingfeng Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 8fe39e31d22d..4bdfb1c81eff 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -29,6 +29,17 @@ * DRM operations: */ +static struct device_node *etnaviv_of_first_available_node(void) +{ + struct device_node *np; + + for_each_compatible_node(np, NULL, "vivante,gc") { + if (of_device_is_available(np)) + return np; + } + + return NULL; +} static void load_gpu(struct drm_device *dev) { @@ -597,9 +608,6 @@ static int etnaviv_pdev_probe(struct platform_device *pdev) if (!of_device_is_available(core_node)) continue; - if (!first_node) - first_node = core_node; - drm_of_component_match_add(&pdev->dev, &match, component_compare_of, core_node); } @@ -634,8 +642,11 @@ static int etnaviv_pdev_probe(struct platform_device *pdev) * device as the GPU we found. This assumes that all Vivante * GPUs in the system share the same DMA constraints. */ - if (first_node) + first_node = etnaviv_of_first_available_node(); + if (first_node) { of_dma_configure(&pdev->dev, first_node, true); + of_node_put(first_node); + } return component_master_add_with_match(dev, &etnaviv_master_ops, match); } @@ -709,16 +720,13 @@ static int __init etnaviv_init(void) * If the DT contains at least one available GPU device, instantiate * the DRM platform device. */ - for_each_compatible_node(np, NULL, "vivante,gc") { - if (!of_device_is_available(np)) - continue; + np = etnaviv_of_first_available_node(); + if (np) { of_node_put(np); ret = etnaviv_create_platform_device("etnaviv", &etnaviv_drm); if (ret) goto unregister_platform_driver; - - break; } return 0; From e8491f0238625b156e2d82c49fd8c838352b7e74 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Mon, 2 Oct 2023 19:12:07 +0800 Subject: [PATCH 006/295] drm/etnaviv: Clean up etnaviv_gem_get_pages As in the etnaviv_gem_get_pages() function, the point to the drm_device has already been cached to the 'dev' local variable. We can use it directly, While at it, using 'unsigned int' type to count the number of pages. As the drm_prime_pages_to_sg() function takes an unsigned int type for its third argument. No functional change. Signed-off-by: Sui Jingfeng [lst: Reword subject to make more generic and match patch content] Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index be2f459c66b5..71a6d2b1c80f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -100,11 +100,10 @@ struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *etnaviv_obj) if (!etnaviv_obj->sgt) { struct drm_device *dev = etnaviv_obj->base.dev; - int npages = etnaviv_obj->base.size >> PAGE_SHIFT; + unsigned int npages = etnaviv_obj->base.size >> PAGE_SHIFT; struct sg_table *sgt; - sgt = drm_prime_pages_to_sg(etnaviv_obj->base.dev, - etnaviv_obj->pages, npages); + sgt = drm_prime_pages_to_sg(dev, etnaviv_obj->pages, npages); if (IS_ERR(sgt)) { dev_err(dev->dev, "failed to allocate sgt: %ld\n", PTR_ERR(sgt)); From 9e2e8a5113bf452081cb1f6a13617e36f5298cbf Mon Sep 17 00:00:00 2001 From: Sui Jingfeng Date: Sat, 7 Oct 2023 15:03:12 +0800 Subject: [PATCH 007/295] drm/etnaviv: Drop the 'len' parameter of etnaviv_iommu_map() function The 'len' parameter is the 4th argument, because it is not get used, so drop it. No functional change. Signed-off-by: Sui Jingfeng Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index 4fa72567183a..1661d589bf3e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -70,7 +70,7 @@ static int etnaviv_context_map(struct etnaviv_iommu_context *context, } static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova, - struct sg_table *sgt, unsigned len, int prot) + struct sg_table *sgt, int prot) { struct scatterlist *sg; unsigned int da = iova; unsigned int i; @@ -314,7 +314,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context, goto unlock; mapping->iova = node->start; - ret = etnaviv_iommu_map(context, node->start, sgt, etnaviv_obj->base.size, + ret = etnaviv_iommu_map(context, node->start, sgt, ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE); if (ret < 0) { From b0da08559c749ddc0e9a6e378b292ffa6845fb01 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 7 Jun 2023 14:58:41 +0200 Subject: [PATCH 008/295] drm/etnaviv: disable MLCG and pulse eater on GPU reset Module level clock gating and the pulse eater might interfere with the GPU reset, as they both have the potential to stop the clock and thus reset propagation to parts of the GPU. Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 9276756e1397..1dcfa23db3be 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -513,8 +513,19 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) timeout = jiffies + msecs_to_jiffies(1000); while (time_is_after_jiffies(timeout)) { - /* enable clock */ unsigned int fscale = 1 << (6 - gpu->freq_scale); + u32 pulse_eater = 0x01590880; + + /* disable clock gating */ + gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, 0x0); + + /* disable pulse eater */ + pulse_eater |= BIT(17); + gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater); + pulse_eater |= BIT(0); + gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater); + + /* enable clock */ control = VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale); etnaviv_gpu_load_clock(gpu, control); From 1dccdba084897443d116508a8ed71e0ac8a031a4 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 21 Nov 2023 07:32:59 +0100 Subject: [PATCH 009/295] drm/etnaviv: Expose a few more chipspecs to userspace These ones will be needed to make use fo the NN and TP units in the NPUs based on Vivante IP. Also fix the number of NN cores in the VIPNano-qi. Signed-off-by: Tomeu Vizoso Acked-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 20 +++++++++++++++ drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 12 +++++++++ drivers/gpu/drm/etnaviv/etnaviv_hwdb.c | 34 ++++++++++++++++++++++++++ include/uapi/drm/etnaviv_drm.h | 5 ++++ 4 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 1dcfa23db3be..18725ff5c79b 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -164,6 +164,26 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) *value = gpu->identity.eco_id; break; + case ETNAVIV_PARAM_GPU_NN_CORE_COUNT: + *value = gpu->identity.nn_core_count; + break; + + case ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE: + *value = gpu->identity.nn_mad_per_core; + break; + + case ETNAVIV_PARAM_GPU_TP_CORE_COUNT: + *value = gpu->identity.tp_core_count; + break; + + case ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE: + *value = gpu->identity.on_chip_sram_size; + break; + + case ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE: + *value = gpu->identity.axi_sram_size; + break; + default: DBG("%s: invalid param: %u", dev_name(gpu->dev), param); return -EINVAL; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 197e0037732e..7d5e9158e13c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -54,6 +54,18 @@ struct etnaviv_chip_identity { /* Number of Neural Network cores. */ u32 nn_core_count; + /* Number of MAD units per Neural Network core. */ + u32 nn_mad_per_core; + + /* Number of Tensor Processing cores. */ + u32 tp_core_count; + + /* Size in bytes of the SRAM inside the NPU. */ + u32 on_chip_sram_size; + + /* Size in bytes of the SRAM across the AXI bus. */ + u32 axi_sram_size; + /* Size of the vertex cache. */ u32 vertex_cache_size; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index 67201242438b..9eb8ca7c5034 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -17,6 +17,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 128, .shader_core_count = 1, .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 8, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -48,6 +52,11 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 256, .shader_core_count = 1, + .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 8, .vertex_output_buffer_size = 512, .pixel_pipes = 1, @@ -80,6 +89,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 512, .shader_core_count = 2, .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -112,6 +125,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 512, .shader_core_count = 2, .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -143,6 +160,11 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 512, .shader_core_count = 2, + .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -175,6 +197,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 1024, .shader_core_count = 4, .nn_core_count = 0, + .nn_mad_per_core = 0, + .tp_core_count = 0, + .on_chip_sram_size = 0, + .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 2, @@ -207,6 +233,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 256, .shader_core_count = 1, .nn_core_count = 8, + .nn_mad_per_core = 64, + .tp_core_count = 4, + .on_chip_sram_size = 524288, + .axi_sram_size = 1048576, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -239,6 +269,10 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 256, .shader_core_count = 1, .nn_core_count = 6, + .nn_mad_per_core = 64, + .tp_core_count = 3, + .on_chip_sram_size = 262144, + .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h index af024d90453d..d87410a8443a 100644 --- a/include/uapi/drm/etnaviv_drm.h +++ b/include/uapi/drm/etnaviv_drm.h @@ -77,6 +77,11 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_PRODUCT_ID 0x1c #define ETNAVIV_PARAM_GPU_CUSTOMER_ID 0x1d #define ETNAVIV_PARAM_GPU_ECO_ID 0x1e +#define ETNAVIV_PARAM_GPU_NN_CORE_COUNT 0x1f +#define ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE 0x20 +#define ETNAVIV_PARAM_GPU_TP_CORE_COUNT 0x21 +#define ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE 0x22 +#define ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE 0x23 #define ETNA_MAX_PIPES 4 From c9959996a8fc171bbb2c2d9c7478306f331a6cca Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Thu, 7 Dec 2023 08:43:08 +0100 Subject: [PATCH 010/295] drm/etnaviv: add sensitive state for PE_RT_ADDR_4_PIPE(3, 0|1) address 0x1540 is the address of 4th render target address pair (two pixel pipes). Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c index b106e8b288ad..9bf47327f436 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c @@ -54,6 +54,7 @@ static const struct { ST(0x1480, 8), ST(0x1500, 8), ST(0x1520, 8), + ST(0x1540, 8), ST(0x1608, 1), ST(0x1610, 1), ST(0x1658, 1), From 15ef04e2b683153670791ce961871865a6a6ee13 Mon Sep 17 00:00:00 2001 From: Hsiao Chien Sung Date: Thu, 14 Dec 2023 13:58:43 +0800 Subject: [PATCH 011/295] drm/mediatek: Add Padding to OVL adaptor Add MT8188 Padding to OVL adaptor to probe the driver. Reviewed-by: CK Hu Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hsiao Chien Sung Link: https://patchwork.kernel.org/project/dri-devel/patch/20231214055847.4936-20-shawn.sung@mediatek.com/ Signed-off-by: Chun-Kuang Hu --- .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c index 12a37f740bf4..309c48c9a07c 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c @@ -30,6 +30,7 @@ enum mtk_ovl_adaptor_comp_type { OVL_ADAPTOR_TYPE_ETHDR, OVL_ADAPTOR_TYPE_MDP_RDMA, OVL_ADAPTOR_TYPE_MERGE, + OVL_ADAPTOR_TYPE_PADDING, OVL_ADAPTOR_TYPE_NUM, }; @@ -47,6 +48,14 @@ enum mtk_ovl_adaptor_comp_id { OVL_ADAPTOR_MERGE1, OVL_ADAPTOR_MERGE2, OVL_ADAPTOR_MERGE3, + OVL_ADAPTOR_PADDING0, + OVL_ADAPTOR_PADDING1, + OVL_ADAPTOR_PADDING2, + OVL_ADAPTOR_PADDING3, + OVL_ADAPTOR_PADDING4, + OVL_ADAPTOR_PADDING5, + OVL_ADAPTOR_PADDING6, + OVL_ADAPTOR_PADDING7, OVL_ADAPTOR_ID_MAX }; @@ -67,6 +76,7 @@ static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = { [OVL_ADAPTOR_TYPE_ETHDR] = "ethdr", [OVL_ADAPTOR_TYPE_MDP_RDMA] = "vdo1-rdma", [OVL_ADAPTOR_TYPE_MERGE] = "merge", + [OVL_ADAPTOR_TYPE_PADDING] = "padding", }; static const struct mtk_ddp_comp_funcs ethdr = { @@ -81,6 +91,13 @@ static const struct mtk_ddp_comp_funcs merge = { .clk_disable = mtk_merge_clk_disable, }; +static const struct mtk_ddp_comp_funcs padding = { + .clk_enable = mtk_padding_clk_enable, + .clk_disable = mtk_padding_clk_disable, + .start = mtk_padding_start, + .stop = mtk_padding_stop, +}; + static const struct mtk_ddp_comp_funcs rdma = { .power_on = mtk_mdp_rdma_power_on, .power_off = mtk_mdp_rdma_power_off, @@ -102,6 +119,14 @@ static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = { [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2, &merge }, [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3, &merge }, [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4, &merge }, + [OVL_ADAPTOR_PADDING0] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING0, 0, &padding }, + [OVL_ADAPTOR_PADDING1] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING1, 1, &padding }, + [OVL_ADAPTOR_PADDING2] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING2, 2, &padding }, + [OVL_ADAPTOR_PADDING3] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING3, 3, &padding }, + [OVL_ADAPTOR_PADDING4] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING4, 4, &padding }, + [OVL_ADAPTOR_PADDING5] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING5, 5, &padding }, + [OVL_ADAPTOR_PADDING6] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING6, 6, &padding }, + [OVL_ADAPTOR_PADDING7] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING7, 7, &padding }, }; void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, @@ -437,6 +462,7 @@ static int ovl_adaptor_comp_get_id(struct device *dev, struct device_node *node, } static const struct of_device_id mtk_ovl_adaptor_comp_dt_ids[] = { + { .compatible = "mediatek,mt8188-disp-padding", .data = (void *)OVL_ADAPTOR_TYPE_PADDING }, { .compatible = "mediatek,mt8195-disp-ethdr", .data = (void *)OVL_ADAPTOR_TYPE_ETHDR }, { .compatible = "mediatek,mt8195-disp-merge", .data = (void *)OVL_ADAPTOR_TYPE_MERGE }, { .compatible = "mediatek,mt8195-vdo1-rdma", .data = (void *)OVL_ADAPTOR_TYPE_MDP_RDMA }, From b82a2a4b85628a287ae4e9da6f8c258b955f0c45 Mon Sep 17 00:00:00 2001 From: Hsiao Chien Sung Date: Thu, 14 Dec 2023 13:58:47 +0800 Subject: [PATCH 012/295] drm/mediatek: Support MT8188 VDOSYS1 in display driver - The mmsys_dev_num in MT8188 VDOSYS0 was set to 1 since VDOSYS1 was not available before. Increase it to support VDOSYS1 in display driver. - Add compatible name for MT8188 VDOSYS1 (shares the same driver data with MT8195 VDOSYS1) Reviewed-by: CK Hu Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hsiao Chien Sung Link: https://patchwork.kernel.org/project/dri-devel/patch/20231214055847.4936-24-shawn.sung@mediatek.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 14a1e0157cc4..74832c213092 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -293,7 +293,7 @@ static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = { .main_len = ARRAY_SIZE(mt8188_mtk_ddp_main), .conn_routes = mt8188_mtk_ddp_main_routes, .num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes), - .mmsys_dev_num = 1, + .mmsys_dev_num = 2, }; static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { @@ -334,6 +334,8 @@ static const struct of_device_id mtk_drm_of_ids[] = { .data = &mt8186_mmsys_driver_data}, { .compatible = "mediatek,mt8188-vdosys0", .data = &mt8188_vdosys0_driver_data}, + { .compatible = "mediatek,mt8188-vdosys1", + .data = &mt8195_vdosys1_driver_data}, { .compatible = "mediatek,mt8192-mmsys", .data = &mt8192_mmsys_driver_data}, { .compatible = "mediatek,mt8195-mmsys", From e5dbaa9f43ea6da88d6cf1dd020308fc448c82ea Mon Sep 17 00:00:00 2001 From: Juha-Pekka Heikkila Date: Fri, 2 Feb 2024 17:06:02 +0200 Subject: [PATCH 013/295] drm/i915/display: On Xe2 always enable decompression with tile4 With Xe2 always treat tile4 as if it was using flat ccs. Signed-off-by: Juha-Pekka Heikkila Reviewed-by: Mika Kahola Signed-off-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20240202150602.430036-2-juhapekka.heikkila@gmail.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 392d93e97bf8..e941e2e4fd14 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -948,6 +948,11 @@ static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, if (DISPLAY_VER(dev_priv) == 13) plane_ctl |= adlp_plane_ctl_arb_slots(plane_state); + if (GRAPHICS_VER(dev_priv) >= 20 && + fb->modifier == I915_FORMAT_MOD_4_TILED) { + plane_ctl |= PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; + } + return plane_ctl; } From 6074be620c31dc2ae11af96a1a5ea95580976fb5 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Mon, 5 Feb 2024 20:46:19 +0000 Subject: [PATCH 014/295] drm/i915/dsc: Fix the macro that calculates DSCC_/DSCA_ PPS reg address Commit bd077259d0a9 ("drm/i915/vdsc: Add function to read any PPS register") defines a new macro to calculate the DSC PPS register addresses with PPS number as an input. This macro correctly calculates the addresses till PPS 11 since the addresses increment by 4. So in that case the following macro works correctly to give correct register address: _MMIO(_DSCA_PPS_0 + (pps) * 4) However after PPS 11, the register address for PPS 12 increments by 12 because of RC Buffer memory allocation in between. Because of this discontinuity in the address space, the macro calculates wrong addresses for PPS 12 - 16 resulting into incorrect DSC PPS parameter value read/writes causing DSC corruption. This fixes it by correcting this macro to add the offset of 12 for PPS >=12. v3: Add correct paranthesis for pps argument (Jani Nikula) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10172 Fixes: bd077259d0a9 ("drm/i915/vdsc: Add function to read any PPS register") Cc: Suraj Kandpal Cc: Ankit Nautiyal Cc: Animesh Manna Cc: Jani Nikula Cc: Sean Paul Cc: Drew Davenport Signed-off-by: Manasi Navare Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20240205204619.1991673-1-navaremanasi@chromium.org --- drivers/gpu/drm/i915/display/intel_vdsc_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index 64f440fdc22b..8b21dc8e26d5 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -51,8 +51,8 @@ #define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00) #define _DSCA_PPS_0 0x6B200 #define _DSCC_PPS_0 0x6BA00 -#define DSCA_PPS(pps) _MMIO(_DSCA_PPS_0 + (pps) * 4) -#define DSCC_PPS(pps) _MMIO(_DSCC_PPS_0 + (pps) * 4) +#define DSCA_PPS(pps) _MMIO(_DSCA_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4) +#define DSCC_PPS(pps) _MMIO(_DSCC_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4) #define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB 0x78270 #define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB 0x78370 #define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC 0x78470 From 6061811d72e14f41f71b6a025510920b187bfcca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:45:52 +0200 Subject: [PATCH 015/295] drm/i915/dp: Limit SST link rate to <=8.1Gbps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the link rate to HBR3 or below (<=8.1Gbps) in SST mode. UHBR (10Gbps+) link rates require 128b/132b channel encoding which we have not yet hooked up into the SST/no-sideband codepaths. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208154552.14545-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ab415f41924d..5045c34a16be 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2356,6 +2356,9 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, limits->min_rate = intel_dp_common_rate(intel_dp, 0); limits->max_rate = intel_dp_max_link_rate(intel_dp); + /* FIXME 128b/132b SST support missing */ + limits->max_rate = min(limits->max_rate, 810000); + limits->min_lane_count = 1; limits->max_lane_count = intel_dp_max_lane_count(intel_dp); From c9950a5d5056b11dd04b7ab3ef8e259be0c6268a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:08 +0200 Subject: [PATCH 016/295] drm/i915: Correct for_each_old_global_obj_in_state() arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit for_each_old_global_obj_in_state() gives us the old state, not the new state. Correct the name of the macro argument. Note that while the argument was misnamed the macro did work correctly regardless. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_global_state.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_global_state.h b/drivers/gpu/drm/i915/display/intel_global_state.h index 5c8545d7a76a..6506a8e32972 100644 --- a/drivers/gpu/drm/i915/display/intel_global_state.h +++ b/drivers/gpu/drm/i915/display/intel_global_state.h @@ -37,11 +37,11 @@ struct intel_global_obj { (__i)++) \ for_each_if(obj) -#define for_each_old_global_obj_in_state(__state, obj, new_obj_state, __i) \ +#define for_each_old_global_obj_in_state(__state, obj, old_obj_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->num_global_objs && \ ((obj) = (__state)->global_objs[__i].ptr, \ - (new_obj_state) = (__state)->global_objs[__i].old_state, 1); \ + (old_obj_state) = (__state)->global_objs[__i].old_state, 1); \ (__i)++) \ for_each_if(obj) From dff8f3f85a1bb199af7d963c97983bdee23d7dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:09 +0200 Subject: [PATCH 017/295] drm/i915/sdvo: Convert to per-device debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use drm_dbg_kms() instead of DRM_DEBUG_KMS() in the sdvo code to get the device name into the debug prints. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sdvo.c | 113 +++++++++++++--------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index a086d5f51e61..a882bed5b0ad 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -252,6 +252,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); struct i2c_msg msgs[] = { { .addr = intel_sdvo->slave_addr, @@ -271,7 +272,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) if ((ret = i2c_transfer(intel_sdvo->i2c, msgs, 2)) == 2) return true; - DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); + drm_dbg_kms(&i915->drm, "i2c transfer returned %d\n", ret); return false; } @@ -437,7 +438,8 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, drm_WARN_ON(&dev_priv->drm, pos >= sizeof(buffer) - 1); #undef BUF_PRINT - DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); + drm_dbg_kms(&dev_priv->drm, "%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), + cmd, buffer); } static const char * const cmd_status_names[] = { @@ -462,6 +464,7 @@ static bool __intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, const void *args, int args_len, bool unlocked) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); u8 *buf, status; struct i2c_msg *msgs; int i, ret = true; @@ -511,13 +514,13 @@ static bool __intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, else ret = __i2c_transfer(intel_sdvo->i2c, msgs, i+3); if (ret < 0) { - DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); + drm_dbg_kms(&i915->drm, "I2c transfer returned %d\n", ret); ret = false; goto out; } if (ret != i+3) { /* failure in I2C transfer */ - DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3); + drm_dbg_kms(&i915->drm, "I2c transfer returned %d/%d\n", ret, i+3); ret = false; } @@ -604,12 +607,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, drm_WARN_ON(&dev_priv->drm, pos >= sizeof(buffer) - 1); #undef BUF_PRINT - DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer); + drm_dbg_kms(&dev_priv->drm, "%s: R: %s\n", + SDVO_NAME(intel_sdvo), buffer); return true; log_fail: - DRM_DEBUG_KMS("%s: R: ... failed %s\n", - SDVO_NAME(intel_sdvo), buffer); + drm_dbg_kms(&dev_priv->drm, "%s: R: ... failed %s\n", + SDVO_NAME(intel_sdvo), buffer); return false; } @@ -1004,6 +1008,7 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, unsigned int if_index, u8 tx_rate, const u8 *data, unsigned int length) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); u8 set_buf_index[2] = { if_index, 0 }; u8 hbuf_size, tmp[8]; int i; @@ -1016,8 +1021,9 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, if (!intel_sdvo_get_hbuf_size(intel_sdvo, &hbuf_size)) return false; - DRM_DEBUG_KMS("writing sdvo hbuf: %i, length %u, hbuf_size: %i\n", - if_index, length, hbuf_size); + drm_dbg_kms(&i915->drm, + "writing sdvo hbuf: %i, length %u, hbuf_size: %i\n", + if_index, length, hbuf_size); if (hbuf_size < length) return false; @@ -1042,6 +1048,7 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo, unsigned int if_index, u8 *data, unsigned int length) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); u8 set_buf_index[2] = { if_index, 0 }; u8 hbuf_size, tx_rate, av_split; int i; @@ -1071,8 +1078,9 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo, if (!intel_sdvo_get_hbuf_size(intel_sdvo, &hbuf_size)) return false; - DRM_DEBUG_KMS("reading sdvo hbuf: %i, length %u, hbuf_size: %i\n", - if_index, length, hbuf_size); + drm_dbg_kms(&i915->drm, + "reading sdvo hbuf: %i, length %u, hbuf_size: %i\n", + if_index, length, hbuf_size); hbuf_size = min_t(unsigned int, length, hbuf_size); @@ -1151,6 +1159,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo, struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); u8 sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; union hdmi_infoframe *frame = &crtc_state->infoframes.avi; ssize_t len; @@ -1162,7 +1171,7 @@ static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo, len = intel_sdvo_read_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, sdvo_data, sizeof(sdvo_data)); if (len < 0) { - DRM_DEBUG_KMS("failed to read AVI infoframe\n"); + drm_dbg_kms(&i915->drm, "failed to read AVI infoframe\n"); return; } else if (len == 0) { return; @@ -1173,13 +1182,14 @@ static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo, ret = hdmi_infoframe_unpack(frame, sdvo_data, len); if (ret) { - DRM_DEBUG_KMS("Failed to unpack AVI infoframe\n"); + drm_dbg_kms(&i915->drm, "Failed to unpack AVI infoframe\n"); return; } if (frame->any.type != HDMI_INFOFRAME_TYPE_AVI) - DRM_DEBUG_KMS("Found the wrong infoframe type 0x%x (expected 0x%02x)\n", - frame->any.type, HDMI_INFOFRAME_TYPE_AVI); + drm_dbg_kms(&i915->drm, + "Found the wrong infoframe type 0x%x (expected 0x%02x)\n", + frame->any.type, HDMI_INFOFRAME_TYPE_AVI); } static void intel_sdvo_get_eld(struct intel_sdvo *intel_sdvo, @@ -1348,6 +1358,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_sdvo *intel_sdvo = to_sdvo(encoder); struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(conn_state->connector); @@ -1360,7 +1371,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, return -EINVAL; } - DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); + drm_dbg_kms(&i915->drm, "forcing bpc to 8 for SDVO\n"); /* FIXME: Don't increase pipe_bpp */ pipe_config->pipe_bpp = 8*3; pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; @@ -1439,7 +1450,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, if (!intel_sdvo_compute_avi_infoframe(intel_sdvo, pipe_config, conn_state)) { - DRM_DEBUG_KMS("bad AVI infoframe\n"); + drm_dbg_kms(&i915->drm, "bad AVI infoframe\n"); return -EINVAL; } @@ -1916,8 +1927,8 @@ static void intel_enable_sdvo(struct intel_atomic_state *state, */ if (success && !input1) { drm_dbg_kms(&dev_priv->drm, - "First %s output reported failure to " - "sync\n", SDVO_NAME(intel_sdvo)); + "First %s output reported failure to sync\n", + SDVO_NAME(intel_sdvo)); } if (0) @@ -1976,13 +1987,14 @@ intel_sdvo_mode_valid(struct drm_connector *connector, static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); BUILD_BUG_ON(sizeof(*caps) != 8); if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_DEVICE_CAPS, caps, sizeof(*caps))) return false; - DRM_DEBUG_KMS("SDVO capabilities:\n" + drm_dbg_kms(&i915->drm, "SDVO capabilities:\n" " vendor_id: %d\n" " device_id: %d\n" " device_rev_id: %d\n" @@ -2121,8 +2133,9 @@ intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, bool monitor_is_digital = drm_edid_is_digital(drm_edid); bool connector_is_digital = !!IS_DIGITAL(sdvo); - DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", - connector_is_digital, monitor_is_digital); + drm_dbg_kms(sdvo->base.base.dev, + "connector_is_digital? %d, monitor_is_digital? %d\n", + connector_is_digital, monitor_is_digital); return connector_is_digital == monitor_is_digital; } @@ -2135,8 +2148,8 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) enum drm_connector_status ret; u16 response; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); if (!intel_display_device_enabled(i915)) return connector_status_disconnected; @@ -2153,9 +2166,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) &response, 2)) return connector_status_unknown; - DRM_DEBUG_KMS("SDVO response %d %d [%x]\n", - response & 0xff, response >> 8, - intel_sdvo_connector->output_flag); + drm_dbg_kms(&i915->drm, "SDVO response %d %d [%x]\n", + response & 0xff, response >> 8, + intel_sdvo_connector->output_flag); if (response == 0) return connector_status_disconnected; @@ -2192,8 +2205,8 @@ static int intel_sdvo_get_ddc_modes(struct drm_connector *connector) int num_modes = 0; const struct drm_edid *drm_edid; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); /* set the bus switch and get the modes */ drm_edid = intel_sdvo_get_edid(connector); @@ -2287,6 +2300,7 @@ static const struct drm_display_mode sdvo_tv_modes[] = { static int intel_sdvo_get_tv_modes(struct drm_connector *connector) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); const struct drm_connector_state *conn_state = connector->state; @@ -2295,8 +2309,8 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector) int num_modes = 0; int i; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); /* * Read the list of supported input resolutions for the selected TV @@ -2783,10 +2797,11 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type) struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; struct intel_encoder *intel_encoder = to_intel_encoder(encoder); + struct drm_i915_private *i915 = to_i915(intel_encoder->base.dev); struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising DVI type 0x%x\n", type); + drm_dbg_kms(&i915->drm, "initialising DVI type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2832,12 +2847,13 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type) static bool intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, u16 type) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising TV type 0x%x\n", type); + drm_dbg_kms(&i915->drm, "initialising TV type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2871,12 +2887,13 @@ err: static bool intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, u16 type) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising analog type 0x%x\n", type); + drm_dbg_kms(&i915->drm, "initialising analog type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2908,7 +2925,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising LVDS type 0x%x\n", type); + drm_dbg_kms(&i915->drm, "initialising LVDS type 0x%x\n", type); intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) @@ -2992,6 +3009,7 @@ static bool intel_sdvo_output_init(struct intel_sdvo *sdvo, u16 type) static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); static const u16 probe_order[] = { SDVO_OUTPUT_TMDS0, SDVO_OUTPUT_TMDS1, @@ -3010,8 +3028,9 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo) flags = intel_sdvo_filter_output_flags(intel_sdvo->caps.output_flags); if (flags == 0) { - DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%04x)\n", - SDVO_NAME(intel_sdvo), intel_sdvo->caps.output_flags); + drm_dbg_kms(&i915->drm, + "%s: Unknown SDVO output type (0x%04x)\n", + SDVO_NAME(intel_sdvo), intel_sdvo->caps.output_flags); return false; } @@ -3100,8 +3119,8 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, state_assignment = response; \ drm_object_attach_property(&connector->base, \ intel_sdvo_connector->name, 0); \ - DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \ - data_value[0], data_value[1], response); \ + drm_dbg_kms(dev, #name ": max %d, default %d, current %d\n", \ + data_value[0], data_value[1], response); \ } \ } while (0) @@ -3112,6 +3131,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, struct intel_sdvo_enhancements_reply enhancements) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); struct drm_device *dev = intel_sdvo->base.base.dev; struct drm_connector *connector = &intel_sdvo_connector->base.base; struct drm_connector_state *conn_state = connector->state; @@ -3149,9 +3169,8 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, drm_object_attach_property(&connector->base, intel_sdvo_connector->right, 0); - DRM_DEBUG_KMS("h_overscan: max %d, " - "default %d, current %d\n", - data_value[0], data_value[1], response); + drm_dbg_kms(&i915->drm, "h_overscan: max %d, default %d, current %d\n", + data_value[0], data_value[1], response); } if (enhancements.overscan_v) { @@ -3185,9 +3204,8 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, drm_object_attach_property(&connector->base, intel_sdvo_connector->bottom, 0); - DRM_DEBUG_KMS("v_overscan: max %d, " - "default %d, current %d\n", - data_value[0], data_value[1], response); + drm_dbg_kms(&i915->drm, "v_overscan: max %d, default %d, current %d\n", + data_value[0], data_value[1], response); } ENHANCEMENT(&sdvo_state->tv, hpos, HPOS); @@ -3215,7 +3233,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, drm_object_attach_property(&connector->base, intel_sdvo_connector->dot_crawl, 0); - DRM_DEBUG_KMS("dot crawl: current %d\n", response); + drm_dbg_kms(&i915->drm, "dot crawl: current %d\n", response); } return true; @@ -3240,6 +3258,7 @@ intel_sdvo_create_enhance_property_lvds(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector) { + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); union { struct intel_sdvo_enhancements_reply reply; u16 response; @@ -3251,7 +3270,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, &enhancements, sizeof(enhancements)) || enhancements.response == 0) { - DRM_DEBUG_KMS("No enhancement is supported\n"); + drm_dbg_kms(&i915->drm, "No enhancement is supported\n"); return true; } From ca93f9f3a8d65a99c0f286efa503335456fdecbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:10 +0200 Subject: [PATCH 018/295] drm/i915/sdvo: Fix up code alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Realign a bunch of code that has become messy. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sdvo.c | 104 +++++++++++----------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index a882bed5b0ad..66dab0a37e65 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -762,7 +762,7 @@ static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd, } static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo, - struct intel_sdvo_dtd *dtd) + struct intel_sdvo_dtd *dtd) { return intel_sdvo_set_timing(intel_sdvo, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); @@ -930,8 +930,8 @@ static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo) BUILD_BUG_ON(sizeof(encode) != 2); return intel_sdvo_get_value(intel_sdvo, - SDVO_CMD_GET_SUPP_ENCODE, - &encode, sizeof(encode)); + SDVO_CMD_GET_SUPP_ENCODE, + &encode, sizeof(encode)); } static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo, @@ -1995,30 +1995,30 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in return false; drm_dbg_kms(&i915->drm, "SDVO capabilities:\n" - " vendor_id: %d\n" - " device_id: %d\n" - " device_rev_id: %d\n" - " sdvo_version_major: %d\n" - " sdvo_version_minor: %d\n" - " sdvo_num_inputs: %d\n" - " smooth_scaling: %d\n" - " sharp_scaling: %d\n" - " up_scaling: %d\n" - " down_scaling: %d\n" - " stall_support: %d\n" - " output_flags: %d\n", - caps->vendor_id, - caps->device_id, - caps->device_rev_id, - caps->sdvo_version_major, - caps->sdvo_version_minor, - caps->sdvo_num_inputs, - caps->smooth_scaling, - caps->sharp_scaling, - caps->up_scaling, - caps->down_scaling, - caps->stall_support, - caps->output_flags); + " vendor_id: %d\n" + " device_id: %d\n" + " device_rev_id: %d\n" + " sdvo_version_major: %d\n" + " sdvo_version_minor: %d\n" + " sdvo_num_inputs: %d\n" + " smooth_scaling: %d\n" + " sharp_scaling: %d\n" + " up_scaling: %d\n" + " down_scaling: %d\n" + " stall_support: %d\n" + " output_flags: %d\n", + caps->vendor_id, + caps->device_id, + caps->device_rev_id, + caps->sdvo_version_major, + caps->sdvo_version_minor, + caps->sdvo_num_inputs, + caps->smooth_scaling, + caps->sharp_scaling, + caps->up_scaling, + caps->down_scaling, + caps->stall_support, + caps->output_flags); return true; } @@ -2050,7 +2050,7 @@ static u16 intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) return 0; if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, - &hotplug, sizeof(hotplug))) + &hotplug, sizeof(hotplug))) return 0; return hotplug; @@ -2812,7 +2812,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type) intel_connector = &intel_sdvo_connector->base; connector = &intel_connector->base; if (intel_sdvo_get_hotplug_support(intel_sdvo) & - intel_sdvo_connector->output_flag) { + intel_sdvo_connector->output_flag) { intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag; /* * Some SDVO devices have one-shot hotplug interrupts. @@ -3092,8 +3092,8 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, intel_sdvo_connector->tv_format = - drm_property_create(dev, DRM_MODE_PROP_ENUM, - "mode", intel_sdvo_connector->format_supported_num); + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "mode", intel_sdvo_connector->format_supported_num); if (!intel_sdvo_connector->tv_format) return false; @@ -3168,7 +3168,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, return false; drm_object_attach_property(&connector->base, - intel_sdvo_connector->right, 0); + intel_sdvo_connector->right, 0); drm_dbg_kms(&i915->drm, "h_overscan: max %d, default %d, current %d\n", data_value[0], data_value[1], response); } @@ -3189,7 +3189,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, intel_sdvo_connector->max_vscan = data_value[0]; intel_sdvo_connector->top = drm_property_create_range(dev, 0, - "top_margin", 0, data_value[0]); + "top_margin", 0, data_value[0]); if (!intel_sdvo_connector->top) return false; @@ -3198,12 +3198,12 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, intel_sdvo_connector->bottom = drm_property_create_range(dev, 0, - "bottom_margin", 0, data_value[0]); + "bottom_margin", 0, data_value[0]); if (!intel_sdvo_connector->bottom) return false; drm_object_attach_property(&connector->base, - intel_sdvo_connector->bottom, 0); + intel_sdvo_connector->bottom, 0); drm_dbg_kms(&i915->drm, "v_overscan: max %d, default %d, current %d\n", data_value[0], data_value[1], response); } @@ -3491,23 +3491,23 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, goto err_output; drm_dbg_kms(&dev_priv->drm, "%s device VID/DID: %02X:%02X.%02X, " - "clock range %dMHz - %dMHz, " - "num inputs: %d, " - "output 1: %c, output 2: %c\n", - SDVO_NAME(intel_sdvo), - intel_sdvo->caps.vendor_id, intel_sdvo->caps.device_id, - intel_sdvo->caps.device_rev_id, - intel_sdvo->pixel_clock_min / 1000, - intel_sdvo->pixel_clock_max / 1000, - intel_sdvo->caps.sdvo_num_inputs, - /* check currently supported outputs */ - intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 | - SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_SVID0 | - SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB0) ? 'Y' : 'N', - intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1 | - SDVO_OUTPUT_LVDS1) ? 'Y' : 'N'); + "clock range %dMHz - %dMHz, " + "num inputs: %d, " + "output 1: %c, output 2: %c\n", + SDVO_NAME(intel_sdvo), + intel_sdvo->caps.vendor_id, intel_sdvo->caps.device_id, + intel_sdvo->caps.device_rev_id, + intel_sdvo->pixel_clock_min / 1000, + intel_sdvo->pixel_clock_max / 1000, + intel_sdvo->caps.sdvo_num_inputs, + /* check currently supported outputs */ + intel_sdvo->caps.output_flags & + (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 | + SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_SVID0 | + SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB0) ? 'Y' : 'N', + intel_sdvo->caps.output_flags & + (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1 | + SDVO_OUTPUT_LVDS1) ? 'Y' : 'N'); return true; err_output: From 0128e89a9163e64fb71c2a5513d55fdb6d8df817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:11 +0200 Subject: [PATCH 019/295] drm/i915/color: Use per-device debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to drm_dbg_kms() in the LUT validation code so we see which device generated the debugs. Need to plumb i915 a bit deeper to make that happen. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_color.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index c5092b7e87d5..ca7112b32cb3 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2111,7 +2111,8 @@ static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state) return DISPLAY_INFO(i915)->color.degamma_lut_size; } -static int check_lut_size(const struct drm_property_blob *lut, int expected) +static int check_lut_size(struct drm_i915_private *i915, + const struct drm_property_blob *lut, int expected) { int len; @@ -2120,8 +2121,8 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) len = drm_color_lut_size(lut); if (len != expected) { - DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n", - len, expected); + drm_dbg_kms(&i915->drm, "Invalid LUT size; got %d, expected %d\n", + len, expected); return -EINVAL; } @@ -2146,8 +2147,8 @@ static int _check_luts(const struct intel_crtc_state *crtc_state, degamma_length = intel_degamma_lut_size(crtc_state); gamma_length = intel_gamma_lut_size(crtc_state); - if (check_lut_size(degamma_lut, degamma_length) || - check_lut_size(gamma_lut, gamma_length)) + if (check_lut_size(i915, degamma_lut, degamma_length) || + check_lut_size(i915, gamma_lut, gamma_length)) return -EINVAL; if (drm_color_lut_check(degamma_lut, degamma_tests) || From 5f67258c0872f1f0e0b1712b466b87bbe1b0c2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:12 +0200 Subject: [PATCH 020/295] drm/i915/fb: Use per-device debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to drm_dbg_kms() in the fb code so we see which device generated the debugs. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 0c0144eaa8fa..3ea6470d6d92 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1849,9 +1849,10 @@ static int intel_plane_check_stride(const struct intel_plane_state *plane_state) fb->modifier, rotation); if (stride > max_stride) { - DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n", - fb->base.id, stride, - plane->base.base.id, plane->base.name, max_stride); + drm_dbg_kms(plane->base.dev, + "[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n", + fb->base.id, stride, + plane->base.base.id, plane->base.name, max_stride); return -EINVAL; } From abe6af1627c73e7086bb90d750cf5c72e9fde9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:13 +0200 Subject: [PATCH 021/295] drm/i915/bios: Switch to kms debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VBT code is all about displays, so switch to UT_KMS debugs from UT_DRIVER. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 5f04e495fd27..63655b17714c 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2911,17 +2911,17 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return false; if (sizeof(struct vbt_header) > size) { - DRM_DEBUG_DRIVER("VBT header incomplete\n"); + DRM_DEBUG_KMS("VBT header incomplete\n"); return false; } if (memcmp(vbt->signature, "$VBT", 4)) { - DRM_DEBUG_DRIVER("VBT invalid signature\n"); + DRM_DEBUG_KMS("VBT invalid signature\n"); return false; } if (vbt->vbt_size > size) { - DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n"); + DRM_DEBUG_KMS("VBT incomplete (vbt_size overflows)\n"); return false; } @@ -2931,13 +2931,13 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) vbt->bdb_offset, sizeof(struct bdb_header), size)) { - DRM_DEBUG_DRIVER("BDB header incomplete\n"); + DRM_DEBUG_KMS("BDB header incomplete\n"); return false; } bdb = get_bdb_header(vbt); if (range_overflows_t(size_t, vbt->bdb_offset, bdb->bdb_size, size)) { - DRM_DEBUG_DRIVER("BDB incomplete\n"); + DRM_DEBUG_KMS("BDB incomplete\n"); return false; } From ff9bc20cd21c23a8fca0d5039e23142898383d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:14 +0200 Subject: [PATCH 022/295] drm/i915/bios: Use per-device debugs for VBT related stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to drm_dbg_kms() in the VBT code so we see which device generated the debugs. Need to plumb i915 a bit deeper to make that happen. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 73 ++++++++++--------- drivers/gpu/drm/i915/display/intel_bios.h | 3 +- drivers/gpu/drm/i915/display/intel_opregion.c | 6 +- 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 63655b17714c..fe52c06271ef 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1759,7 +1759,8 @@ parse_mipi_config(struct drm_i915_private *i915, /* Find the sequence block and size for the given panel. */ static const u8 * -find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, +find_panel_sequence_block(struct drm_i915_private *i915, + const struct bdb_mipi_sequence *sequence, u16 panel_id, u32 *seq_size) { u32 total = get_blocksize(sequence); @@ -1776,7 +1777,7 @@ find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index < total; i++) { if (index + header_size > total) { - DRM_ERROR("Invalid sequence block (header)\n"); + drm_err(&i915->drm, "Invalid sequence block (header)\n"); return NULL; } @@ -1789,7 +1790,7 @@ find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, index += header_size; if (index + current_size > total) { - DRM_ERROR("Invalid sequence block\n"); + drm_err(&i915->drm, "Invalid sequence block\n"); return NULL; } @@ -1801,12 +1802,13 @@ find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, index += current_size; } - DRM_ERROR("Sequence block detected but no valid configuration\n"); + drm_err(&i915->drm, "Sequence block detected but no valid configuration\n"); return NULL; } -static int goto_next_sequence(const u8 *data, int index, int total) +static int goto_next_sequence(struct drm_i915_private *i915, + const u8 *data, int index, int total) { u16 len; @@ -1836,7 +1838,7 @@ static int goto_next_sequence(const u8 *data, int index, int total) len = *(data + index + 6) + 7; break; default: - DRM_ERROR("Unknown operation byte\n"); + drm_err(&i915->drm, "Unknown operation byte\n"); return 0; } } @@ -1844,7 +1846,8 @@ static int goto_next_sequence(const u8 *data, int index, int total) return 0; } -static int goto_next_sequence_v3(const u8 *data, int index, int total) +static int goto_next_sequence_v3(struct drm_i915_private *i915, + const u8 *data, int index, int total) { int seq_end; u16 len; @@ -1855,7 +1858,7 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) * checking on the structure. */ if (total < 5) { - DRM_ERROR("Too small sequence size\n"); + drm_err(&i915->drm, "Too small sequence size\n"); return 0; } @@ -1872,7 +1875,7 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) seq_end = index + size_of_sequence; if (seq_end > total) { - DRM_ERROR("Invalid sequence size\n"); + drm_err(&i915->drm, "Invalid sequence size\n"); return 0; } @@ -1882,7 +1885,7 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) if (operation_byte == MIPI_SEQ_ELEM_END) { if (index != seq_end) { - DRM_ERROR("Invalid element structure\n"); + drm_err(&i915->drm, "Invalid element structure\n"); return 0; } return index; @@ -1904,8 +1907,8 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) case MIPI_SEQ_ELEM_PMIC: break; default: - DRM_ERROR("Unknown operation byte %u\n", - operation_byte); + drm_err(&i915->drm, "Unknown operation byte %u\n", + operation_byte); break; } } @@ -2030,7 +2033,7 @@ parse_mipi_sequence(struct drm_i915_private *i915, drm_dbg(&i915->drm, "Found MIPI sequence block v%u\n", sequence->version); - seq_data = find_panel_sequence_block(sequence, panel_type, &seq_size); + seq_data = find_panel_sequence_block(i915, sequence, panel_type, &seq_size); if (!seq_data) return; @@ -2058,9 +2061,9 @@ parse_mipi_sequence(struct drm_i915_private *i915, panel->vbt.dsi.sequence[seq_id] = data + index; if (sequence->version >= 3) - index = goto_next_sequence_v3(data, index, seq_size); + index = goto_next_sequence_v3(i915, data, index, seq_size); else - index = goto_next_sequence(data, index, seq_size); + index = goto_next_sequence(i915, data, index, seq_size); if (!index) { drm_err(&i915->drm, "Invalid sequence %u\n", seq_id); @@ -2135,12 +2138,13 @@ parse_compression_parameters(struct drm_i915_private *i915) } } -static u8 translate_iboost(u8 val) +static u8 translate_iboost(struct drm_i915_private *i915, u8 val) { static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */ if (val >= ARRAY_SIZE(mapping)) { - DRM_DEBUG_KMS("Unsupported I_boost value found in VBT (%d), display may not work properly\n", val); + drm_dbg_kms(&i915->drm, + "Unsupported I_boost value found in VBT (%d), display may not work properly\n", val); return 0; } return mapping[val]; @@ -2897,12 +2901,14 @@ static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt) /** * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT + * @i915: the device * @buf: pointer to a buffer to validate * @size: size of the buffer * * Returns true on valid VBT. */ -bool intel_bios_is_valid_vbt(const void *buf, size_t size) +bool intel_bios_is_valid_vbt(struct drm_i915_private *i915, + const void *buf, size_t size) { const struct vbt_header *vbt = buf; const struct bdb_header *bdb; @@ -2911,17 +2917,17 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return false; if (sizeof(struct vbt_header) > size) { - DRM_DEBUG_KMS("VBT header incomplete\n"); + drm_dbg_kms(&i915->drm, "VBT header incomplete\n"); return false; } if (memcmp(vbt->signature, "$VBT", 4)) { - DRM_DEBUG_KMS("VBT invalid signature\n"); + drm_dbg_kms(&i915->drm, "VBT invalid signature\n"); return false; } if (vbt->vbt_size > size) { - DRM_DEBUG_KMS("VBT incomplete (vbt_size overflows)\n"); + drm_dbg_kms(&i915->drm, "VBT incomplete (vbt_size overflows)\n"); return false; } @@ -2931,13 +2937,13 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) vbt->bdb_offset, sizeof(struct bdb_header), size)) { - DRM_DEBUG_KMS("BDB header incomplete\n"); + drm_dbg_kms(&i915->drm, "BDB header incomplete\n"); return false; } bdb = get_bdb_header(vbt); if (range_overflows_t(size_t, vbt->bdb_offset, bdb->bdb_size, size)) { - DRM_DEBUG_KMS("BDB incomplete\n"); + drm_dbg_kms(&i915->drm, "BDB incomplete\n"); return false; } @@ -2989,7 +2995,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) for (count = 0; count < vbt_size; count += 4) *(vbt + store++) = intel_spi_read(&i915->uncore, found + count); - if (!intel_bios_is_valid_vbt(vbt, vbt_size)) + if (!intel_bios_is_valid_vbt(i915, vbt, vbt_size)) goto err_free_vbt; drm_dbg_kms(&i915->drm, "Found valid VBT in SPI flash\n"); @@ -3046,7 +3052,7 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) memcpy_fromio(vbt, p, vbt_size); - if (!intel_bios_is_valid_vbt(vbt, vbt_size)) + if (!intel_bios_is_valid_vbt(i915, vbt, vbt_size)) goto err_free_vbt; pci_unmap_rom(pdev, oprom); @@ -3398,6 +3404,7 @@ static void fill_dsc(struct intel_crtc_state *crtc_state, struct dsc_compression_parameters_entry *dsc, int dsc_max_bpc) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; int bpc = 8; @@ -3411,8 +3418,8 @@ static void fill_dsc(struct intel_crtc_state *crtc_state, else if (dsc->support_8bpc && dsc_max_bpc >= 8) bpc = 8; else - DRM_DEBUG_KMS("VBT: Unsupported BPC %d for DCS\n", - dsc_max_bpc); + drm_dbg_kms(&i915->drm, "VBT: Unsupported BPC %d for DCS\n", + dsc_max_bpc); crtc_state->pipe_bpp = bpc * 3; @@ -3432,16 +3439,16 @@ static void fill_dsc(struct intel_crtc_state *crtc_state, } else { /* FIXME */ if (!(dsc->slices_per_line & BIT(0))) - DRM_DEBUG_KMS("VBT: Unsupported DSC slice count for DSI\n"); + drm_dbg_kms(&i915->drm, "VBT: Unsupported DSC slice count for DSI\n"); crtc_state->dsc.slice_count = 1; } if (crtc_state->hw.adjusted_mode.crtc_hdisplay % crtc_state->dsc.slice_count != 0) - DRM_DEBUG_KMS("VBT: DSC hdisplay %d not divisible by slice count %d\n", - crtc_state->hw.adjusted_mode.crtc_hdisplay, - crtc_state->dsc.slice_count); + drm_dbg_kms(&i915->drm, "VBT: DSC hdisplay %d not divisible by slice count %d\n", + crtc_state->hw.adjusted_mode.crtc_hdisplay, + crtc_state->dsc.slice_count); /* * The VBT rc_buffer_block_size and rc_buffer_size definitions @@ -3597,7 +3604,7 @@ int intel_bios_dp_boost_level(const struct intel_bios_encoder_data *devdata) if (!devdata || devdata->i915->display.vbt.version < 196 || !devdata->child.iboost) return 0; - return translate_iboost(devdata->child.dp_iboost_level); + return translate_iboost(devdata->i915, devdata->child.dp_iboost_level); } int intel_bios_hdmi_boost_level(const struct intel_bios_encoder_data *devdata) @@ -3605,7 +3612,7 @@ int intel_bios_hdmi_boost_level(const struct intel_bios_encoder_data *devdata) if (!devdata || devdata->i915->display.vbt.version < 196 || !devdata->child.iboost) return 0; - return translate_iboost(devdata->child.hdmi_iboost_level); + return translate_iboost(devdata->i915, devdata->child.hdmi_iboost_level); } int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata) diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 41bfb009d4b0..06a51be4afd8 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -242,7 +242,8 @@ void intel_bios_init_panel_late(struct drm_i915_private *dev_priv, const struct drm_edid *drm_edid); void intel_bios_fini_panel(struct intel_panel *panel); void intel_bios_driver_remove(struct drm_i915_private *dev_priv); -bool intel_bios_is_valid_vbt(const void *buf, size_t size); +bool intel_bios_is_valid_vbt(struct drm_i915_private *i915, + const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port); diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index f242bb320610..fcbb083318a7 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -887,7 +887,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv) return ret; } - if (intel_bios_is_valid_vbt(fw->data, fw->size)) { + if (intel_bios_is_valid_vbt(dev_priv, fw->data, fw->size)) { opregion->vbt_firmware = kmemdup(fw->data, fw->size, GFP_KERNEL); if (opregion->vbt_firmware) { drm_dbg_kms(&dev_priv->drm, @@ -1034,7 +1034,7 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) vbt = opregion->rvda; vbt_size = opregion->asle->rvds; - if (intel_bios_is_valid_vbt(vbt, vbt_size)) { + if (intel_bios_is_valid_vbt(dev_priv, vbt, vbt_size)) { drm_dbg_kms(&dev_priv->drm, "Found valid VBT in ACPI OpRegion (RVDA)\n"); opregion->vbt = vbt; @@ -1059,7 +1059,7 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) vbt_size = (mboxes & MBOX_ASLE_EXT) ? OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE; vbt_size -= OPREGION_VBT_OFFSET; - if (intel_bios_is_valid_vbt(vbt, vbt_size)) { + if (intel_bios_is_valid_vbt(dev_priv, vbt, vbt_size)) { drm_dbg_kms(&dev_priv->drm, "Found valid VBT in ACPI OpRegion (Mailbox #4)\n"); opregion->vbt = vbt; From 8c9e4f68b861dfe75650b75ac9e57e68f5f1850a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:15 +0200 Subject: [PATCH 023/295] drm/i915/hdcp: Use per-device debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to per-device debugs in the hdcp code so we see at least which device is involved. Should proably also print the connector/encoder/etc. in there, but left that for the future. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 3a595cd433d4..9dff4bdfeec8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -36,8 +36,10 @@ static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder) } } -static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) +static void intel_dp_hdcp_wait_for_cp_irq(struct intel_connector *connector, + int timeout) { + struct intel_hdcp *hdcp = &connector->hdcp; long ret; #define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count)) @@ -45,7 +47,8 @@ static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) msecs_to_jiffies(timeout)); if (!ret) - DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n"); + drm_dbg_kms(connector->base.dev, + "Timedout at waiting for CP_IRQ\n"); } static @@ -387,7 +390,8 @@ int hdcp2_detect_msg_availability(struct intel_connector *connector, *msg_ready = true; break; default: - DRM_ERROR("Unidentified msg_id: %d\n", msg_id); + drm_err(connector->base.dev, + "Unidentified msg_id: %d\n", msg_id); return -EINVAL; } @@ -421,7 +425,7 @@ intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector, * As we want to check the msg availability at timeout, Ignoring * the timeout at wait for CP_IRQ. */ - intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout); + intel_dp_hdcp_wait_for_cp_irq(connector, timeout); ret = hdcp2_detect_msg_availability(connector, msg_id, &msg_ready); if (!msg_ready) From 29d7a5b4d224d2f1cba4b21bf5db1a22c8568bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:16 +0200 Subject: [PATCH 024/295] drm/i915/wm: Pass the whole i915 to intel_get_cxsr_latency() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just pass the whole i915 to intel_get_cxsr_latency() instead of having each caller dig out bits and pieces. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 27 ++++++++++---------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 11ca9572e8b3..e6275ab14320 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -70,22 +70,21 @@ static const struct cxsr_latency cxsr_latency_table[] = { {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ }; -static const struct cxsr_latency *intel_get_cxsr_latency(bool is_desktop, - bool is_ddr3, - int fsb, - int mem) +static const struct cxsr_latency *intel_get_cxsr_latency(struct drm_i915_private *i915) { - const struct cxsr_latency *latency; int i; - if (fsb == 0 || mem == 0) + if (i915->fsb_freq == 0 || i915->mem_freq == 0) return NULL; for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { - latency = &cxsr_latency_table[i]; + const struct cxsr_latency *latency = &cxsr_latency_table[i]; + bool is_desktop = !IS_MOBILE(i915); + if (is_desktop == latency->is_desktop && - is_ddr3 == latency->is_ddr3 && - fsb == latency->fsb_freq && mem == latency->mem_freq) + i915->is_ddr3 == latency->is_ddr3 && + i915->fsb_freq == latency->fsb_freq && + i915->mem_freq == latency->mem_freq) return latency; } @@ -634,10 +633,7 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) u32 reg; unsigned int wm; - latency = intel_get_cxsr_latency(!IS_MOBILE(dev_priv), - dev_priv->is_ddr3, - dev_priv->fsb_freq, - dev_priv->mem_freq); + latency = intel_get_cxsr_latency(dev_priv); if (!latency) { drm_dbg_kms(&dev_priv->drm, "Unknown FSB/MEM found, disable CxSR\n"); @@ -4016,10 +4012,7 @@ void i9xx_wm_init(struct drm_i915_private *dev_priv) g4x_setup_wm_latency(dev_priv); dev_priv->display.funcs.wm = &g4x_wm_funcs; } else if (IS_PINEVIEW(dev_priv)) { - if (!intel_get_cxsr_latency(!IS_MOBILE(dev_priv), - dev_priv->is_ddr3, - dev_priv->fsb_freq, - dev_priv->mem_freq)) { + if (!intel_get_cxsr_latency(dev_priv)) { drm_info(&dev_priv->drm, "failed to find known CxSR latency " "(found ddr%s fsb freq %d, mem freq %d), " From 167712d82aadb317a5e912eac5abae00a9c78994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:17 +0200 Subject: [PATCH 025/295] drm/i915/wm: Use per-device debugs in pre-ilk wm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to drm_dbg_kms() in the pre-ilk wm code so we see which device generated the debugs. Need to plumb i915 a bit deeper to make that happen. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-11-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index e6275ab14320..46877fd260d5 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -88,7 +88,7 @@ static const struct cxsr_latency *intel_get_cxsr_latency(struct drm_i915_private return latency; } - DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); + drm_dbg_kms(&i915->drm, "Unknown FSB/MEM found, disable CxSR\n"); return NULL; } @@ -524,6 +524,7 @@ static unsigned int intel_wm_method2(unsigned int pixel_rate, /** * intel_calculate_wm - calculate watermark level + * @i915: the device * @pixel_rate: pixel clock * @wm: chip FIFO params * @fifo_size: size of the FIFO buffer @@ -541,7 +542,8 @@ static unsigned int intel_wm_method2(unsigned int pixel_rate, * past the watermark point. If the FIFO drains completely, a FIFO underrun * will occur, and a display engine hang could result. */ -static unsigned int intel_calculate_wm(int pixel_rate, +static unsigned int intel_calculate_wm(struct drm_i915_private *i915, + int pixel_rate, const struct intel_watermark_params *wm, int fifo_size, int cpp, unsigned int latency_ns) @@ -558,10 +560,10 @@ static unsigned int intel_calculate_wm(int pixel_rate, latency_ns / 100); entries = DIV_ROUND_UP(entries, wm->cacheline_size) + wm->guard_size; - DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries); + drm_dbg_kms(&i915->drm, "FIFO entries required for mode: %d\n", entries); wm_size = fifo_size - entries; - DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); + drm_dbg_kms(&i915->drm, "FIFO watermark level: %d\n", wm_size); /* Don't promote wm_size to unsigned... */ if (wm_size > wm->max_wm) @@ -649,7 +651,8 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) int cpp = fb->format->cpp[0]; /* Display SR */ - wm = intel_calculate_wm(pixel_rate, &pnv_display_wm, + wm = intel_calculate_wm(dev_priv, pixel_rate, + &pnv_display_wm, pnv_display_wm.fifo_size, cpp, latency->display_sr); reg = intel_uncore_read(&dev_priv->uncore, DSPFW1); @@ -659,20 +662,23 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "DSPFW1 register is %x\n", reg); /* cursor SR */ - wm = intel_calculate_wm(pixel_rate, &pnv_cursor_wm, + wm = intel_calculate_wm(dev_priv, pixel_rate, + &pnv_cursor_wm, pnv_display_wm.fifo_size, 4, latency->cursor_sr); intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_CURSOR_SR_MASK, FW_WM(wm, CURSOR_SR)); /* Display HPLL off SR */ - wm = intel_calculate_wm(pixel_rate, &pnv_display_hplloff_wm, + wm = intel_calculate_wm(dev_priv, pixel_rate, + &pnv_display_hplloff_wm, pnv_display_hplloff_wm.fifo_size, cpp, latency->display_hpll_disable); intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_HPLL_SR_MASK, FW_WM(wm, HPLL_SR)); /* cursor HPLL off SR */ - wm = intel_calculate_wm(pixel_rate, &pnv_cursor_hplloff_wm, + wm = intel_calculate_wm(dev_priv, pixel_rate, + &pnv_cursor_hplloff_wm, pnv_display_hplloff_wm.fifo_size, 4, latency->cursor_hpll_disable); reg = intel_uncore_read(&dev_priv->uncore, DSPFW3); @@ -2120,7 +2126,7 @@ static void i9xx_update_wm(struct drm_i915_private *dev_priv) else cpp = fb->format->cpp[0]; - planea_wm = intel_calculate_wm(crtc->config->pixel_rate, + planea_wm = intel_calculate_wm(dev_priv, crtc->config->pixel_rate, wm_info, fifo_size, cpp, pessimal_latency_ns); } else { @@ -2147,7 +2153,7 @@ static void i9xx_update_wm(struct drm_i915_private *dev_priv) else cpp = fb->format->cpp[0]; - planeb_wm = intel_calculate_wm(crtc->config->pixel_rate, + planeb_wm = intel_calculate_wm(dev_priv, crtc->config->pixel_rate, wm_info, fifo_size, cpp, pessimal_latency_ns); } else { @@ -2241,7 +2247,7 @@ static void i845_update_wm(struct drm_i915_private *dev_priv) if (crtc == NULL) return; - planea_wm = intel_calculate_wm(crtc->config->pixel_rate, + planea_wm = intel_calculate_wm(dev_priv, crtc->config->pixel_rate, &i845_wm_info, i845_get_fifo_size(dev_priv, PLANE_A), 4, pessimal_latency_ns); From 1db5efe51f9427b212e608d2cf072c9d9d780440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:18 +0200 Subject: [PATCH 026/295] drm/i915/wm: Use per-device debugs ilk wm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to drm_dbg_kms() in the ilk wm code so we see which device generated the debugs. Need to plumb i915 a bit deeper to make that happen. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-12-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 46877fd260d5..628e7192ebc9 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -2533,7 +2533,8 @@ static void ilk_compute_wm_reg_maximums(const struct drm_i915_private *dev_priv, max->fbc = ilk_fbc_wm_reg_max(dev_priv); } -static bool ilk_validate_wm_level(int level, +static bool ilk_validate_wm_level(struct drm_i915_private *i915, + int level, const struct ilk_wm_maximums *max, struct intel_wm_level *result) { @@ -2556,14 +2557,17 @@ static bool ilk_validate_wm_level(int level, */ if (level == 0 && !result->enable) { if (result->pri_val > max->pri) - DRM_DEBUG_KMS("Primary WM%d too large %u (max %u)\n", - level, result->pri_val, max->pri); + drm_dbg_kms(&i915->drm, + "Primary WM%d too large %u (max %u)\n", + level, result->pri_val, max->pri); if (result->spr_val > max->spr) - DRM_DEBUG_KMS("Sprite WM%d too large %u (max %u)\n", - level, result->spr_val, max->spr); + drm_dbg_kms(&i915->drm, + "Sprite WM%d too large %u (max %u)\n", + level, result->spr_val, max->spr); if (result->cur_val > max->cur) - DRM_DEBUG_KMS("Cursor WM%d too large %u (max %u)\n", - level, result->cur_val, max->cur); + drm_dbg_kms(&i915->drm, + "Cursor WM%d too large %u (max %u)\n", + level, result->cur_val, max->cur); result->pri_val = min_t(u32, result->pri_val, max->pri); result->spr_val = min_t(u32, result->spr_val, max->spr); @@ -2763,7 +2767,7 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) } } -static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv, +static bool ilk_validate_pipe_wm(struct drm_i915_private *dev_priv, struct intel_pipe_wm *pipe_wm) { /* LP0 watermark maximums depend on this pipe alone */ @@ -2778,7 +2782,7 @@ static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv, ilk_compute_wm_maximums(dev_priv, 0, &config, INTEL_DDB_PART_1_2, &max); /* At least LP0 must be valid */ - if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) { + if (!ilk_validate_wm_level(dev_priv, 0, &max, &pipe_wm->wm[0])) { drm_dbg_kms(&dev_priv->drm, "LP0 watermark invalid\n"); return false; } @@ -2847,7 +2851,7 @@ static int ilk_compute_pipe_wm(struct intel_atomic_state *state, * register maximums since such watermarks are * always invalid. */ - if (!ilk_validate_wm_level(level, &max, wm)) { + if (!ilk_validate_wm_level(dev_priv, level, &max, wm)) { memset(wm, 0, sizeof(*wm)); break; } @@ -2978,7 +2982,7 @@ static void ilk_wm_merge(struct drm_i915_private *dev_priv, if (level > last_enabled_level) wm->enable = false; - else if (!ilk_validate_wm_level(level, max, wm)) + else if (!ilk_validate_wm_level(dev_priv, level, max, wm)) /* make sure all following levels get disabled */ last_enabled_level = level - 1; From 8dc0e7dfc5aaf63b8d615fe968e6db36de5b2dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:19 +0200 Subject: [PATCH 027/295] drm/i915/dvo/ns2501: Nuke pointless casts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dvo 'dev_priv' is void* so no need for an explicit cast. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-13-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_ns2501.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index a724a8755673..32fd4aa27598 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -551,7 +551,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, const struct drm_display_mode *adjusted_mode) { const struct ns2501_configuration *conf; - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); + struct ns2501_priv *ns = dvo->dev_priv; int mode_idx, i; DRM_DEBUG_KMS @@ -655,7 +655,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo) /* set the NS2501 power state */ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) { - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); + struct ns2501_priv *ns = dvo->dev_priv; DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable); From cd1f0d3df26ad5abbf15b3d1f26a5a6417091b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Feb 2024 17:17:20 +0200 Subject: [PATCH 028/295] drm/i915/dvo: Use sizeof(*variable) instead of sizeof(type) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer sizeof(*variable) to sizeof(type) to make it a bit harder to screw things up. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240208151720.7866-14-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_ch7017.c | 2 +- drivers/gpu/drm/i915/display/dvo_ch7xxx.c | 2 +- drivers/gpu/drm/i915/display/dvo_ivch.c | 2 +- drivers/gpu/drm/i915/display/dvo_ns2501.c | 2 +- drivers/gpu/drm/i915/display/dvo_sil164.c | 2 +- drivers/gpu/drm/i915/display/dvo_tfp410.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/dvo_ch7017.c b/drivers/gpu/drm/i915/display/dvo_ch7017.c index 0589994dde11..d0c3880d7f80 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7017.c @@ -205,7 +205,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, const char *str; u8 val; - priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (priv == NULL) return false; diff --git a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c index 6d948520e9a6..2e8e85da5a40 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c @@ -216,7 +216,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, u8 vendor, device; char *name, *devid; - ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL); + ch7xxx = kzalloc(sizeof(*ch7xxx), GFP_KERNEL); if (ch7xxx == NULL) return false; diff --git a/drivers/gpu/drm/i915/display/dvo_ivch.c b/drivers/gpu/drm/i915/display/dvo_ivch.c index f43d8c610d3f..eef72bb3b767 100644 --- a/drivers/gpu/drm/i915/display/dvo_ivch.c +++ b/drivers/gpu/drm/i915/display/dvo_ivch.c @@ -267,7 +267,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, u16 temp; int i; - priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (priv == NULL) return false; diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index 32fd4aa27598..1df212fb000e 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -476,7 +476,7 @@ static bool ns2501_init(struct intel_dvo_device *dvo, struct ns2501_priv *ns; unsigned char ch; - ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL); + ns = kzalloc(sizeof(*ns), GFP_KERNEL); if (ns == NULL) return false; diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index 4acc8ce29c0b..6c461024c8e3 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -141,7 +141,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, struct sil164_priv *sil; unsigned char ch; - sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL); + sil = kzalloc(sizeof(*sil), GFP_KERNEL); if (sil == NULL) return false; diff --git a/drivers/gpu/drm/i915/display/dvo_tfp410.c b/drivers/gpu/drm/i915/display/dvo_tfp410.c index 009d65b0f3e9..0939e097f4f9 100644 --- a/drivers/gpu/drm/i915/display/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/display/dvo_tfp410.c @@ -173,7 +173,7 @@ static bool tfp410_init(struct intel_dvo_device *dvo, struct tfp410_priv *tfp; int id; - tfp = kzalloc(sizeof(struct tfp410_priv), GFP_KERNEL); + tfp = kzalloc(sizeof(*tfp), GFP_KERNEL); if (tfp == NULL) return false; From ec97f371895f83fb0c123187d26d19bdb927621f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Oct 2023 23:57:23 +0300 Subject: [PATCH 029/295] drm/msm/dsi: do not store internal bridge pointer Since the driver was switched to devm_drm_bridge_add(), there is no need anymore to store the created bridge instance in struct msm_dsi. Drop this field and pass data directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/561693/ Link: https://lore.kernel.org/r/20231009205727.2781802-2-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/dsi/dsi.c | 8 +++++--- drivers/gpu/drm/msm/dsi/dsi.h | 7 ++----- drivers/gpu/drm/msm/dsi/dsi_manager.c | 19 ++++++++----------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index c6bd7bf15605..0edc1da256ec 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -216,6 +216,7 @@ void __exit msm_dsi_unregister(void) int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoder) { + struct drm_bridge *bridge; int ret; msm_dsi->dev = dev; @@ -237,13 +238,14 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, msm_dsi->encoder = encoder; - ret = msm_dsi_manager_bridge_init(msm_dsi); - if (ret) { + bridge = msm_dsi_manager_bridge_init(msm_dsi); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); return ret; } - ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id); + ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id, bridge); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 28379b1af63f..84c0b04e41e1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -35,9 +35,6 @@ struct msm_dsi { struct drm_device *dev; struct platform_device *pdev; - /* internal dsi bridge attached to MDP interface */ - struct drm_bridge *bridge; - struct mipi_dsi_host *host; struct msm_dsi_phy *phy; @@ -56,8 +53,8 @@ struct msm_dsi { }; /* dsi manager */ -int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); -int msm_dsi_manager_ext_bridge_init(u8 id); +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); +int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 896f369fdd53..f5285faefc61 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -466,9 +466,9 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { }; /* initialize bridge */ -int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) { - struct drm_bridge *bridge = NULL; + struct drm_bridge *bridge; struct dsi_bridge *dsi_bridge; struct drm_encoder *encoder; int ret; @@ -476,7 +476,7 @@ int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, sizeof(*dsi_bridge), GFP_KERNEL); if (!dsi_bridge) - return -ENOMEM; + return ERR_PTR(-ENOMEM); dsi_bridge->id = msm_dsi->id; @@ -487,26 +487,23 @@ int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge); if (ret) - return ret; + return ERR_PTR(ret); ret = drm_bridge_attach(encoder, bridge, NULL, 0); if (ret) - return ret; + return ERR_PTR(ret); - msm_dsi->bridge = bridge; - - return 0; + return bridge; } -int msm_dsi_manager_ext_bridge_init(u8 id) +int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_device *dev = msm_dsi->dev; struct drm_encoder *encoder; - struct drm_bridge *int_bridge, *ext_bridge; + struct drm_bridge *ext_bridge; int ret; - int_bridge = msm_dsi->bridge; ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev, msm_dsi->pdev->dev.of_node, 1, 0); if (IS_ERR(ext_bridge)) From 891a8d83c11d453348683ee7d45dc65035a075c2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Oct 2023 23:57:24 +0300 Subject: [PATCH 030/295] drm/msm/dsi: drop msm_dsi_device_connected() function Since the commit 8f59ee9a570c ("drm/msm/dsi: Adjust probe order") the DSI hosts are not bound through the component framework if the DSI driver wasn't attached to the DSI device connected to this host. Afterwards, if there is no bridge (including the panel bridge) created for the DSI device then devm_drm_of_get_bridge() will return an error, also making msm_dsi_manager_ext_bridge_init() and thus DSI modesetting init fail. This way there can be no 'unconnected' MSM DSI bridges. Remove the msm_dsi_device_connected() function. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/561692/ Link: https://lore.kernel.org/r/20231009205727.2781802-3-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/dsi/dsi.h | 6 ------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 5 ----- 2 files changed, 11 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 84c0b04e41e1..3f778d9efba0 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -61,12 +61,6 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); void msm_dsi_manager_tpg_enable(void); -/* msm dsi */ -static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) -{ - return msm_dsi->external_bridge; -} - /* dsi host */ struct msm_dsi_host; int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index f5285faefc61..4b49911ec43a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -305,8 +305,6 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) int ret; DBG("id=%d", id); - if (!msm_dsi_device_connected(msm_dsi)) - return; /* Do nothing with the host if it is slave-DSI in case of bonded DSI */ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) @@ -364,9 +362,6 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) DBG("id=%d", id); - if (!msm_dsi_device_connected(msm_dsi)) - return; - /* * Do nothing with the host if it is slave-DSI in case of bonded DSI. * It is safe to call dsi_mgr_phy_disable() here because a single PHY From 51c139615b33c0bab595d7faeb2d7b925f3fff04 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Oct 2023 23:57:25 +0300 Subject: [PATCH 031/295] drm/msm/dsi: stop calling set_split_display Since the commit 8b03ad30e314 ("drm/msm/dsi: Use one connector for dual DSI mode"), the second DSI host in the bonded pair will not be associated with the encoder and will not get the bridges, thus making condition in msm_dsi_manager_set_split_display() always false. Technically that change broke bonded DSI support in the MDP5 driver. But since nobody complained in the last 5.5 years, it seems that nobody cares enough. Drop the msm_dsi_manager_set_split_display() completely and stop calling the set_split_display() KMS callback. Also remove the msm_dsi::external_bridge field which was only used by the mentioned function. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/561695/ Link: https://lore.kernel.org/r/20231009205727.2781802-4-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/dsi/dsi.h | 5 ---- drivers/gpu/drm/msm/dsi/dsi_manager.c | 35 --------------------------- 2 files changed, 40 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 3f778d9efba0..de34e7caa5c8 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -38,11 +38,6 @@ struct msm_dsi { struct mipi_dsi_host *host; struct msm_dsi_phy *phy; - /* - * external_bridge connected to dsi bridge output - */ - struct drm_bridge *external_bridge; - struct device *phy_dev; bool phy_enabled; diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4b49911ec43a..0cf4e301ed2c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -198,36 +198,6 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge) return dsi_bridge->id; } -static void msm_dsi_manager_set_split_display(u8 id) -{ - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); - struct msm_drm_private *priv = msm_dsi->dev->dev_private; - struct msm_kms *kms = priv->kms; - struct msm_dsi *master_dsi, *slave_dsi; - - if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) { - master_dsi = other_dsi; - slave_dsi = msm_dsi; - } else { - master_dsi = msm_dsi; - slave_dsi = other_dsi; - } - - if (!msm_dsi->external_bridge || !IS_BONDED_DSI()) - return; - - /* - * Set split display info to kms once bonded DSI panel is connected to - * both hosts. - */ - if (other_dsi && other_dsi->external_bridge && kms->funcs->set_split_display) { - kms->funcs->set_split_display(kms, master_dsi->encoder, - slave_dsi->encoder, - msm_dsi_is_cmd_mode(msm_dsi)); - } -} - static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge) { int id = dsi_mgr_bridge_get_id(bridge); @@ -504,8 +474,6 @@ int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge) if (IS_ERR(ext_bridge)) return PTR_ERR(ext_bridge); - msm_dsi->external_bridge = ext_bridge; - encoder = msm_dsi->encoder; /* @@ -538,9 +506,6 @@ int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge) return ret; } - /* The pipeline is ready, ping encoders if necessary */ - msm_dsi_manager_set_split_display(id); - return 0; } From 89cdd4dee1f04a418ce86d62927e6bf6502d20fe Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Oct 2023 23:57:26 +0300 Subject: [PATCH 032/295] drm/msm/dsi: remove msm_dsi::encoder There is no need anymore to stop the drm_encoder instance in struct msm_dsi. Remove corresponding field. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/561697/ Link: https://lore.kernel.org/r/20231009205727.2781802-5-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/dsi/dsi.c | 4 +--- drivers/gpu/drm/msm/dsi/dsi.h | 6 ++---- drivers/gpu/drm/msm/dsi/dsi_manager.c | 8 +++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 0edc1da256ec..37c4c07005fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -236,9 +236,7 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, return 0; } - msm_dsi->encoder = encoder; - - bridge = msm_dsi_manager_bridge_init(msm_dsi); + bridge = msm_dsi_manager_bridge_init(msm_dsi, encoder); if (IS_ERR(bridge)) { ret = PTR_ERR(bridge); DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index de34e7caa5c8..2ad9a842c678 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -41,14 +41,12 @@ struct msm_dsi { struct device *phy_dev; bool phy_enabled; - /* the encoder we are hooked to (outside of dsi block) */ - struct drm_encoder *encoder; - int id; }; /* dsi manager */ -struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi, + struct drm_encoder *encoder); int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 0cf4e301ed2c..af2a287cb3bd 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -431,11 +431,11 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { }; /* initialize bridge */ -struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi, + struct drm_encoder *encoder) { struct drm_bridge *bridge; struct dsi_bridge *dsi_bridge; - struct drm_encoder *encoder; int ret; dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, @@ -445,8 +445,6 @@ struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) dsi_bridge->id = msm_dsi->id; - encoder = msm_dsi->encoder; - bridge = &dsi_bridge->base; bridge->funcs = &dsi_mgr_bridge_funcs; @@ -474,7 +472,7 @@ int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge) if (IS_ERR(ext_bridge)) return PTR_ERR(ext_bridge); - encoder = msm_dsi->encoder; + encoder = int_bridge->encoder; /* * Try first to create the bridge without it creating its own From df3c7899946c4627a559171c5fc61948d175dc76 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 9 Oct 2023 23:57:27 +0300 Subject: [PATCH 033/295] drm/msm/mdp5: drop split display support The MSM DSI driver has dropped support for calling mdp_kms_funcs::set_split_display() callback. Drop corresponding callback from the mdp5 driver together with the rest of the infrastructure. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/561698/ Link: https://lore.kernel.org/r/20231009205727.2781802-6-dmitry.baryshkov@linaro.org --- .../gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c | 42 ------------------- drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 42 ------------------- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 14 ------- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h | 9 ---- drivers/gpu/drm/msm/msm_kms.h | 4 -- 5 files changed, 111 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c index a640af22eafc..e5662412db9b 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c @@ -158,46 +158,4 @@ void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) mdp5_cmd_enc->enabled = true; } - -int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, - struct drm_encoder *slave_encoder) -{ - struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder); - struct mdp5_kms *mdp5_kms; - struct device *dev; - int intf_num; - u32 data = 0; - - if (!encoder || !slave_encoder) - return -EINVAL; - - mdp5_kms = get_kms(encoder); - intf_num = mdp5_cmd_enc->intf->num; - - /* Switch slave encoder's trigger MUX, to use the master's - * start signal for the slave encoder - */ - if (intf_num == 1) - data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX; - else if (intf_num == 2) - data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX; - else - return -EINVAL; - - /* Smart Panel, Sync mode */ - data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL; - - dev = &mdp5_kms->pdev->dev; - - /* Make sure clocks are on when connectors calling this function. */ - pm_runtime_get_sync(dev); - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data); - - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, - MDP5_SPLIT_DPL_LOWER_SMART_PANEL); - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); - pm_runtime_put_sync(dev); - - return 0; -} #endif /* CONFIG_DRM_MSM_DSI */ diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c index 8db97083e14d..eaba3b2d73b5 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c @@ -263,48 +263,6 @@ u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder) return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf)); } -int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder, - struct drm_encoder *slave_encoder) -{ - struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); - struct mdp5_encoder *mdp5_slave_enc = to_mdp5_encoder(slave_encoder); - struct mdp5_kms *mdp5_kms; - struct device *dev; - int intf_num; - u32 data = 0; - - if (!encoder || !slave_encoder) - return -EINVAL; - - mdp5_kms = get_kms(encoder); - intf_num = mdp5_encoder->intf->num; - - /* Switch slave encoder's TimingGen Sync mode, - * to use the master's enable signal for the slave encoder. - */ - if (intf_num == 1) - data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC; - else if (intf_num == 2) - data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC; - else - return -EINVAL; - - dev = &mdp5_kms->pdev->dev; - /* Make sure clocks are on when connectors calling this function. */ - pm_runtime_get_sync(dev); - - /* Dumb Panel, Sync mode */ - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0); - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data); - mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); - - mdp5_ctl_pair(mdp5_encoder->ctl, mdp5_slave_enc->ctl, true); - - pm_runtime_put_sync(dev); - - return 0; -} - void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 0827634664ae..25279c724fe0 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -190,19 +190,6 @@ static void mdp5_complete_commit(struct msm_kms *kms, unsigned crtc_mask) mdp5_smp_complete_commit(mdp5_kms->smp, &global_state->smp); } -static int mdp5_set_split_display(struct msm_kms *kms, - struct drm_encoder *encoder, - struct drm_encoder *slave_encoder, - bool is_cmd_mode) -{ - if (is_cmd_mode) - return mdp5_cmd_encoder_set_split_display(encoder, - slave_encoder); - else - return mdp5_vid_encoder_set_split_display(encoder, - slave_encoder); -} - static void mdp5_destroy(struct mdp5_kms *mdp5_kms); static void mdp5_kms_destroy(struct msm_kms *kms) @@ -268,7 +255,6 @@ static const struct mdp_kms_funcs kms_funcs = { .wait_flush = mdp5_wait_flush, .complete_commit = mdp5_complete_commit, .get_format = mdp_get_format, - .set_split_display = mdp5_set_split_display, .destroy = mdp5_kms_destroy, #ifdef CONFIG_DEBUG_FS .debugfs_init = mdp5_kms_debugfs_init, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h index 29bf11f08601..ee68e9913f8c 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h @@ -291,8 +291,6 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, struct mdp5_interface *intf, struct mdp5_ctl *ctl); -int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder, - struct drm_encoder *slave_encoder); void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode); int mdp5_encoder_get_linecount(struct drm_encoder *encoder); u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder); @@ -303,8 +301,6 @@ void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode); void mdp5_cmd_encoder_disable(struct drm_encoder *encoder); void mdp5_cmd_encoder_enable(struct drm_encoder *encoder); -int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, - struct drm_encoder *slave_encoder); #else static inline void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, @@ -317,11 +313,6 @@ static inline void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) static inline void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) { } -static inline int mdp5_cmd_encoder_set_split_display( - struct drm_encoder *encoder, struct drm_encoder *slave_encoder) -{ - return -EINVAL; -} #endif #endif /* __MDP5_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 44aa435d68ce..0641f6111b93 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -105,10 +105,6 @@ struct msm_kms_funcs { /* misc: */ long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, struct drm_encoder *encoder); - int (*set_split_display)(struct msm_kms *kms, - struct drm_encoder *encoder, - struct drm_encoder *slave_encoder, - bool is_cmd_mode); /* cleanup: */ void (*destroy)(struct msm_kms *kms); From 858ddb64f1fffb95c411564bc10f79be5e8cc30d Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Thu, 14 Dec 2023 10:56:12 -0800 Subject: [PATCH 034/295] drm/msm/dpu: improve DSC allocation At DSC V1.1 DCE (Display Compression Engine) contains a DSC encoder. However, at DSC V1.2 DCE consists of two DSC encoders, one has an odd index and another one has an even index. Each encoder can work independently. But only two DSC encoders from same DCE can be paired to work together to support DSC merge mode at DSC V1.2. For DSC V1.1 two consecutive DSC encoders (start with even index) have to be paired to support DSC merge mode. In addition, the DSC with even index have to be mapped to even PINGPONG index and DSC with odd index have to be mapped to odd PINGPONG index at its data path in regardless of DSC V1.1 or V1.2. This patch improves DSC allocation mechanism with consideration of those factors. Changes in V6: -- rename _dpu_rm_reserve_dsc_single to _dpu_rm_dsc_alloc -- rename _dpu_rm_reserve_dsc_pair to _dpu_rm_dsc_alloc_pair -- pass global_state to _dpu_rm_pingpong_next_index() -- remove pp_max -- fix for loop condition check at _dpu_rm_dsc_alloc() Changes in V5: -- delete dsc_id[] -- update to global_state->dsc_to_enc_id[] directly -- replace ndx with idx -- fix indentation at function declaration -- only one for loop at _dpu_rm_reserve_dsc_single() Changes in V4: -- rework commit message -- use reserved_by_other() -- add _dpu_rm_pingpong_next_index() -- revise _dpu_rm_pingpong_dsc_check() Changes in V3: -- add dpu_rm_pingpong_dsc_check() -- for pair allocation use i += 2 at for loop Changes in V2: -- split _dpu_rm_reserve_dsc() into _dpu_rm_reserve_dsc_single() and _dpu_rm_reserve_dsc_pair() Fixes: f2803ee91a41 ("drm/msm/disp/dpu1: Add DSC support in RM") Signed-off-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/572144/ Link: https://lore.kernel.org/r/1702580172-30606-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 154 ++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 724537ab776d..cb5ce3c62a22 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -409,29 +409,153 @@ static int _dpu_rm_reserve_ctls( return 0; } +static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state, + int start, + uint32_t enc_id) +{ + int i; + + for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) { + if (global_state->pingpong_to_enc_id[i] == enc_id) + return i; + } + + return -ENAVAIL; +} + +static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx) +{ + /* + * DSC with even index must be used with the PINGPONG with even index + * DSC with odd index must be used with the PINGPONG with odd index + */ + if ((dsc_idx & 0x01) != (pp_idx & 0x01)) + return -ENAVAIL; + + return 0; +} + +static int _dpu_rm_dsc_alloc(struct dpu_rm *rm, + struct dpu_global_state *global_state, + uint32_t enc_id, + const struct msm_display_topology *top) +{ + int num_dsc = 0; + int pp_idx = 0; + int dsc_idx; + int ret; + + for (dsc_idx = 0; dsc_idx < ARRAY_SIZE(rm->dsc_blks) && + num_dsc < top->num_dsc; dsc_idx++) { + if (!rm->dsc_blks[dsc_idx]) + continue; + + if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id)) + continue; + + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); + if (pp_idx < 0) + return -ENAVAIL; + + ret = _dpu_rm_pingpong_dsc_check(dsc_idx, pp_idx); + if (ret) + return -ENAVAIL; + + global_state->dsc_to_enc_id[dsc_idx] = enc_id; + num_dsc++; + pp_idx++; + } + + if (num_dsc < top->num_dsc) { + DPU_ERROR("DSC allocation failed num_dsc=%d required=%d\n", + num_dsc, top->num_dsc); + return -ENAVAIL; + } + + return 0; +} + +static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm, + struct dpu_global_state *global_state, + uint32_t enc_id, + const struct msm_display_topology *top) +{ + int num_dsc = 0; + int dsc_idx, pp_idx = 0; + int ret; + + /* only start from even dsc index */ + for (dsc_idx = 0; dsc_idx < ARRAY_SIZE(rm->dsc_blks) && + num_dsc < top->num_dsc; dsc_idx += 2) { + if (!rm->dsc_blks[dsc_idx] || + !rm->dsc_blks[dsc_idx + 1]) + continue; + + /* consective dsc index to be paired */ + if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) || + reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id)) + continue; + + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id); + if (pp_idx < 0) + return -ENAVAIL; + + ret = _dpu_rm_pingpong_dsc_check(dsc_idx, pp_idx); + if (ret) { + pp_idx = 0; + continue; + } + + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id); + if (pp_idx < 0) + return -ENAVAIL; + + ret = _dpu_rm_pingpong_dsc_check(dsc_idx + 1, pp_idx); + if (ret) { + pp_idx = 0; + continue; + } + + global_state->dsc_to_enc_id[dsc_idx] = enc_id; + global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id; + num_dsc += 2; + pp_idx++; /* start for next pair */ + } + + if (num_dsc < top->num_dsc) { + DPU_ERROR("DSC allocation failed num_dsc=%d required=%d\n", + num_dsc, top->num_dsc); + return -ENAVAIL; + } + + return 0; +} + static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, struct dpu_global_state *global_state, struct drm_encoder *enc, const struct msm_display_topology *top) { - int num_dsc = top->num_dsc; - int i; + uint32_t enc_id = enc->base.id; - /* check if DSC required are allocated or not */ - for (i = 0; i < num_dsc; i++) { - if (!rm->dsc_blks[i]) { - DPU_ERROR("DSC %d does not exist\n", i); - return -EIO; - } + if (!top->num_dsc || !top->num_intf) + return 0; - if (global_state->dsc_to_enc_id[i]) { - DPU_ERROR("DSC %d is already allocated\n", i); - return -EIO; - } - } + /* + * Facts: + * 1) no pingpong split (two layer mixers shared one pingpong) + * 2) DSC pair starts from even index, such as index(0,1), (2,3), etc + * 3) even PINGPONG connects to even DSC + * 4) odd PINGPONG connects to odd DSC + * 5) pair: encoder +--> pp_idx_0 --> dsc_idx_0 + * +--> pp_idx_1 --> dsc_idx_1 + */ - for (i = 0; i < num_dsc; i++) - global_state->dsc_to_enc_id[i] = enc->base.id; + /* num_dsc should be either 1, 2 or 4 */ + if (top->num_dsc > top->num_intf) /* merge mode */ + return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top); + else + return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top); return 0; } From 72b557c15956edaa42d98f9dec6521c9899f7cc5 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Thu, 11 Jan 2024 09:14:15 -0800 Subject: [PATCH 035/295] drm/msm/dp: remove mdss_dp_test_bit_depth_to_bpc() mdss_dp_test_bit_depth_to_bpc() can be replace by mdss_dp_test_bit_depth_to_bpp() / 3. Hence remove it. Signed-off-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/574279/ Link: https://lore.kernel.org/r/1704993255-12753-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_debug.c | 2 +- drivers/gpu/drm/msm/dp/dp_link.h | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 6c281dc095b9..26f800afe5a2 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -101,7 +101,7 @@ static int dp_test_data_show(struct seq_file *m, void *data) seq_printf(m, "vdisplay: %d\n", debug->link->test_video.test_v_height); seq_printf(m, "bpc: %u\n", - dp_link_bit_depth_to_bpc(bpc)); + dp_link_bit_depth_to_bpp(bpc) / 3); } else { seq_puts(m, "0"); } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 9dd4dd926530..83da170bc56b 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -112,29 +112,6 @@ static inline u32 dp_link_bit_depth_to_bpp(u32 tbd) } } -/** - * dp_test_bit_depth_to_bpc() - convert test bit depth to bpc - * @tbd: test bit depth - * - * Returns the bits per comp (bpc) to be used corresponding to the - * bit depth value. This function assumes that bit depth has - * already been validated. - */ -static inline u32 dp_link_bit_depth_to_bpc(u32 tbd) -{ - switch (tbd) { - case DP_TEST_BIT_DEPTH_6: - return 6; - case DP_TEST_BIT_DEPTH_8: - return 8; - case DP_TEST_BIT_DEPTH_10: - return 10; - case DP_TEST_BIT_DEPTH_UNKNOWN: - default: - return 0; - } -} - void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link); u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp); int dp_link_process_request(struct dp_link *dp_link); From db36595c688963bf1479ebc15f1b31d08339a9b3 Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sun, 21 Jan 2024 20:41:00 +0100 Subject: [PATCH 036/295] dt-bindings: dsi-controller-main: Document missing msm8976 compatible When all dsi-ctrl compats were added msm8976 was missed, include it too. Signed-off-by: Adam Skladowski Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/575288/ Link: https://lore.kernel.org/r/20240121194221.13513-3-a39.skl@gmail.com Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index 4219936eda5a..1fa28e976559 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -19,6 +19,7 @@ properties: - qcom,msm8916-dsi-ctrl - qcom,msm8953-dsi-ctrl - qcom,msm8974-dsi-ctrl + - qcom,msm8976-dsi-ctrl - qcom,msm8996-dsi-ctrl - qcom,msm8998-dsi-ctrl - qcom,qcm2290-dsi-ctrl @@ -248,6 +249,7 @@ allOf: contains: enum: - qcom,msm8953-dsi-ctrl + - qcom,msm8976-dsi-ctrl then: properties: clocks: From 3b63880de42bd3cb79c2a99949135a8f2441c088 Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sun, 21 Jan 2024 20:41:01 +0100 Subject: [PATCH 037/295] dt-bindings: msm: qcom, mdss: Include ommited fam-b compatible During conversion 28nm-hpm-fam-b compat got lost, add it. Signed-off-by: Adam Skladowski Fixes: f7d46c5efee2 ("dt-bindings: display/msm: split qcom, mdss bindings") Acked-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/575290/ Link: https://lore.kernel.org/r/20240121194221.13513-4-a39.skl@gmail.com Signed-off-by: Dmitry Baryshkov --- Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml index 0999ea07f47b..e4576546bf0d 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml @@ -127,6 +127,7 @@ patternProperties: - qcom,dsi-phy-20nm - qcom,dsi-phy-28nm-8226 - qcom,dsi-phy-28nm-hpm + - qcom,dsi-phy-28nm-hpm-fam-b - qcom,dsi-phy-28nm-lp - qcom,hdmi-phy-8084 - qcom,hdmi-phy-8660 From 08c5b691ee54165d3ce2ad7ca3007a180bc33a43 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:20 +0200 Subject: [PATCH 038/295] drm/msm/dp: drop unused parser definitions Drop several unused and obsolete definitions from the dp_parser module. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576110/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-1-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_parser.h | 46 ------------------------------ 1 file changed, 46 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 1f068626d445..90a2cdbbe344 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -12,7 +12,6 @@ #include "msm_drv.h" -#define DP_LABEL "MDSS DP DISPLAY" #define DP_MAX_PIXEL_CLK_KHZ 675000 #define DP_MAX_NUM_DP_LANES 4 #define DP_LINK_RATE_HBR2 540000 /* kbytes */ @@ -21,7 +20,6 @@ enum dp_pm_type { DP_CORE_PM, DP_CTRL_PM, DP_STREAM_PM, - DP_PHY_PM, DP_MAX_PM }; @@ -43,28 +41,10 @@ static inline const char *dp_parser_pm_name(enum dp_pm_type module) case DP_CORE_PM: return "DP_CORE_PM"; case DP_CTRL_PM: return "DP_CTRL_PM"; case DP_STREAM_PM: return "DP_STREAM_PM"; - case DP_PHY_PM: return "DP_PHY_PM"; default: return "???"; } } -/** - * struct dp_display_data - display related device tree data. - * - * @ctrl_node: referece to controller device - * @phy_node: reference to phy device - * @is_active: is the controller currently active - * @name: name of the display - * @display_type: type of the display - */ -struct dp_display_data { - struct device_node *ctrl_node; - struct device_node *phy_node; - bool is_active; - const char *name; - const char *display_type; -}; - /** * struct dp_ctrl_resource - controller's IO related data * @@ -77,28 +57,6 @@ struct dp_io { union phy_configure_opts phy_opts; }; -/** - * struct dp_pinctrl - DP's pin control - * - * @pin: pin-controller's instance - * @state_active: active state pin control - * @state_hpd_active: hpd active state pin control - * @state_suspend: suspend state pin control - */ -struct dp_pinctrl { - struct pinctrl *pin; - struct pinctrl_state *state_active; - struct pinctrl_state *state_hpd_active; - struct pinctrl_state *state_suspend; -}; - -/* Regulators for DP devices */ -struct dp_reg_entry { - char name[32]; - int enable_load; - int disable_load; -}; - struct dss_module_power { unsigned int num_clk; struct clk_bulk_data *clocks; @@ -109,16 +67,12 @@ struct dss_module_power { * * @pdev: platform data of the client * @mp: gpio, regulator and clock related data - * @pinctrl: pin-control related data - * @disp_data: controller's display related data * @parse: function to be called by client to parse device tree. */ struct dp_parser { struct platform_device *pdev; struct dss_module_power mp[DP_MAX_PM]; - struct dp_pinctrl pinctrl; struct dp_io io; - struct dp_display_data disp_data; u32 max_dp_lanes; u32 max_dp_link_rate; struct drm_bridge *next_bridge; From 9aeb50ea0ea96ad9577666f4aafa9ed241947c21 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:21 +0200 Subject: [PATCH 039/295] drm/msm/dp: drop unused fields from dp_power_private Drop unused and obsolete fields from struct dp_power_private. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576100/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-2-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_power.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index c4843dd69f47..b095a5b47c8b 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -16,9 +16,6 @@ struct dp_power_private { struct dp_parser *parser; struct device *dev; struct drm_device *drm_dev; - struct clk *link_clk_src; - struct clk *pixel_provider; - struct clk *link_provider; struct dp_power dp_power; }; From 31a01db14b90fda9ca55ba9178d75e45911efea2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:22 +0200 Subject: [PATCH 040/295] drm/msm/dp: parse DT from dp_parser_get It makes little sense to split the submodule get and actual DT parsing. Call dp_parser_parse() directly from dp_parser_get(), so that the parser data is fully initialised once it is returned to the caller. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576101/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-3-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_display.c | 6 ------ drivers/gpu/drm/msm/dp/dp_parser.c | 8 +++++++- drivers/gpu/drm/msm/dp/dp_parser.h | 3 --- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c8e1bbebdffe..fd6dd2dec369 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1267,12 +1267,6 @@ static int dp_display_probe(struct platform_device *pdev) return -EPROBE_DEFER; } - rc = dp->parser->parse(dp->parser); - if (rc) { - DRM_ERROR("device tree parsing failed\n"); - goto err; - } - rc = dp_power_client_init(dp->power); if (rc) { DRM_ERROR("Power client create failed\n"); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 7032dcc8842b..2d9d126c119b 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -315,13 +315,19 @@ static int dp_parser_parse(struct dp_parser *parser) struct dp_parser *dp_parser_get(struct platform_device *pdev) { struct dp_parser *parser; + int ret; parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL); if (!parser) return ERR_PTR(-ENOMEM); - parser->parse = dp_parser_parse; parser->pdev = pdev; + ret = dp_parser_parse(parser); + if (ret) { + dev_err(&pdev->dev, "device tree parsing failed\n"); + return ERR_PTR(ret); + } + return parser; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 90a2cdbbe344..4ccc432b4142 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -67,7 +67,6 @@ struct dss_module_power { * * @pdev: platform data of the client * @mp: gpio, regulator and clock related data - * @parse: function to be called by client to parse device tree. */ struct dp_parser { struct platform_device *pdev; @@ -76,8 +75,6 @@ struct dp_parser { u32 max_dp_lanes; u32 max_dp_link_rate; struct drm_bridge *next_bridge; - - int (*parse)(struct dp_parser *parser); }; /** From 47103b582412bcc6adad356bfab3c3ef637105af Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:23 +0200 Subject: [PATCH 041/295] drm/msm/dp: inline dp_power_(de)init In preparation to cleanup of the dp_power module, inline dp_power_init() and dp_power_deinit() functions, which are now just turning the clocks on and off. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576113/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-4-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_power.c | 10 ---------- drivers/gpu/drm/msm/dp/dp_power.h | 21 --------------------- 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fd6dd2dec369..a2c5c7f8841c 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -435,7 +435,7 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_power_init(dp->power); + dp_power_clk_enable(dp->power, DP_CORE_PM, true); dp_ctrl_reset_irq_ctrl(dp->ctrl, true); dp_aux_init(dp->aux); dp->core_initialized = true; @@ -449,7 +449,7 @@ static void dp_display_host_deinit(struct dp_display_private *dp) dp_ctrl_reset_irq_ctrl(dp->ctrl, false); dp_aux_deinit(dp->aux); - dp_power_deinit(dp->power); + dp_power_clk_enable(dp->power, DP_CORE_PM, false); dp->core_initialized = false; } diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index b095a5b47c8b..f49e3aede308 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -152,16 +152,6 @@ int dp_power_client_init(struct dp_power *dp_power) return dp_power_clk_init(power); } -int dp_power_init(struct dp_power *dp_power) -{ - return dp_power_clk_enable(dp_power, DP_CORE_PM, true); -} - -int dp_power_deinit(struct dp_power *dp_power) -{ - return dp_power_clk_enable(dp_power, DP_CORE_PM, false); -} - struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser) { struct dp_power_private *power; diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h index 55ada51edb57..eb836b5aa24a 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ b/drivers/gpu/drm/msm/dp/dp_power.h @@ -22,27 +22,6 @@ struct dp_power { bool stream_clks_on; }; -/** - * dp_power_init() - enable power supplies for display controller - * - * @power: instance of power module - * return: 0 if success or error if failure. - * - * This API will turn on the regulators and configures gpio's - * aux/hpd. - */ -int dp_power_init(struct dp_power *power); - -/** - * dp_power_deinit() - turn off regulators and gpios. - * - * @power: instance of power module - * return: 0 for success - * - * This API turns off power and regulators. - */ -int dp_power_deinit(struct dp_power *power); - /** * dp_power_clk_status() - display controller clocks status * From 17cb153f81dff9da61b0a51eeeb71ec3cc260ca7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:24 +0200 Subject: [PATCH 042/295] drm/msm/dp: fold dp_power into dp_ctrl module The dp_power submodule is limited to handling the clocks only following previous cleanups. Fold it into the dp_ctrl submodule, removing one unnecessary level of indirection. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576104/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-5-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/dp/dp_ctrl.c | 150 +++++++++++++++++++++--- drivers/gpu/drm/msm/dp/dp_ctrl.h | 6 +- drivers/gpu/drm/msm/dp/dp_display.c | 24 +--- drivers/gpu/drm/msm/dp/dp_power.c | 170 ---------------------------- drivers/gpu/drm/msm/dp/dp_power.h | 74 ------------ 6 files changed, 142 insertions(+), 283 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dp/dp_power.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_power.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index b1173128b5b9..8dbdf3fba69e 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -128,7 +128,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_link.o \ dp/dp_panel.o \ dp/dp_parser.o \ - dp/dp_power.o \ dp/dp_audio.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index fb588fde298a..b501a06e3ec6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -76,13 +76,16 @@ struct dp_ctrl_private { struct drm_dp_aux *aux; struct dp_panel *panel; struct dp_link *link; - struct dp_power *power; struct dp_parser *parser; struct dp_catalog *catalog; struct completion idle_comp; struct completion psr_op_comp; struct completion video_comp; + + bool core_clks_on; + bool link_clks_on; + bool stream_clks_on; }; static int dp_aux_link_configure(struct drm_dp_aux *aux, @@ -1333,6 +1336,83 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, name, rate); } +int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, + enum dp_pm_type pm_type, bool enable) +{ + struct dp_ctrl_private *ctrl; + struct dss_module_power *mp; + int ret = 0; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + if (pm_type != DP_CORE_PM && + pm_type != DP_CTRL_PM && + pm_type != DP_STREAM_PM) { + DRM_ERROR("unsupported ctrl module: %s\n", + dp_parser_pm_name(pm_type)); + return -EINVAL; + } + + if (enable) { + if (pm_type == DP_CORE_PM && ctrl->core_clks_on) { + drm_dbg_dp(ctrl->drm_dev, + "core clks already enabled\n"); + return 0; + } + + if (pm_type == DP_CTRL_PM && ctrl->link_clks_on) { + drm_dbg_dp(ctrl->drm_dev, + "links clks already enabled\n"); + return 0; + } + + if (pm_type == DP_STREAM_PM && ctrl->stream_clks_on) { + drm_dbg_dp(ctrl->drm_dev, + "pixel clks already enabled\n"); + return 0; + } + + if ((pm_type == DP_CTRL_PM) && (!ctrl->core_clks_on)) { + drm_dbg_dp(ctrl->drm_dev, + "Enable core clks before link clks\n"); + mp = &ctrl->parser->mp[DP_CORE_PM]; + + ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); + if (ret) + return ret; + + ctrl->core_clks_on = true; + } + } + + mp = &ctrl->parser->mp[pm_type]; + if (enable) { + ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); + if (ret) + return ret; + } else { + clk_bulk_disable_unprepare(mp->num_clk, mp->clocks); + } + + if (pm_type == DP_CORE_PM) + ctrl->core_clks_on = enable; + else if (pm_type == DP_STREAM_PM) + ctrl->stream_clks_on = enable; + else + ctrl->link_clks_on = enable; + + drm_dbg_dp(ctrl->drm_dev, "%s clocks for %s\n", + enable ? "enable" : "disable", + dp_parser_pm_name(pm_type)); + drm_dbg_dp(ctrl->drm_dev, + "stream_clks:%s link_clks:%s core_clks:%s\n", + ctrl->stream_clks_on ? "on" : "off", + ctrl->link_clks_on ? "on" : "off", + ctrl->core_clks_on ? "on" : "off"); + + return 0; +} + static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) { int ret = 0; @@ -1349,7 +1429,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) phy_power_on(phy); dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, true); if (ret) DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); @@ -1497,7 +1577,7 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) * link maintenance. */ dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); return ret; @@ -1529,7 +1609,7 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_reset(ctrl->catalog); dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } @@ -1651,7 +1731,7 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", pixel_rate * 1000); - ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, true); if (ret) { DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); return ret; @@ -1747,7 +1827,7 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) rate = ctrl->panel->link_info.rate; pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - dp_power_clk_enable(ctrl->power, DP_CORE_PM, true); + dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CORE_PM, true); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { drm_dbg_dp(ctrl->drm_dev, @@ -1880,7 +1960,11 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, pixel_rate); - if (!dp_power_clk_status(ctrl->power, DP_CTRL_PM)) { /* link clk is off */ + drm_dbg_dp(ctrl->drm_dev, + "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", + ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); + + if (!ctrl->link_clks_on) { /* link clk is off */ ret = dp_ctrl_enable_mainlink_clocks(ctrl); if (ret) { DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); @@ -1890,7 +1974,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", pixel_rate * 1000); - ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, true); if (ret) { DRM_ERROR("Unable to start pixel clocks. ret=%d\n", ret); goto end; @@ -1946,8 +2030,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); - if (dp_power_clk_status(ctrl->power, DP_STREAM_PM)) { - ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, false); + if (ctrl->stream_clks_on) { + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, false); if (ret) { DRM_ERROR("Failed to disable pclk. ret=%d\n", ret); return ret; @@ -1955,7 +2039,7 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) } dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); return ret; @@ -1985,7 +2069,7 @@ int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } @@ -2019,12 +2103,12 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_reset(ctrl->catalog); - ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, false); if (ret) DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret); dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } @@ -2081,9 +2165,38 @@ irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl) return ret; } +static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl_private; + int rc = 0; + struct dss_module_power *core, *ctrl, *stream; + struct device *dev; + + ctrl_private = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + dev = ctrl_private->dev; + + core = &ctrl_private->parser->mp[DP_CORE_PM]; + ctrl = &ctrl_private->parser->mp[DP_CTRL_PM]; + stream = &ctrl_private->parser->mp[DP_STREAM_PM]; + + rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); + if (rc) + return rc; + + rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks); + if (rc) + return -ENODEV; + + rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks); + if (rc) + return -ENODEV; + + return 0; +} + struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_panel *panel, struct drm_dp_aux *aux, - struct dp_power *power, struct dp_catalog *catalog, + struct dp_catalog *catalog, struct dp_parser *parser) { struct dp_ctrl_private *ctrl; @@ -2120,11 +2233,16 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, /* in parameters */ ctrl->parser = parser; ctrl->panel = panel; - ctrl->power = power; ctrl->aux = aux; ctrl->link = link; ctrl->catalog = catalog; ctrl->dev = dev; + ret = dp_ctrl_clk_init(&ctrl->dp_ctrl); + if (ret) { + dev_err(dev, "failed to init clocks\n"); + return ERR_PTR(ret); + } + return &ctrl->dp_ctrl; } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index b2c27d3532bf..85da5a7e5307 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -10,7 +10,6 @@ #include "dp_panel.h" #include "dp_link.h" #include "dp_parser.h" -#include "dp_power.h" #include "dp_catalog.h" struct dp_ctrl { @@ -28,7 +27,7 @@ irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl); void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl); struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_panel *panel, struct drm_dp_aux *aux, - struct dp_power *power, struct dp_catalog *catalog, + struct dp_catalog *catalog, struct dp_parser *parser); void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable); @@ -39,4 +38,7 @@ void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl); void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enable); void dp_ctrl_config_psr(struct dp_ctrl *dp_ctrl); +int dp_ctrl_clk_enable(struct dp_ctrl *ctrl, enum dp_pm_type pm_type, + bool enable); + #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index a2c5c7f8841c..fe348279fee7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -16,13 +16,12 @@ #include "msm_drv.h" #include "msm_kms.h" #include "dp_parser.h" -#include "dp_power.h" +#include "dp_ctrl.h" #include "dp_catalog.h" #include "dp_aux.h" #include "dp_reg.h" #include "dp_link.h" #include "dp_panel.h" -#include "dp_ctrl.h" #include "dp_display.h" #include "dp_drm.h" #include "dp_audio.h" @@ -90,7 +89,6 @@ struct dp_display_private { struct dentry *root; struct dp_parser *parser; - struct dp_power *power; struct dp_catalog *catalog; struct drm_dp_aux *aux; struct dp_link *link; @@ -435,7 +433,7 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_power_clk_enable(dp->power, DP_CORE_PM, true); + dp_ctrl_clk_enable(dp->ctrl, DP_CORE_PM, true); dp_ctrl_reset_irq_ctrl(dp->ctrl, true); dp_aux_init(dp->aux); dp->core_initialized = true; @@ -449,7 +447,7 @@ static void dp_display_host_deinit(struct dp_display_private *dp) dp_ctrl_reset_irq_ctrl(dp->ctrl, false); dp_aux_deinit(dp->aux); - dp_power_clk_enable(dp->power, DP_CORE_PM, false); + dp_ctrl_clk_enable(dp->ctrl, DP_CORE_PM, false); dp->core_initialized = false; } @@ -732,14 +730,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } - dp->power = dp_power_get(dev, dp->parser); - if (IS_ERR(dp->power)) { - rc = PTR_ERR(dp->power); - DRM_ERROR("failed to initialize power, rc = %d\n", rc); - dp->power = NULL; - goto error; - } - dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); @@ -769,7 +759,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, - dp->power, dp->catalog, dp->parser); + dp->catalog, dp->parser); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); @@ -1267,12 +1257,6 @@ static int dp_display_probe(struct platform_device *pdev) return -EPROBE_DEFER; } - rc = dp_power_client_init(dp->power); - if (rc) { - DRM_ERROR("Power client create failed\n"); - goto err; - } - /* setup event q */ mutex_init(&dp->event_mutex); init_waitqueue_head(&dp->event_q); diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c deleted file mode 100644 index f49e3aede308..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ /dev/null @@ -1,170 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include -#include "dp_power.h" -#include "msm_drv.h" - -struct dp_power_private { - struct dp_parser *parser; - struct device *dev; - struct drm_device *drm_dev; - - struct dp_power dp_power; -}; - -static int dp_power_clk_init(struct dp_power_private *power) -{ - int rc = 0; - struct dss_module_power *core, *ctrl, *stream; - struct device *dev = power->dev; - - core = &power->parser->mp[DP_CORE_PM]; - ctrl = &power->parser->mp[DP_CTRL_PM]; - stream = &power->parser->mp[DP_STREAM_PM]; - - rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); - if (rc) - return rc; - - rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks); - if (rc) - return -ENODEV; - - rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks); - if (rc) - return -ENODEV; - - return 0; -} - -int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) -{ - struct dp_power_private *power; - - power = container_of(dp_power, struct dp_power_private, dp_power); - - drm_dbg_dp(power->drm_dev, - "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", - dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on); - - if (pm_type == DP_CORE_PM) - return dp_power->core_clks_on; - - if (pm_type == DP_CTRL_PM) - return dp_power->link_clks_on; - - if (pm_type == DP_STREAM_PM) - return dp_power->stream_clks_on; - - return 0; -} - -int dp_power_clk_enable(struct dp_power *dp_power, - enum dp_pm_type pm_type, bool enable) -{ - int rc = 0; - struct dp_power_private *power; - struct dss_module_power *mp; - - power = container_of(dp_power, struct dp_power_private, dp_power); - - if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM && - pm_type != DP_STREAM_PM) { - DRM_ERROR("unsupported power module: %s\n", - dp_parser_pm_name(pm_type)); - return -EINVAL; - } - - if (enable) { - if (pm_type == DP_CORE_PM && dp_power->core_clks_on) { - drm_dbg_dp(power->drm_dev, - "core clks already enabled\n"); - return 0; - } - - if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) { - drm_dbg_dp(power->drm_dev, - "links clks already enabled\n"); - return 0; - } - - if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) { - drm_dbg_dp(power->drm_dev, - "pixel clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) { - drm_dbg_dp(power->drm_dev, - "Enable core clks before link clks\n"); - mp = &power->parser->mp[DP_CORE_PM]; - - rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); - if (rc) - return rc; - - dp_power->core_clks_on = true; - } - } - - mp = &power->parser->mp[pm_type]; - if (enable) { - rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); - if (rc) - return rc; - } else { - clk_bulk_disable_unprepare(mp->num_clk, mp->clocks); - } - - if (pm_type == DP_CORE_PM) - dp_power->core_clks_on = enable; - else if (pm_type == DP_STREAM_PM) - dp_power->stream_clks_on = enable; - else - dp_power->link_clks_on = enable; - - drm_dbg_dp(power->drm_dev, "%s clocks for %s\n", - enable ? "enable" : "disable", - dp_parser_pm_name(pm_type)); - drm_dbg_dp(power->drm_dev, - "strem_clks:%s link_clks:%s core_clks:%s\n", - dp_power->stream_clks_on ? "on" : "off", - dp_power->link_clks_on ? "on" : "off", - dp_power->core_clks_on ? "on" : "off"); - - return 0; -} - -int dp_power_client_init(struct dp_power *dp_power) -{ - struct dp_power_private *power; - - power = container_of(dp_power, struct dp_power_private, dp_power); - - return dp_power_clk_init(power); -} - -struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser) -{ - struct dp_power_private *power; - struct dp_power *dp_power; - - power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); - if (!power) - return ERR_PTR(-ENOMEM); - - power->parser = parser; - power->dev = dev; - - dp_power = &power->dp_power; - - return dp_power; -} diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h deleted file mode 100644 index eb836b5aa24a..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_POWER_H_ -#define _DP_POWER_H_ - -#include "dp_parser.h" - -/** - * sruct dp_power - DisplayPort's power related data - * - * @init: initializes the regulators/core clocks/GPIOs/pinctrl - * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl - * @clk_enable: enable/disable the DP clocks - * @set_pixel_clk_parent: set the parent of DP pixel clock - */ -struct dp_power { - bool core_clks_on; - bool link_clks_on; - bool stream_clks_on; -}; - -/** - * dp_power_clk_status() - display controller clocks status - * - * @power: instance of power module - * @pm_type: type of pm, core/ctrl/phy - * return: status of power clocks - * - * This API return status of DP clocks - */ - -int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type); - -/** - * dp_power_clk_enable() - enable display controller clocks - * - * @power: instance of power module - * @pm_type: type of pm, core/ctrl/phy - * @enable: enables or disables - * return: pointer to allocated power module data - * - * This API will call setrate and enable for DP clocks - */ - -int dp_power_clk_enable(struct dp_power *power, enum dp_pm_type pm_type, - bool enable); - -/** - * dp_power_client_init() - initialize clock and regulator modules - * - * @power: instance of power module - * return: 0 for success, error for failure. - * - * This API will configure the DisplayPort's clocks and regulator - * modules. - */ -int dp_power_client_init(struct dp_power *power); - -/** - * dp_power_get() - configure and get the DisplayPort power module data - * - * @parser: instance of parser module - * return: pointer to allocated power module data - * - * This API will configure the DisplayPort's power module and provides - * methods to be called by the client to configure the power related - * modules. - */ -struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser); - -#endif /* _DP_POWER_H_ */ From 9bd0946d5ca1fa5bee11ae718e8e429bc83e1058 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:25 +0200 Subject: [PATCH 043/295] drm/msm/dp: simplify stream clocks handling There is only a single DP_STREAM_PM clock, stream_pixel. Instead of using a separate dss_module_power instance for this single clock, handle this clock directly. This allows us to drop several wrapping functions. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576102/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-6-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 91 +++++++++++++----------------- drivers/gpu/drm/msm/dp/dp_parser.c | 41 +++----------- drivers/gpu/drm/msm/dp/dp_parser.h | 2 - 3 files changed, 47 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index b501a06e3ec6..4a741f5b7b5a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -79,6 +79,8 @@ struct dp_ctrl_private { struct dp_parser *parser; struct dp_catalog *catalog; + struct clk *pixel_clk; + struct completion idle_comp; struct completion psr_op_comp; struct completion video_comp; @@ -1315,27 +1317,6 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, return ret; } -static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, - enum dp_pm_type module, char *name, unsigned long rate) -{ - u32 num = ctrl->parser->mp[module].num_clk; - struct clk_bulk_data *cfg = ctrl->parser->mp[module].clocks; - - while (num && strcmp(cfg->id, name)) { - num--; - cfg++; - } - - drm_dbg_dp(ctrl->drm_dev, "setting rate=%lu on clk=%s\n", - rate, name); - - if (num) - clk_set_rate(cfg->clk, rate); - else - DRM_ERROR("%s clock doesn't exit to set rate %lu\n", - name, rate); -} - int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, enum dp_pm_type pm_type, bool enable) { @@ -1346,8 +1327,7 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (pm_type != DP_CORE_PM && - pm_type != DP_CTRL_PM && - pm_type != DP_STREAM_PM) { + pm_type != DP_CTRL_PM) { DRM_ERROR("unsupported ctrl module: %s\n", dp_parser_pm_name(pm_type)); return -EINVAL; @@ -1366,12 +1346,6 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, return 0; } - if (pm_type == DP_STREAM_PM && ctrl->stream_clks_on) { - drm_dbg_dp(ctrl->drm_dev, - "pixel clks already enabled\n"); - return 0; - } - if ((pm_type == DP_CTRL_PM) && (!ctrl->core_clks_on)) { drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n"); @@ -1396,8 +1370,6 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, if (pm_type == DP_CORE_PM) ctrl->core_clks_on = enable; - else if (pm_type == DP_STREAM_PM) - ctrl->stream_clks_on = enable; else ctrl->link_clks_on = enable; @@ -1729,14 +1701,23 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) } pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", pixel_rate * 1000); - - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, true); + ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); return ret; } + if (ctrl->stream_clks_on) { + drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); + } else { + ret = clk_prepare_enable(ctrl->pixel_clk); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + return ret; + } + ctrl->stream_clks_on = true; + } + dp_ctrl_send_phy_test_pattern(ctrl); return 0; @@ -1972,14 +1953,23 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) } } - dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", pixel_rate * 1000); - - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, true); + ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); if (ret) { - DRM_ERROR("Unable to start pixel clocks. ret=%d\n", ret); + DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); goto end; } + if (ctrl->stream_clks_on) { + drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); + } else { + ret = clk_prepare_enable(ctrl->pixel_clk); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + goto end; + } + ctrl->stream_clks_on = true; + } + if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl)) dp_ctrl_link_retrain(ctrl); @@ -2031,11 +2021,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); if (ctrl->stream_clks_on) { - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, false); - if (ret) { - DRM_ERROR("Failed to disable pclk. ret=%d\n", ret); - return ret; - } + clk_disable_unprepare(ctrl->pixel_clk); + ctrl->stream_clks_on = false; } dev_pm_opp_set_rate(ctrl->dev, 0); @@ -2103,9 +2090,10 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_reset(ctrl->catalog); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_STREAM_PM, false); - if (ret) - DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret); + if (ctrl->stream_clks_on) { + clk_disable_unprepare(ctrl->pixel_clk); + ctrl->stream_clks_on = false; + } dev_pm_opp_set_rate(ctrl->dev, 0); ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); @@ -2169,7 +2157,7 @@ static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl_private; int rc = 0; - struct dss_module_power *core, *ctrl, *stream; + struct dss_module_power *core, *ctrl; struct device *dev; ctrl_private = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); @@ -2177,7 +2165,6 @@ static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) core = &ctrl_private->parser->mp[DP_CORE_PM]; ctrl = &ctrl_private->parser->mp[DP_CTRL_PM]; - stream = &ctrl_private->parser->mp[DP_STREAM_PM]; rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); if (rc) @@ -2187,9 +2174,9 @@ static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) if (rc) return -ENODEV; - rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks); - if (rc) - return -ENODEV; + ctrl_private->pixel_clk = devm_clk_get(dev, "stream_pixel"); + if (IS_ERR(ctrl_private->pixel_clk)) + return PTR_ERR(ctrl_private->pixel_clk); return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 2d9d126c119b..fe2b75f7555a 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -150,12 +150,11 @@ static inline bool dp_parser_check_prefix(const char *clk_prefix, static int dp_parser_init_clk_data(struct dp_parser *parser) { int num_clk, i, rc; - int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; + int core_clk_count = 0, ctrl_clk_count = 0; const char *clk_name; struct device *dev = &parser->pdev->dev; struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; - struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; num_clk = of_property_count_strings(dev->of_node, "clock-names"); if (num_clk <= 0) { @@ -174,9 +173,6 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) if (dp_parser_check_prefix("ctrl", clk_name)) ctrl_clk_count++; - - if (dp_parser_check_prefix("stream", clk_name)) - stream_clk_count++; } /* Initialize the CORE power module */ @@ -207,47 +203,30 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) return -ENOMEM; } - /* Initialize the STREAM power module */ - if (stream_clk_count == 0) { - DRM_ERROR("no stream (pixel) clocks are defined\n"); - return -EINVAL; - } - - stream_power->num_clk = stream_clk_count; - stream_power->clocks = devm_kcalloc(dev, - stream_power->num_clk, sizeof(struct clk_bulk_data), - GFP_KERNEL); - if (!stream_power->clocks) { - stream_power->num_clk = 0; - return -ENOMEM; - } - - return 0; + return num_clk; } static int dp_parser_clock(struct dp_parser *parser) { int rc = 0, i = 0; int num_clk = 0; - int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0; - int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; + int core_clk_index = 0, ctrl_clk_index = 0; + int core_clk_count = 0, ctrl_clk_count = 0; const char *clk_name; struct device *dev = &parser->pdev->dev; struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; - struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; rc = dp_parser_init_clk_data(parser); - if (rc) { + if (rc < 0) { DRM_ERROR("failed to initialize power data %d\n", rc); - return -EINVAL; + return rc; } + num_clk = rc; + core_clk_count = core_power->num_clk; ctrl_clk_count = ctrl_power->num_clk; - stream_clk_count = stream_power->num_clk; - - num_clk = core_clk_count + ctrl_clk_count + stream_clk_count; for (i = 0; i < num_clk; i++) { rc = of_property_read_string_index(dev->of_node, "clock-names", @@ -260,10 +239,6 @@ static int dp_parser_clock(struct dp_parser *parser) core_clk_index < core_clk_count) { core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); core_clk_index++; - } else if (dp_parser_check_prefix("stream", clk_name) && - stream_clk_index < stream_clk_count) { - stream_power->clocks[stream_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); - stream_clk_index++; } else if (dp_parser_check_prefix("ctrl", clk_name) && ctrl_clk_index < ctrl_clk_count) { ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 4ccc432b4142..c6fe26602e07 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -19,7 +19,6 @@ enum dp_pm_type { DP_CORE_PM, DP_CTRL_PM, - DP_STREAM_PM, DP_MAX_PM }; @@ -40,7 +39,6 @@ static inline const char *dp_parser_pm_name(enum dp_pm_type module) switch (module) { case DP_CORE_PM: return "DP_CORE_PM"; case DP_CTRL_PM: return "DP_CTRL_PM"; - case DP_STREAM_PM: return "DP_STREAM_PM"; default: return "???"; } } From 77d0243a3313f1be6e93a7fdccc131aa007dcd5a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:26 +0200 Subject: [PATCH 044/295] drm/msm/dp: stop parsing clock names from DT All supported platforms use the same clocks configuration. Instead of parsing names from DT in a pretty complex manner, use the static configuration. If at some point newer (or older) platforms have different clock configuration, this clock config can be moved to the device data. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576115/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-7-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 75 ++++++++++++++----- drivers/gpu/drm/msm/dp/dp_ctrl.h | 6 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 112 ----------------------------- drivers/gpu/drm/msm/dp/dp_parser.h | 22 ------ 4 files changed, 64 insertions(+), 151 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 4a741f5b7b5a..c207e4d7f0da 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -69,6 +69,11 @@ struct dp_vc_tu_mapping_table { u8 tu_size_minus1; }; +struct dss_module_power { + unsigned int num_clk; + struct clk_bulk_data *clocks; +}; + struct dp_ctrl_private { struct dp_ctrl dp_ctrl; struct drm_device *drm_dev; @@ -79,6 +84,7 @@ struct dp_ctrl_private { struct dp_parser *parser; struct dp_catalog *catalog; + struct dss_module_power mp[DP_MAX_PM]; struct clk *pixel_clk; struct completion idle_comp; @@ -90,6 +96,15 @@ struct dp_ctrl_private { bool stream_clks_on; }; +static inline const char *dp_pm_name(enum dp_pm_type module) +{ + switch (module) { + case DP_CORE_PM: return "DP_CORE_PM"; + case DP_CTRL_PM: return "DP_CTRL_PM"; + default: return "???"; + } +} + static int dp_aux_link_configure(struct drm_dp_aux *aux, struct dp_link_info *link) { @@ -1329,7 +1344,7 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM) { DRM_ERROR("unsupported ctrl module: %s\n", - dp_parser_pm_name(pm_type)); + dp_pm_name(pm_type)); return -EINVAL; } @@ -1349,7 +1364,7 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, if ((pm_type == DP_CTRL_PM) && (!ctrl->core_clks_on)) { drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n"); - mp = &ctrl->parser->mp[DP_CORE_PM]; + mp = &ctrl->mp[DP_CORE_PM]; ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); if (ret) @@ -1359,7 +1374,7 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, } } - mp = &ctrl->parser->mp[pm_type]; + mp = &ctrl->mp[pm_type]; if (enable) { ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); if (ret) @@ -1375,7 +1390,7 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, drm_dbg_dp(ctrl->drm_dev, "%s clocks for %s\n", enable ? "enable" : "disable", - dp_parser_pm_name(pm_type)); + dp_pm_name(pm_type)); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", ctrl->stream_clks_on ? "on" : "off", @@ -2153,30 +2168,56 @@ irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl) return ret; } +static const char *core_clks[] = { + "core_iface", + "core_aux", +}; + +static const char *ctrl_clks[] = { + "ctrl_link", + "ctrl_link_iface", +}; + static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) { - struct dp_ctrl_private *ctrl_private; - int rc = 0; - struct dss_module_power *core, *ctrl; + struct dp_ctrl_private *ctrl; + struct dss_module_power *core, *link; struct device *dev; + int i, rc; - ctrl_private = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dev = ctrl_private->dev; + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + dev = ctrl->dev; - core = &ctrl_private->parser->mp[DP_CORE_PM]; - ctrl = &ctrl_private->parser->mp[DP_CTRL_PM]; + core = &ctrl->mp[DP_CORE_PM]; + link = &ctrl->mp[DP_CTRL_PM]; + + core->num_clk = ARRAY_SIZE(core_clks); + core->clocks = devm_kcalloc(dev, core->num_clk, sizeof(*core->clocks), GFP_KERNEL); + if (!core->clocks) + return -ENOMEM; + + for (i = 0; i < core->num_clk; i++) + core->clocks[i].id = core_clks[i]; rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); if (rc) return rc; - rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks); - if (rc) - return -ENODEV; + link->num_clk = ARRAY_SIZE(ctrl_clks); + link->clocks = devm_kcalloc(dev, link->num_clk, sizeof(*link->clocks), GFP_KERNEL); + if (!link->clocks) + return -ENOMEM; - ctrl_private->pixel_clk = devm_clk_get(dev, "stream_pixel"); - if (IS_ERR(ctrl_private->pixel_clk)) - return PTR_ERR(ctrl_private->pixel_clk); + for (i = 0; i < link->num_clk; i++) + link->clocks[i].id = ctrl_clks[i]; + + rc = devm_clk_bulk_get(dev, link->num_clk, link->clocks); + if (rc) + return rc; + + ctrl->pixel_clk = devm_clk_get(dev, "stream_pixel"); + if (IS_ERR(ctrl->pixel_clk)) + return PTR_ERR(ctrl->pixel_clk); return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 85da5a7e5307..d8007a9d8260 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -17,6 +17,12 @@ struct dp_ctrl { bool wide_bus_en; }; +enum dp_pm_type { + DP_CORE_PM, + DP_CTRL_PM, + DP_MAX_PM +}; + int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train); int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index fe2b75f7555a..de7cfc340f0c 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -141,114 +141,6 @@ static int dp_parser_misc(struct dp_parser *parser) return 0; } -static inline bool dp_parser_check_prefix(const char *clk_prefix, - const char *clk_name) -{ - return !strncmp(clk_prefix, clk_name, strlen(clk_prefix)); -} - -static int dp_parser_init_clk_data(struct dp_parser *parser) -{ - int num_clk, i, rc; - int core_clk_count = 0, ctrl_clk_count = 0; - const char *clk_name; - struct device *dev = &parser->pdev->dev; - struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; - struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; - - num_clk = of_property_count_strings(dev->of_node, "clock-names"); - if (num_clk <= 0) { - DRM_ERROR("no clocks are defined\n"); - return -EINVAL; - } - - for (i = 0; i < num_clk; i++) { - rc = of_property_read_string_index(dev->of_node, - "clock-names", i, &clk_name); - if (rc < 0) - return rc; - - if (dp_parser_check_prefix("core", clk_name)) - core_clk_count++; - - if (dp_parser_check_prefix("ctrl", clk_name)) - ctrl_clk_count++; - } - - /* Initialize the CORE power module */ - if (core_clk_count == 0) { - DRM_ERROR("no core clocks are defined\n"); - return -EINVAL; - } - - core_power->num_clk = core_clk_count; - core_power->clocks = devm_kcalloc(dev, - core_power->num_clk, sizeof(struct clk_bulk_data), - GFP_KERNEL); - if (!core_power->clocks) - return -ENOMEM; - - /* Initialize the CTRL power module */ - if (ctrl_clk_count == 0) { - DRM_ERROR("no ctrl clocks are defined\n"); - return -EINVAL; - } - - ctrl_power->num_clk = ctrl_clk_count; - ctrl_power->clocks = devm_kcalloc(dev, - ctrl_power->num_clk, sizeof(struct clk_bulk_data), - GFP_KERNEL); - if (!ctrl_power->clocks) { - ctrl_power->num_clk = 0; - return -ENOMEM; - } - - return num_clk; -} - -static int dp_parser_clock(struct dp_parser *parser) -{ - int rc = 0, i = 0; - int num_clk = 0; - int core_clk_index = 0, ctrl_clk_index = 0; - int core_clk_count = 0, ctrl_clk_count = 0; - const char *clk_name; - struct device *dev = &parser->pdev->dev; - struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; - struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; - - rc = dp_parser_init_clk_data(parser); - if (rc < 0) { - DRM_ERROR("failed to initialize power data %d\n", rc); - return rc; - } - - num_clk = rc; - - core_clk_count = core_power->num_clk; - ctrl_clk_count = ctrl_power->num_clk; - - for (i = 0; i < num_clk; i++) { - rc = of_property_read_string_index(dev->of_node, "clock-names", - i, &clk_name); - if (rc) { - DRM_ERROR("error reading clock-names %d\n", rc); - return rc; - } - if (dp_parser_check_prefix("core", clk_name) && - core_clk_index < core_clk_count) { - core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); - core_clk_index++; - } else if (dp_parser_check_prefix("ctrl", clk_name) && - ctrl_clk_index < ctrl_clk_count) { - ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); - ctrl_clk_index++; - } - } - - return 0; -} - int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser) { struct platform_device *pdev = parser->pdev; @@ -280,10 +172,6 @@ static int dp_parser_parse(struct dp_parser *parser) if (rc) return rc; - rc = dp_parser_clock(parser); - if (rc) - return rc; - return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index c6fe26602e07..cad82c4d07da 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -16,12 +16,6 @@ #define DP_MAX_NUM_DP_LANES 4 #define DP_LINK_RATE_HBR2 540000 /* kbytes */ -enum dp_pm_type { - DP_CORE_PM, - DP_CTRL_PM, - DP_MAX_PM -}; - struct dss_io_region { size_t len; void __iomem *base; @@ -34,15 +28,6 @@ struct dss_io_data { struct dss_io_region p0; }; -static inline const char *dp_parser_pm_name(enum dp_pm_type module) -{ - switch (module) { - case DP_CORE_PM: return "DP_CORE_PM"; - case DP_CTRL_PM: return "DP_CTRL_PM"; - default: return "???"; - } -} - /** * struct dp_ctrl_resource - controller's IO related data * @@ -55,20 +40,13 @@ struct dp_io { union phy_configure_opts phy_opts; }; -struct dss_module_power { - unsigned int num_clk; - struct clk_bulk_data *clocks; -}; - /** * struct dp_parser - DP parser's data exposed to clients * * @pdev: platform data of the client - * @mp: gpio, regulator and clock related data */ struct dp_parser { struct platform_device *pdev; - struct dss_module_power mp[DP_MAX_PM]; struct dp_io io; u32 max_dp_lanes; u32 max_dp_link_rate; From e518c27218c6f8091f991d1c7145d441819a8e92 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:27 +0200 Subject: [PATCH 045/295] drm/msm/dp: split dp_ctrl_clk_enable into four functuions Split the dp_ctrl_clk_enable() beast into four functions, each of them doing just a single item: enabling or disabling core or link clocks. This allows us to cleanup the dss_module_power structure and makes several dp_ctrl functions return void. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576105/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-8-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 234 +++++++++++++--------------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 16 +- drivers/gpu/drm/msm/dp/dp_display.c | 4 +- 3 files changed, 115 insertions(+), 139 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c207e4d7f0da..9ddf2117abb2 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -69,11 +69,6 @@ struct dp_vc_tu_mapping_table { u8 tu_size_minus1; }; -struct dss_module_power { - unsigned int num_clk; - struct clk_bulk_data *clocks; -}; - struct dp_ctrl_private { struct dp_ctrl dp_ctrl; struct drm_device *drm_dev; @@ -84,7 +79,12 @@ struct dp_ctrl_private { struct dp_parser *parser; struct dp_catalog *catalog; - struct dss_module_power mp[DP_MAX_PM]; + unsigned int num_core_clks; + struct clk_bulk_data *core_clks; + + unsigned int num_link_clks; + struct clk_bulk_data *link_clks; + struct clk *pixel_clk; struct completion idle_comp; @@ -96,15 +96,6 @@ struct dp_ctrl_private { bool stream_clks_on; }; -static inline const char *dp_pm_name(enum dp_pm_type module) -{ - switch (module) { - case DP_CORE_PM: return "DP_CORE_PM"; - case DP_CTRL_PM: return "DP_CTRL_PM"; - default: return "???"; - } -} - static int dp_aux_link_configure(struct drm_dp_aux *aux, struct dp_link_info *link) { @@ -1332,67 +1323,26 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, return ret; } -int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, - enum dp_pm_type pm_type, bool enable) +int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dss_module_power *mp; int ret = 0; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - if (pm_type != DP_CORE_PM && - pm_type != DP_CTRL_PM) { - DRM_ERROR("unsupported ctrl module: %s\n", - dp_pm_name(pm_type)); - return -EINVAL; + if (ctrl->core_clks_on) { + drm_dbg_dp(ctrl->drm_dev, "core clks already enabled\n"); + return 0; } - if (enable) { - if (pm_type == DP_CORE_PM && ctrl->core_clks_on) { - drm_dbg_dp(ctrl->drm_dev, - "core clks already enabled\n"); - return 0; - } + ret = clk_bulk_prepare_enable(ctrl->num_core_clks, ctrl->core_clks); + if (ret) + return ret; - if (pm_type == DP_CTRL_PM && ctrl->link_clks_on) { - drm_dbg_dp(ctrl->drm_dev, - "links clks already enabled\n"); - return 0; - } + ctrl->core_clks_on = true; - if ((pm_type == DP_CTRL_PM) && (!ctrl->core_clks_on)) { - drm_dbg_dp(ctrl->drm_dev, - "Enable core clks before link clks\n"); - mp = &ctrl->mp[DP_CORE_PM]; - - ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); - if (ret) - return ret; - - ctrl->core_clks_on = true; - } - } - - mp = &ctrl->mp[pm_type]; - if (enable) { - ret = clk_bulk_prepare_enable(mp->num_clk, mp->clocks); - if (ret) - return ret; - } else { - clk_bulk_disable_unprepare(mp->num_clk, mp->clocks); - } - - if (pm_type == DP_CORE_PM) - ctrl->core_clks_on = enable; - else - ctrl->link_clks_on = enable; - - drm_dbg_dp(ctrl->drm_dev, "%s clocks for %s\n", - enable ? "enable" : "disable", - dp_pm_name(pm_type)); - drm_dbg_dp(ctrl->drm_dev, - "stream_clks:%s link_clks:%s core_clks:%s\n", + drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n"); + drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", ctrl->stream_clks_on ? "on" : "off", ctrl->link_clks_on ? "on" : "off", ctrl->core_clks_on ? "on" : "off"); @@ -1400,6 +1350,73 @@ int dp_ctrl_clk_enable(struct dp_ctrl *dp_ctrl, return 0; } +void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + clk_bulk_disable_unprepare(ctrl->num_core_clks, ctrl->core_clks); + + ctrl->core_clks_on = false; + + drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n"); + drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", + ctrl->stream_clks_on ? "on" : "off", + ctrl->link_clks_on ? "on" : "off", + ctrl->core_clks_on ? "on" : "off"); +} + +static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + int ret = 0; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + if (ctrl->link_clks_on) { + drm_dbg_dp(ctrl->drm_dev, "links clks already enabled\n"); + return 0; + } + + if (!ctrl->core_clks_on) { + drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n"); + + dp_ctrl_core_clk_enable(dp_ctrl); + } + + ret = clk_bulk_prepare_enable(ctrl->num_link_clks, ctrl->link_clks); + if (ret) + return ret; + + ctrl->link_clks_on = true; + + drm_dbg_dp(ctrl->drm_dev, "enale link clocks\n"); + drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", + ctrl->stream_clks_on ? "on" : "off", + ctrl->link_clks_on ? "on" : "off", + ctrl->core_clks_on ? "on" : "off"); + + return 0; +} + +static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + clk_bulk_disable_unprepare(ctrl->num_link_clks, ctrl->link_clks); + + ctrl->link_clks_on = false; + + drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n"); + drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", + ctrl->stream_clks_on ? "on" : "off", + ctrl->link_clks_on ? "on" : "off", + ctrl->core_clks_on ? "on" : "off"); +} + static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) { int ret = 0; @@ -1416,7 +1433,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) phy_power_on(phy); dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, true); + ret = dp_ctrl_link_clk_enable(&ctrl->dp_ctrl); if (ret) DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); @@ -1564,11 +1581,9 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) * link maintenance. */ dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); - if (ret) { - DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); - return ret; - } + + dp_ctrl_link_clk_disable(&ctrl->dp_ctrl); + phy_power_off(phy); /* hw recommended delay before re-enabling clocks */ msleep(20); @@ -1586,7 +1601,6 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) { struct dp_io *dp_io; struct phy *phy; - int ret; dp_io = &ctrl->parser->io; phy = dp_io->phy; @@ -1596,10 +1610,7 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_reset(ctrl->catalog); dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); - if (ret) { - DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); - } + dp_ctrl_link_clk_disable(&ctrl->dp_ctrl); phy_power_off(phy); @@ -1703,11 +1714,7 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) * running. Add the global reset just before disabling the * link clocks and core clocks. */ - ret = dp_ctrl_off(&ctrl->dp_ctrl); - if (ret) { - DRM_ERROR("failed to disable DP controller\n"); - return ret; - } + dp_ctrl_off(&ctrl->dp_ctrl); ret = dp_ctrl_on_link(&ctrl->dp_ctrl); if (ret) { @@ -1823,7 +1830,7 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) rate = ctrl->panel->link_info.rate; pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CORE_PM, true); + dp_ctrl_core_clk_enable(&ctrl->dp_ctrl); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { drm_dbg_dp(ctrl->drm_dev, @@ -2019,12 +2026,11 @@ end: return ret; } -int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) +void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; struct phy *phy; - int ret; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = &ctrl->parser->io; @@ -2041,11 +2047,7 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) } dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); - if (ret) { - DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); - return ret; - } + dp_ctrl_link_clk_disable(&ctrl->dp_ctrl); phy_power_off(phy); @@ -2055,15 +2057,13 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n", phy, phy->init_count, phy->power_count); - return ret; } -int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) +void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; struct phy *phy; - int ret; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = &ctrl->parser->io; @@ -2071,10 +2071,7 @@ int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); - if (ret) { - DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); - } + dp_ctrl_link_clk_disable(&ctrl->dp_ctrl); DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n", phy, phy->init_count, phy->power_count); @@ -2083,19 +2080,13 @@ int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) DRM_DEBUG_DP("After, phy=%p init_count=%d power_on=%d\n", phy, phy->init_count, phy->power_count); - - return ret; } -int dp_ctrl_off(struct dp_ctrl *dp_ctrl) +void dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; struct phy *phy; - int ret = 0; - - if (!dp_ctrl) - return -EINVAL; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = &ctrl->parser->io; @@ -2111,16 +2102,11 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) } dev_pm_opp_set_rate(ctrl->dev, 0); - ret = dp_ctrl_clk_enable(&ctrl->dp_ctrl, DP_CTRL_PM, false); - if (ret) { - DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); - } + dp_ctrl_link_clk_disable(&ctrl->dp_ctrl); phy_power_off(phy); drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n", phy, phy->init_count, phy->power_count); - - return ret; } irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl) @@ -2181,37 +2167,33 @@ static const char *ctrl_clks[] = { static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dss_module_power *core, *link; struct device *dev; int i, rc; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dev = ctrl->dev; - core = &ctrl->mp[DP_CORE_PM]; - link = &ctrl->mp[DP_CTRL_PM]; - - core->num_clk = ARRAY_SIZE(core_clks); - core->clocks = devm_kcalloc(dev, core->num_clk, sizeof(*core->clocks), GFP_KERNEL); - if (!core->clocks) + ctrl->num_core_clks = ARRAY_SIZE(core_clks); + ctrl->core_clks = devm_kcalloc(dev, ctrl->num_core_clks, sizeof(*ctrl->core_clks), GFP_KERNEL); + if (!ctrl->core_clks) return -ENOMEM; - for (i = 0; i < core->num_clk; i++) - core->clocks[i].id = core_clks[i]; + for (i = 0; i < ctrl->num_core_clks; i++) + ctrl->core_clks[i].id = core_clks[i]; - rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); + rc = devm_clk_bulk_get(dev, ctrl->num_core_clks, ctrl->core_clks); if (rc) return rc; - link->num_clk = ARRAY_SIZE(ctrl_clks); - link->clocks = devm_kcalloc(dev, link->num_clk, sizeof(*link->clocks), GFP_KERNEL); - if (!link->clocks) + ctrl->num_link_clks = ARRAY_SIZE(ctrl_clks); + ctrl->link_clks = devm_kcalloc(dev, ctrl->num_link_clks, sizeof(*ctrl->link_clks), GFP_KERNEL); + if (!ctrl->link_clks) return -ENOMEM; - for (i = 0; i < link->num_clk; i++) - link->clocks[i].id = ctrl_clks[i]; + for (i = 0; i < ctrl->num_link_clks; i++) + ctrl->link_clks[i].id = ctrl_clks[i]; - rc = devm_clk_bulk_get(dev, link->num_clk, link->clocks); + rc = devm_clk_bulk_get(dev, ctrl->num_link_clks, ctrl->link_clks); if (rc) return rc; diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index d8007a9d8260..023f14d0b021 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -17,17 +17,11 @@ struct dp_ctrl { bool wide_bus_en; }; -enum dp_pm_type { - DP_CORE_PM, - DP_CTRL_PM, - DP_MAX_PM -}; - int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train); -int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); -int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl); -int dp_ctrl_off(struct dp_ctrl *dp_ctrl); +void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); +void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl); +void dp_ctrl_off(struct dp_ctrl *dp_ctrl); void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl); void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl); @@ -44,7 +38,7 @@ void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl); void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enable); void dp_ctrl_config_psr(struct dp_ctrl *dp_ctrl); -int dp_ctrl_clk_enable(struct dp_ctrl *ctrl, enum dp_pm_type pm_type, - bool enable); +int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl); +void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fe348279fee7..51434c93925c 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -433,7 +433,7 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_ctrl_clk_enable(dp->ctrl, DP_CORE_PM, true); + dp_ctrl_core_clk_enable(dp->ctrl); dp_ctrl_reset_irq_ctrl(dp->ctrl, true); dp_aux_init(dp->aux); dp->core_initialized = true; @@ -447,7 +447,7 @@ static void dp_display_host_deinit(struct dp_display_private *dp) dp_ctrl_reset_irq_ctrl(dp->ctrl, false); dp_aux_deinit(dp->aux); - dp_ctrl_clk_enable(dp->ctrl, DP_CORE_PM, false); + dp_ctrl_core_clk_disable(dp->ctrl); dp->core_initialized = false; } From b4745f741e796b073e1cc60c47e864e0c06ad245 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:28 +0200 Subject: [PATCH 046/295] drm/msm/dp: move phy_configure_opts to dp_ctrl There is little point in sharing phy configuration structure between several modules. Move it to dp_ctrl, which becomes the only submodule re-configuring the PHY. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576124/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-9-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_catalog.c | 19 ------------- drivers/gpu/drm/msm/dp/dp_catalog.h | 2 -- drivers/gpu/drm/msm/dp/dp_ctrl.c | 41 +++++++++++++++++++---------- drivers/gpu/drm/msm/dp/dp_parser.h | 3 --- 4 files changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 5142aeb705a4..e07651768805 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -765,25 +765,6 @@ void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); } -int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, - u8 v_level, u8 p_level) -{ - struct dp_catalog_private *catalog = container_of(dp_catalog, - struct dp_catalog_private, dp_catalog); - struct dp_io *dp_io = catalog->io; - struct phy *phy = dp_io->phy; - struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; - - /* TODO: Update for all lanes instead of just first one */ - opts_dp->voltage[0] = v_level; - opts_dp->pre[0] = p_level; - opts_dp->set_voltages = 1; - phy_configure(phy, &dp_io->phy_opts); - opts_dp->set_voltages = 0; - - return 0; -} - void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, u32 pattern) { diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 38786e855b51..ba7c62ba7ca3 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -111,8 +111,6 @@ void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter); u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog); u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog); -int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, u8 v_level, - u8 p_level); int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog); u32 dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog, diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 9ddf2117abb2..0a9a3ba80adb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -87,6 +87,8 @@ struct dp_ctrl_private { struct clk *pixel_clk; + union phy_configure_opts phy_opts; + struct completion idle_comp; struct completion psr_op_comp; struct completion video_comp; @@ -1012,6 +1014,21 @@ static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) return ret; } +static int dp_ctrl_set_vx_px(struct dp_ctrl_private *ctrl, + u8 v_level, u8 p_level) +{ + union phy_configure_opts *phy_opts = &ctrl->phy_opts; + + /* TODO: Update for all lanes instead of just first one */ + phy_opts->dp.voltage[0] = v_level; + phy_opts->dp.pre[0] = p_level; + phy_opts->dp.set_voltages = 1; + phy_configure(ctrl->parser->io.phy, phy_opts); + phy_opts->dp.set_voltages = 0; + + return 0; +} + static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) { struct dp_link *link = ctrl->link; @@ -1024,7 +1041,7 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "voltage level: %d emphasis level: %d\n", voltage_swing_level, pre_emphasis_level); - ret = dp_catalog_ctrl_update_vx_px(ctrl->catalog, + ret = dp_ctrl_set_vx_px(ctrl, voltage_swing_level, pre_emphasis_level); if (ret) @@ -1420,16 +1437,14 @@ static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl) static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) { int ret = 0; - struct dp_io *dp_io = &ctrl->parser->io; - struct phy *phy = dp_io->phy; - struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; + struct phy *phy = ctrl->parser->io.phy; const u8 *dpcd = ctrl->panel->dpcd; - opts_dp->lanes = ctrl->link->link_params.num_lanes; - opts_dp->link_rate = ctrl->link->link_params.rate / 100; - opts_dp->ssc = drm_dp_max_downspread(dpcd); + ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; + ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100; + ctrl->phy_opts.dp.ssc = drm_dp_max_downspread(dpcd); - phy_configure(phy, &dp_io->phy_opts); + phy_configure(phy, &ctrl->phy_opts); phy_power_on(phy); dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000); @@ -1567,14 +1582,12 @@ static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) { + struct phy *phy = ctrl->parser->io.phy; int ret = 0; - struct dp_io *dp_io = &ctrl->parser->io; - struct phy *phy = dp_io->phy; - struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); - opts_dp->lanes = ctrl->link->link_params.num_lanes; - phy_configure(phy, &dp_io->phy_opts); + ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; + phy_configure(phy, &ctrl->phy_opts); /* * Disable and re-enable the mainlink clock since the * link clock might have been adjusted as part of the @@ -1654,7 +1667,7 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "request: 0x%x\n", pattern_requested); - if (dp_catalog_ctrl_update_vx_px(ctrl->catalog, + if (dp_ctrl_set_vx_px(ctrl, ctrl->link->phy_params.v_level, ctrl->link->phy_params.p_level)) { DRM_ERROR("Failed to set v/p levels\n"); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index cad82c4d07da..b28052e87101 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -7,8 +7,6 @@ #define _DP_PARSER_H_ #include -#include -#include #include "msm_drv.h" @@ -37,7 +35,6 @@ struct dss_io_data { struct dp_io { struct dss_io_data dp_controller; struct phy *phy; - union phy_configure_opts phy_opts; }; /** From 64eba0d63c707775c4afb318f6d86a4e9fab5678 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:29 +0200 Subject: [PATCH 047/295] drm/msm/dp: remove PHY handling from dp_catalog.c Inline dp_catalog_aux_update_cfg() and call phy_calibrate() from dp_aux functions directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576106/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-10-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_aux.c | 9 +++++++-- drivers/gpu/drm/msm/dp/dp_aux.h | 1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 12 ------------ drivers/gpu/drm/msm/dp/dp_catalog.h | 1 - drivers/gpu/drm/msm/dp/dp_display.c | 4 +++- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 03f4951c49f4..adbd5a367395 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -4,6 +4,7 @@ */ #include +#include #include #include "dp_reg.h" @@ -23,6 +24,8 @@ struct dp_aux_private { struct device *dev; struct dp_catalog *catalog; + struct phy *phy; + struct mutex mutex; struct completion comp; @@ -336,7 +339,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, if (aux->native) { aux->retry_cnt++; if (!(aux->retry_cnt % MAX_AUX_RETRIES)) - dp_catalog_aux_update_cfg(aux->catalog); + phy_calibrate(aux->phy); } /* reset aux if link is in connected state */ if (dp_catalog_link_is_connected(aux->catalog)) @@ -439,7 +442,7 @@ void dp_aux_reconfig(struct drm_dp_aux *dp_aux) aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - dp_catalog_aux_update_cfg(aux->catalog); + phy_calibrate(aux->phy); dp_catalog_aux_reset(aux->catalog); } @@ -517,6 +520,7 @@ static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux, } struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, + struct phy *phy, bool is_edp) { struct dp_aux_private *aux; @@ -537,6 +541,7 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, aux->dev = dev; aux->catalog = catalog; + aux->phy = phy; aux->retry_cnt = 0; /* diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index 511305da4f66..16d9b1758748 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -17,6 +17,7 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux); void dp_aux_reconfig(struct drm_dp_aux *dp_aux); struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, + struct phy *phy, bool is_edp); void dp_aux_put(struct drm_dp_aux *aux); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index e07651768805..4c6207797c99 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -7,8 +7,6 @@ #include #include -#include -#include #include #include #include @@ -243,16 +241,6 @@ void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); } -void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog) -{ - struct dp_catalog_private *catalog = container_of(dp_catalog, - struct dp_catalog_private, dp_catalog); - struct dp_io *dp_io = catalog->io; - struct phy *phy = dp_io->phy; - - phy_calibrate(phy); -} - int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog) { u32 state; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index ba7c62ba7ca3..1f3f58d4b8de 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -84,7 +84,6 @@ int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read); int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog); void dp_catalog_aux_reset(struct dp_catalog *dp_catalog); void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable); -void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog); int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog); u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 51434c93925c..37d23b48d36e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -730,7 +730,9 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } - dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp); + dp->aux = dp_aux_get(dev, dp->catalog, + dp->parser->io.phy, + dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); DRM_ERROR("failed to initialize aux, rc = %d\n", rc); From f304bda5bfdaa58a6dd9a3c2930cf73aef9ebe83 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:30 +0200 Subject: [PATCH 048/295] drm/msm/dp: handle PHY directly in dp_ctrl There is little point in going trough dp_parser->io indirection each time the driver needs to access the PHY. Store the pointer directly in dp_ctrl_private. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576119/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-11-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 37 ++++++++++------------------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 3 ++- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 0a9a3ba80adb..03bbdf865d26 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -76,9 +76,10 @@ struct dp_ctrl_private { struct drm_dp_aux *aux; struct dp_panel *panel; struct dp_link *link; - struct dp_parser *parser; struct dp_catalog *catalog; + struct phy *phy; + unsigned int num_core_clks; struct clk_bulk_data *core_clks; @@ -1023,7 +1024,7 @@ static int dp_ctrl_set_vx_px(struct dp_ctrl_private *ctrl, phy_opts->dp.voltage[0] = v_level; phy_opts->dp.pre[0] = p_level; phy_opts->dp.set_voltages = 1; - phy_configure(ctrl->parser->io.phy, phy_opts); + phy_configure(ctrl->phy, phy_opts); phy_opts->dp.set_voltages = 0; return 0; @@ -1437,7 +1438,7 @@ static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl) static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) { int ret = 0; - struct phy *phy = ctrl->parser->io.phy; + struct phy *phy = ctrl->phy; const u8 *dpcd = ctrl->panel->dpcd; ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; @@ -1535,12 +1536,10 @@ void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enter) void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; struct phy *phy; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_init(phy); @@ -1552,12 +1551,10 @@ void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl) void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; struct phy *phy; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_exit(phy); @@ -1582,7 +1579,7 @@ static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) { - struct phy *phy = ctrl->parser->io.phy; + struct phy *phy = ctrl->phy; int ret = 0; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); @@ -1612,11 +1609,9 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) { - struct dp_io *dp_io; struct phy *phy; - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); @@ -2042,12 +2037,10 @@ end: void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; struct phy *phy; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; /* set dongle to D3 (power off) mode */ dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); @@ -2075,12 +2068,10 @@ void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; struct phy *phy; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); @@ -2098,12 +2089,10 @@ void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl) void dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; struct phy *phy; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = &ctrl->parser->io; - phy = dp_io->phy; + phy = ctrl->phy; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); @@ -2220,7 +2209,7 @@ static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl) struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_panel *panel, struct drm_dp_aux *aux, struct dp_catalog *catalog, - struct dp_parser *parser) + struct phy *phy) { struct dp_ctrl_private *ctrl; int ret; @@ -2254,12 +2243,12 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, init_completion(&ctrl->video_comp); /* in parameters */ - ctrl->parser = parser; ctrl->panel = panel; ctrl->aux = aux; ctrl->link = link; ctrl->catalog = catalog; ctrl->dev = dev; + ctrl->phy = phy; ret = dp_ctrl_clk_init(&ctrl->dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 023f14d0b021..6e9f375b856a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -28,7 +28,7 @@ void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl); struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_panel *panel, struct drm_dp_aux *aux, struct dp_catalog *catalog, - struct dp_parser *parser); + struct phy *phy); void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable); void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 37d23b48d36e..2f1eb67338a5 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -761,7 +761,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, - dp->catalog, dp->parser); + dp->catalog, + dp->parser->io.phy); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); From 1577814118e74df91e065bd9a22f9afe3ed39239 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:31 +0200 Subject: [PATCH 049/295] drm/msm/dp: move all IO handling to dp_catalog Rather than parsing the I/O addresses from dp_parser and then passing them via a struct pointer to dp_catalog, handle I/O region parsing in dp_catalog and drop it from dp_parser. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576108/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-12-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_catalog.c | 127 +++++++++++++++++++++++----- drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 6 +- drivers/gpu/drm/msm/dp/dp_parser.c | 73 +--------------- drivers/gpu/drm/msm/dp/dp_parser.h | 26 +----- 5 files changed, 115 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 4c6207797c99..541aac2cb246 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -53,10 +54,31 @@ (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) +#define DP_DEFAULT_AHB_OFFSET 0x0000 +#define DP_DEFAULT_AHB_SIZE 0x0200 +#define DP_DEFAULT_AUX_OFFSET 0x0200 +#define DP_DEFAULT_AUX_SIZE 0x0200 +#define DP_DEFAULT_LINK_OFFSET 0x0400 +#define DP_DEFAULT_LINK_SIZE 0x0C00 +#define DP_DEFAULT_P0_OFFSET 0x1000 +#define DP_DEFAULT_P0_SIZE 0x0400 + +struct dss_io_region { + size_t len; + void __iomem *base; +}; + +struct dss_io_data { + struct dss_io_region ahb; + struct dss_io_region aux; + struct dss_io_region link; + struct dss_io_region p0; +}; + struct dp_catalog_private { struct device *dev; struct drm_device *drm_dev; - struct dp_io *io; + struct dss_io_data io; u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; struct dp_catalog dp_catalog; u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; @@ -66,7 +88,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - struct dss_io_data *dss = &catalog->io->dp_controller; + struct dss_io_data *dss = &catalog->io; msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); @@ -76,7 +98,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) { - return readl_relaxed(catalog->io->dp_controller.aux.base + offset); + return readl_relaxed(catalog->io.aux.base + offset); } static inline void dp_write_aux(struct dp_catalog_private *catalog, @@ -86,12 +108,12 @@ static inline void dp_write_aux(struct dp_catalog_private *catalog, * To make sure aux reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.aux.base + offset); + writel(data, catalog->io.aux.base + offset); } static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset) { - return readl_relaxed(catalog->io->dp_controller.ahb.base + offset); + return readl_relaxed(catalog->io.ahb.base + offset); } static inline void dp_write_ahb(struct dp_catalog_private *catalog, @@ -101,7 +123,7 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog, * To make sure phy reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.ahb.base + offset); + writel(data, catalog->io.ahb.base + offset); } static inline void dp_write_p0(struct dp_catalog_private *catalog, @@ -111,7 +133,7 @@ static inline void dp_write_p0(struct dp_catalog_private *catalog, * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.p0.base + offset); + writel(data, catalog->io.p0.base + offset); } static inline u32 dp_read_p0(struct dp_catalog_private *catalog, @@ -121,12 +143,12 @@ static inline u32 dp_read_p0(struct dp_catalog_private *catalog, * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(catalog->io->dp_controller.p0.base + offset); + return readl_relaxed(catalog->io.p0.base + offset); } static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) { - return readl_relaxed(catalog->io->dp_controller.link.base + offset); + return readl_relaxed(catalog->io.link.base + offset); } static inline void dp_write_link(struct dp_catalog_private *catalog, @@ -136,7 +158,7 @@ static inline void dp_write_link(struct dp_catalog_private *catalog, * To make sure link reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.link.base + offset); + writel(data, catalog->io.link.base + offset); } /* aux related catalog functions */ @@ -248,7 +270,7 @@ int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog) struct dp_catalog_private, dp_catalog); /* poll for hpd connected status every 2ms and timeout after 500ms */ - return readl_poll_timeout(catalog->io->dp_controller.aux.base + + return readl_poll_timeout(catalog->io.aux.base + REG_DP_DP_HPD_INT_STATUS, state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, 2000, 500000); @@ -276,7 +298,7 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - struct dss_io_data *io = &catalog->io->dp_controller; + struct dss_io_data *io = &catalog->io; pr_info("AHB regs\n"); dump_regs(io->ahb.base, io->ahb.len); @@ -500,7 +522,7 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; /* Poll for mainlink ready status */ - ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base + + ret = readx_poll_timeout(readl, catalog->io.link.base + REG_DP_MAINLINK_READY, data, data & bit, POLLING_SLEEP_US, POLLING_TIMEOUT_US); @@ -563,7 +585,7 @@ bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog) struct dp_catalog_private, dp_catalog); /* Poll for mainlink ready status */ - ret = readl_poll_timeout(catalog->io->dp_controller.link.base + + ret = readl_poll_timeout(catalog->io.link.base + REG_DP_MAINLINK_READY, data, data & DP_MAINLINK_READY_FOR_VIDEO, POLLING_SLEEP_US, POLLING_TIMEOUT_US); @@ -945,21 +967,84 @@ void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); } -struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) +static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len) +{ + struct resource *res; + void __iomem *base; + + base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); + if (!IS_ERR(base)) + *len = resource_size(res); + + return base; +} + +static int dp_catalog_get_io(struct dp_catalog_private *catalog) +{ + struct platform_device *pdev = to_platform_device(catalog->dev); + struct dss_io_data *dss = &catalog->io; + + dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len); + if (IS_ERR(dss->ahb.base)) + return PTR_ERR(dss->ahb.base); + + dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len); + if (IS_ERR(dss->aux.base)) { + /* + * The initial binding had a single reg, but in order to + * support variation in the sub-region sizes this was split. + * dp_ioremap() will fail with -EINVAL here if only a single + * reg is specified, so fill in the sub-region offsets and + * lengths based on this single region. + */ + if (PTR_ERR(dss->aux.base) == -EINVAL) { + if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { + DRM_ERROR("legacy memory region not large enough\n"); + return -EINVAL; + } + + dss->ahb.len = DP_DEFAULT_AHB_SIZE; + dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; + dss->aux.len = DP_DEFAULT_AUX_SIZE; + dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; + dss->link.len = DP_DEFAULT_LINK_SIZE; + dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; + dss->p0.len = DP_DEFAULT_P0_SIZE; + } else { + DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base); + return PTR_ERR(dss->aux.base); + } + } else { + dss->link.base = dp_ioremap(pdev, 2, &dss->link.len); + if (IS_ERR(dss->link.base)) { + DRM_ERROR("unable to remap link region: %pe\n", dss->link.base); + return PTR_ERR(dss->link.base); + } + + dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len); + if (IS_ERR(dss->p0.base)) { + DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base); + return PTR_ERR(dss->p0.base); + } + } + + return 0; +} + +struct dp_catalog *dp_catalog_get(struct device *dev) { struct dp_catalog_private *catalog; - - if (!io) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-EINVAL); - } + int ret; catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); if (!catalog) return ERR_PTR(-ENOMEM); catalog->dev = dev; - catalog->io = io; + + ret = dp_catalog_get_io(catalog); + if (ret) + return ERR_PTR(ret); return &catalog->dp_catalog; } diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 1f3f58d4b8de..989e4c4fd6fa 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -126,7 +126,7 @@ void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, struct drm_display_mode *drm_mode); void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog); -struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io); +struct dp_catalog *dp_catalog_get(struct device *dev); /* DP Audio APIs */ void dp_catalog_audio_get_header(struct dp_catalog *catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2f1eb67338a5..27ccb25fb548 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -722,7 +722,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } - dp->catalog = dp_catalog_get(dev, &dp->parser->io); + dp->catalog = dp_catalog_get(dev); if (IS_ERR(dp->catalog)) { rc = PTR_ERR(dp->catalog); DRM_ERROR("failed to initialize catalog, rc = %d\n", rc); @@ -731,7 +731,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->aux = dp_aux_get(dev, dp->catalog, - dp->parser->io.phy, + dp->parser->phy, dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); @@ -762,7 +762,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, dp->catalog, - dp->parser->io.phy); + dp->parser->phy); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index de7cfc340f0c..2d0dd4353cdf 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -13,80 +13,13 @@ #include "dp_parser.h" #include "dp_reg.h" -#define DP_DEFAULT_AHB_OFFSET 0x0000 -#define DP_DEFAULT_AHB_SIZE 0x0200 -#define DP_DEFAULT_AUX_OFFSET 0x0200 -#define DP_DEFAULT_AUX_SIZE 0x0200 -#define DP_DEFAULT_LINK_OFFSET 0x0400 -#define DP_DEFAULT_LINK_SIZE 0x0C00 -#define DP_DEFAULT_P0_OFFSET 0x1000 -#define DP_DEFAULT_P0_SIZE 0x0400 - -static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len) -{ - struct resource *res; - void __iomem *base; - - base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); - if (!IS_ERR(base)) - *len = resource_size(res); - - return base; -} - static int dp_parser_ctrl_res(struct dp_parser *parser) { struct platform_device *pdev = parser->pdev; - struct dp_io *io = &parser->io; - struct dss_io_data *dss = &io->dp_controller; - dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len); - if (IS_ERR(dss->ahb.base)) - return PTR_ERR(dss->ahb.base); - - dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len); - if (IS_ERR(dss->aux.base)) { - /* - * The initial binding had a single reg, but in order to - * support variation in the sub-region sizes this was split. - * dp_ioremap() will fail with -EINVAL here if only a single - * reg is specified, so fill in the sub-region offsets and - * lengths based on this single region. - */ - if (PTR_ERR(dss->aux.base) == -EINVAL) { - if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { - DRM_ERROR("legacy memory region not large enough\n"); - return -EINVAL; - } - - dss->ahb.len = DP_DEFAULT_AHB_SIZE; - dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; - dss->aux.len = DP_DEFAULT_AUX_SIZE; - dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; - dss->link.len = DP_DEFAULT_LINK_SIZE; - dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; - dss->p0.len = DP_DEFAULT_P0_SIZE; - } else { - DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base); - return PTR_ERR(dss->aux.base); - } - } else { - dss->link.base = dp_ioremap(pdev, 2, &dss->link.len); - if (IS_ERR(dss->link.base)) { - DRM_ERROR("unable to remap link region: %pe\n", dss->link.base); - return PTR_ERR(dss->link.base); - } - - dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len); - if (IS_ERR(dss->p0.base)) { - DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base); - return PTR_ERR(dss->p0.base); - } - } - - io->phy = devm_phy_get(&pdev->dev, "dp"); - if (IS_ERR(io->phy)) - return PTR_ERR(io->phy); + parser->phy = devm_phy_get(&pdev->dev, "dp"); + if (IS_ERR(parser->phy)) + return PTR_ERR(parser->phy); return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index b28052e87101..7306768547a6 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -14,37 +14,15 @@ #define DP_MAX_NUM_DP_LANES 4 #define DP_LINK_RATE_HBR2 540000 /* kbytes */ -struct dss_io_region { - size_t len; - void __iomem *base; -}; - -struct dss_io_data { - struct dss_io_region ahb; - struct dss_io_region aux; - struct dss_io_region link; - struct dss_io_region p0; -}; - -/** - * struct dp_ctrl_resource - controller's IO related data - * - * @dp_controller: Display Port controller mapped memory address - * @phy_io: phy's mapped memory address - */ -struct dp_io { - struct dss_io_data dp_controller; - struct phy *phy; -}; - /** * struct dp_parser - DP parser's data exposed to clients * * @pdev: platform data of the client + * @phy: PHY handle */ struct dp_parser { struct platform_device *pdev; - struct dp_io io; + struct phy *phy; u32 max_dp_lanes; u32 max_dp_link_rate; struct drm_bridge *next_bridge; From 3ffe15b30a63afb9b53384a4efea9b823f2f5000 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:32 +0200 Subject: [PATCH 050/295] drm/msm/dp: move link property handling to dp_panel Instead of passing link properties through the separate struct, parse them directly in the dp_panel. Signed-off-by: Dmitry Baryshkov Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576117/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-13-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_display.c | 8 ---- drivers/gpu/drm/msm/dp/dp_display.h | 1 - drivers/gpu/drm/msm/dp/dp_panel.c | 66 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_parser.c | 54 ----------------------- drivers/gpu/drm/msm/dp/dp_parser.h | 4 -- 5 files changed, 66 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 27ccb25fb548..e09ee339be8e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -357,12 +357,6 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) int rc = 0; struct edid *edid; - dp->panel->max_dp_lanes = dp->parser->max_dp_lanes; - dp->panel->max_dp_link_rate = dp->parser->max_dp_link_rate; - - drm_dbg_dp(dp->drm_dev, "max_lanes=%d max_link_rate=%d\n", - dp->panel->max_dp_lanes, dp->panel->max_dp_link_rate); - rc = dp_panel_read_sink_caps(dp->panel, dp->dp_display.connector); if (rc) goto end; @@ -382,8 +376,6 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->audio_supported = drm_detect_monitor_audio(edid); dp_panel_handle_sink_request(dp->panel); - dp->dp_display.max_dp_lanes = dp->parser->max_dp_lanes; - /* * set sink to normal operation mode -- D0 * before dpcd read diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 102f3507d824..70759dd1bfd0 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -28,7 +28,6 @@ struct msm_dp { bool wide_bus_en; - u32 max_dp_lanes; struct dp_audio *dp_audio; bool psr_supported; }; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 127f6af995cd..8242541a81b9 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -7,8 +7,12 @@ #include #include +#include #include +#define DP_MAX_NUM_DP_LANES 4 +#define DP_LINK_RATE_HBR2 540000 /* kbytes */ + struct dp_panel_private { struct device *dev; struct drm_device *drm_dev; @@ -138,6 +142,9 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n", + dp_panel->max_dp_lanes, dp_panel->max_dp_link_rate); + rc = dp_panel_read_dpcd(dp_panel); if (rc) { DRM_ERROR("read dpcd failed %d\n", rc); @@ -386,10 +393,65 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel) return 0; } +static u32 dp_panel_link_frequencies(struct device_node *of_node) +{ + struct device_node *endpoint; + u64 frequency = 0; + int cnt; + + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */ + if (!endpoint) + return 0; + + cnt = of_property_count_u64_elems(endpoint, "link-frequencies"); + + if (cnt > 0) + of_property_read_u64_index(endpoint, "link-frequencies", + cnt - 1, &frequency); + of_node_put(endpoint); + + do_div(frequency, + 10 * /* from symbol rate to link rate */ + 1000); /* kbytes */ + + return frequency; +} + +static int dp_panel_parse_dt(struct dp_panel *dp_panel) +{ + struct dp_panel_private *panel; + struct device_node *of_node; + int cnt; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + of_node = panel->dev->of_node; + + /* + * data-lanes is the property of dp_out endpoint + */ + cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES); + if (cnt < 0) { + /* legacy code, data-lanes is the property of mdss_dp node */ + cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); + } + + if (cnt > 0) + dp_panel->max_dp_lanes = cnt; + else + dp_panel->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ + + dp_panel->max_dp_link_rate = dp_panel_link_frequencies(of_node); + if (!dp_panel->max_dp_link_rate) + dp_panel->max_dp_link_rate = DP_LINK_RATE_HBR2; + + return 0; +} + struct dp_panel *dp_panel_get(struct dp_panel_in *in) { struct dp_panel_private *panel; struct dp_panel *dp_panel; + int ret; if (!in->dev || !in->catalog || !in->aux || !in->link) { DRM_ERROR("invalid input\n"); @@ -408,6 +470,10 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel = &panel->dp_panel; dp_panel->max_bw_code = DP_LINK_BW_8_1; + ret = dp_panel_parse_dt(dp_panel); + if (ret) + return ERR_PTR(ret); + return dp_panel; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 2d0dd4353cdf..aa135d5cedbd 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -24,56 +24,6 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) return 0; } -static u32 dp_parser_link_frequencies(struct device_node *of_node) -{ - struct device_node *endpoint; - u64 frequency = 0; - int cnt; - - endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */ - if (!endpoint) - return 0; - - cnt = of_property_count_u64_elems(endpoint, "link-frequencies"); - - if (cnt > 0) - of_property_read_u64_index(endpoint, "link-frequencies", - cnt - 1, &frequency); - of_node_put(endpoint); - - do_div(frequency, - 10 * /* from symbol rate to link rate */ - 1000); /* kbytes */ - - return frequency; -} - -static int dp_parser_misc(struct dp_parser *parser) -{ - struct device_node *of_node = parser->pdev->dev.of_node; - int cnt; - - /* - * data-lanes is the property of dp_out endpoint - */ - cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES); - if (cnt < 0) { - /* legacy code, data-lanes is the property of mdss_dp node */ - cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); - } - - if (cnt > 0) - parser->max_dp_lanes = cnt; - else - parser->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ - - parser->max_dp_link_rate = dp_parser_link_frequencies(of_node); - if (!parser->max_dp_link_rate) - parser->max_dp_link_rate = DP_LINK_RATE_HBR2; - - return 0; -} - int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser) { struct platform_device *pdev = parser->pdev; @@ -101,10 +51,6 @@ static int dp_parser_parse(struct dp_parser *parser) if (rc) return rc; - rc = dp_parser_misc(parser); - if (rc) - return rc; - return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 7306768547a6..21a66932e35e 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -11,8 +11,6 @@ #include "msm_drv.h" #define DP_MAX_PIXEL_CLK_KHZ 675000 -#define DP_MAX_NUM_DP_LANES 4 -#define DP_LINK_RATE_HBR2 540000 /* kbytes */ /** * struct dp_parser - DP parser's data exposed to clients @@ -23,8 +21,6 @@ struct dp_parser { struct platform_device *pdev; struct phy *phy; - u32 max_dp_lanes; - u32 max_dp_link_rate; struct drm_bridge *next_bridge; }; From b3b1d122a80bdc115c0ef7441d645324d1e21a27 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:33 +0200 Subject: [PATCH 051/295] drm/msm/dp: move next_bridge handling to dp_display Remove two levels of indirection and fetch next bridge directly in dp_display_probe_tail(). Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576126/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-14-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/dp/dp_display.c | 43 ++++++++++------------------- drivers/gpu/drm/msm/dp/dp_parser.c | 14 ---------- drivers/gpu/drm/msm/dp/dp_parser.h | 14 ---------- 3 files changed, 14 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index e09ee339be8e..a8b76c120c36 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1196,16 +1196,25 @@ static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pde return NULL; } -static int dp_display_get_next_bridge(struct msm_dp *dp); - static int dp_display_probe_tail(struct device *dev) { struct msm_dp *dp = dev_get_drvdata(dev); int ret; - ret = dp_display_get_next_bridge(dp); - if (ret) - return ret; + /* + * External bridges are mandatory for eDP interfaces: one has to + * provide at least an eDP panel (which gets wrapped into panel-bridge). + * + * For DisplayPort interfaces external bridges are optional, so + * silently ignore an error if one is not present (-ENODEV). + */ + dp->next_bridge = devm_drm_of_get_bridge(&dp->pdev->dev, dp->pdev->dev.of_node, 1, 0); + if (IS_ERR(dp->next_bridge)) { + ret = PTR_ERR(dp->next_bridge); + dp->next_bridge = NULL; + if (dp->is_edp || ret != -ENODEV) + return ret; + } ret = component_add(dev, &dp_display_comp_ops); if (ret) @@ -1398,30 +1407,6 @@ void dp_display_debugfs_init(struct msm_dp *dp_display, struct dentry *root, boo } } -static int dp_display_get_next_bridge(struct msm_dp *dp) -{ - int rc; - struct dp_display_private *dp_priv; - - dp_priv = container_of(dp, struct dp_display_private, dp_display); - - /* - * External bridges are mandatory for eDP interfaces: one has to - * provide at least an eDP panel (which gets wrapped into panel-bridge). - * - * For DisplayPort interfaces external bridges are optional, so - * silently ignore an error if one is not present (-ENODEV). - */ - rc = devm_dp_parser_find_next_bridge(&dp->pdev->dev, dp_priv->parser); - if (!dp->is_edp && rc == -ENODEV) - return 0; - - if (!rc) - dp->next_bridge = dp_priv->parser->next_bridge; - - return rc; -} - int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index aa135d5cedbd..f95ab3c5c72c 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -24,20 +24,6 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) return 0; } -int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser) -{ - struct platform_device *pdev = parser->pdev; - struct drm_bridge *bridge; - - bridge = devm_drm_of_get_bridge(dev, pdev->dev.of_node, 1, 0); - if (IS_ERR(bridge)) - return PTR_ERR(bridge); - - parser->next_bridge = bridge; - - return 0; -} - static int dp_parser_parse(struct dp_parser *parser) { int rc = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 21a66932e35e..38fd335d5950 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -21,7 +21,6 @@ struct dp_parser { struct platform_device *pdev; struct phy *phy; - struct drm_bridge *next_bridge; }; /** @@ -37,17 +36,4 @@ struct dp_parser { */ struct dp_parser *dp_parser_get(struct platform_device *pdev); -/** - * devm_dp_parser_find_next_bridge() - find an additional bridge to DP - * - * @dev: device to tie bridge lifetime to - * @parser: dp_parser data from client - * - * This function is used to find any additional bridge attached to - * the DP controller. The eDP interface requires a panel bridge. - * - * Return: 0 if able to get the bridge, otherwise negative errno for failure. - */ -int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser); - #endif From 6215f1558babad58e9797931a70272718fb77eff Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 26 Jan 2024 20:26:34 +0200 Subject: [PATCH 052/295] drm/msm/dp: drop dp_parser Finally drop separate "parsing" submodule. There is no need in it anymore. All submodules handle DT properties directly rather than passing them via the separate structure pointer. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Kuogee Hsieh Reviewed-by: Kuogee Hsieh Patchwork: https://patchwork.freedesktop.org/patch/576116/ Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-15-098d5f581dd3@linaro.org --- drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/dp/dp_aux.h | 1 + drivers/gpu/drm/msm/dp/dp_catalog.h | 1 - drivers/gpu/drm/msm/dp/dp_ctrl.h | 3 +- drivers/gpu/drm/msm/dp/dp_debug.c | 1 - drivers/gpu/drm/msm/dp/dp_display.c | 18 ++++----- drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_parser.c | 61 ----------------------------- drivers/gpu/drm/msm/dp/dp_parser.h | 39 ------------------ 9 files changed, 12 insertions(+), 115 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 8dbdf3fba69e..543e04fa72e3 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -127,7 +127,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_drm.o \ dp/dp_link.o \ dp/dp_panel.o \ - dp/dp_parser.o \ dp/dp_audio.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index 16d9b1758748..f47d591c1f54 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -16,6 +16,7 @@ void dp_aux_init(struct drm_dp_aux *dp_aux); void dp_aux_deinit(struct drm_dp_aux *dp_aux); void dp_aux_reconfig(struct drm_dp_aux *dp_aux); +struct phy; struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, struct phy *phy, bool is_edp); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 989e4c4fd6fa..a724a986b6ee 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -8,7 +8,6 @@ #include -#include "dp_parser.h" #include "disp/msm_disp_snapshot.h" /* interrupts */ diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 6e9f375b856a..fa014cee7e21 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -9,7 +9,6 @@ #include "dp_aux.h" #include "dp_panel.h" #include "dp_link.h" -#include "dp_parser.h" #include "dp_catalog.h" struct dp_ctrl { @@ -17,6 +16,8 @@ struct dp_ctrl { bool wide_bus_en; }; +struct phy; + int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train); void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 26f800afe5a2..eca5a02f9003 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -9,7 +9,6 @@ #include #include -#include "dp_parser.h" #include "dp_catalog.h" #include "dp_aux.h" #include "dp_ctrl.h" diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index a8b76c120c36..e4433891becb 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -9,13 +9,13 @@ #include #include #include +#include #include #include #include #include "msm_drv.h" #include "msm_kms.h" -#include "dp_parser.h" #include "dp_ctrl.h" #include "dp_catalog.h" #include "dp_aux.h" @@ -88,7 +88,6 @@ struct dp_display_private { struct drm_device *drm_dev; struct dentry *root; - struct dp_parser *parser; struct dp_catalog *catalog; struct drm_dp_aux *aux; struct dp_link *link; @@ -705,14 +704,11 @@ static int dp_init_sub_modules(struct dp_display_private *dp) struct dp_panel_in panel_in = { .dev = dev, }; + struct phy *phy; - dp->parser = dp_parser_get(dp->dp_display.pdev); - if (IS_ERR(dp->parser)) { - rc = PTR_ERR(dp->parser); - DRM_ERROR("failed to initialize parser, rc = %d\n", rc); - dp->parser = NULL; - goto error; - } + phy = devm_phy_get(dev, "dp"); + if (IS_ERR(phy)) + return PTR_ERR(phy); dp->catalog = dp_catalog_get(dev); if (IS_ERR(dp->catalog)) { @@ -723,7 +719,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->aux = dp_aux_get(dev, dp->catalog, - dp->parser->phy, + phy, dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); @@ -754,7 +750,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, dp->catalog, - dp->parser->phy); + phy); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 70759dd1bfd0..234dada88687 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -10,6 +10,8 @@ #include #include "disp/msm_disp_snapshot.h" +#define DP_MAX_PIXEL_CLK_KHZ 675000 + struct msm_dp { struct drm_device *drm_dev; struct platform_device *pdev; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c deleted file mode 100644 index f95ab3c5c72c..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. - */ - -#include -#include - -#include -#include -#include - -#include "dp_parser.h" -#include "dp_reg.h" - -static int dp_parser_ctrl_res(struct dp_parser *parser) -{ - struct platform_device *pdev = parser->pdev; - - parser->phy = devm_phy_get(&pdev->dev, "dp"); - if (IS_ERR(parser->phy)) - return PTR_ERR(parser->phy); - - return 0; -} - -static int dp_parser_parse(struct dp_parser *parser) -{ - int rc = 0; - - if (!parser) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - rc = dp_parser_ctrl_res(parser); - if (rc) - return rc; - - return 0; -} - -struct dp_parser *dp_parser_get(struct platform_device *pdev) -{ - struct dp_parser *parser; - int ret; - - parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL); - if (!parser) - return ERR_PTR(-ENOMEM); - - parser->pdev = pdev; - - ret = dp_parser_parse(parser); - if (ret) { - dev_err(&pdev->dev, "device tree parsing failed\n"); - return ERR_PTR(ret); - } - - return parser; -} diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h deleted file mode 100644 index 38fd335d5950..000000000000 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_PARSER_H_ -#define _DP_PARSER_H_ - -#include - -#include "msm_drv.h" - -#define DP_MAX_PIXEL_CLK_KHZ 675000 - -/** - * struct dp_parser - DP parser's data exposed to clients - * - * @pdev: platform data of the client - * @phy: PHY handle - */ -struct dp_parser { - struct platform_device *pdev; - struct phy *phy; -}; - -/** - * dp_parser_get() - get the DP's device tree parser module - * - * @pdev: platform data of the client - * return: pointer to dp_parser structure. - * - * This function provides client capability to parse the - * device tree and populate the data structures. The data - * related to clock, regulators, pin-control and other - * can be parsed using this module. - */ -struct dp_parser *dp_parser_get(struct platform_device *pdev); - -#endif From 2f4a67a3894e15c135125cb54edc5b43abc1b70e Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 31 Jan 2024 16:47:36 -0800 Subject: [PATCH 053/295] drm/msm/dpu: fix the programming of INTF_CFG2_DATA_HCTL_EN Currently INTF_CFG2_DATA_HCTL_EN is coupled with the enablement of widebus but this is incorrect because we should be enabling this bit independent of widebus except for cases where compression is enabled in one pixel per clock mode. Fix this by making the condition checks more explicit and enabling INTF_CFG2_DATA_HCTL_EN for all other cases when supported by DPU. Fixes: 3309a7563971 ("drm/msm/dpu: revise timing engine programming to support widebus feature") Suggested-by: Dmitry Baryshkov Signed-off-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/576722/ Link: https://lore.kernel.org/r/20240201004737.2478-1-quic_abhinavk@quicinc.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 +++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 7 +++++++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 15 +++++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 1 + 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 6a4b489d44e5..8932f38a41b2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -226,6 +226,13 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) return dpu_enc->wide_bus_en; } +bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc) +{ + const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); + + return dpu_enc->dsc ? true : false; +} + int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 4c05fd5e9ed1..fe6b1d312a74 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -158,6 +158,13 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc); bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc); +/** + * dpu_encoder_is_dsc_enabled - indicate whether dsc is enabled + * for the encoder. + * @drm_enc: Pointer to previously created drm encoder structure + */ +bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc); + /** * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained * in virtual encoder that can collect CRC values diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index d0f56c5c4cce..f562beb6f797 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -102,6 +102,7 @@ static void drm_mode_to_intf_timing_params( } timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); /* * for DP, divide the horizonal parameters by 2 when diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 6bba531d6dc4..965692ef7892 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -163,13 +163,8 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x; - /* - * DATA_HCTL_EN controls data timing which can be different from - * video timing. It is recommended to enable it for all cases, except - * if compression is enabled in 1 pixel per clock mode - */ if (p->wide_bus_en) - intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN; + intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN; data_width = p->width; @@ -229,6 +224,14 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg); DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format); if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) { + /* + * DATA_HCTL_EN controls data timing which can be different from + * video timing. It is recommended to enable it for all cases, except + * if compression is enabled in 1 pixel per clock mode + */ + if (!(p->compression_en && !p->wide_bus_en)) + intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN; + DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl); DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 0bd57a32144a..6f4c87244f94 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -33,6 +33,7 @@ struct dpu_hw_intf_timing_params { u32 hsync_skew; bool wide_bus_en; + bool compression_en; }; struct dpu_hw_intf_prog_fetch { From 4825b207002a838aa5a11ff2ddcc23b70692e8fe Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 2 Feb 2024 16:23:37 -0600 Subject: [PATCH 054/295] dt-bindings: display: msm: sm8650-mdss: Add missing explicit "additionalProperties" In order to check schemas for missing additionalProperties or unevaluatedProperties, cases allowing extra properties must be explicit. Signed-off-by: Rob Herring Reviewed-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/576954/ Link: https://lore.kernel.org/r/20240202222338.1652333-1-robh@kernel.org Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml index bd11119dc93d..24cece1e888b 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-mdss.yaml @@ -37,18 +37,21 @@ properties: patternProperties: "^display-controller@[0-9a-f]+$": type: object + additionalProperties: true properties: compatible: const: qcom,sm8650-dpu "^displayport-controller@[0-9a-f]+$": type: object + additionalProperties: true properties: compatible: const: qcom,sm8650-dp "^dsi@[0-9a-f]+$": type: object + additionalProperties: true properties: compatible: items: @@ -57,6 +60,7 @@ patternProperties: "^phy@[0-9a-f]+$": type: object + additionalProperties: true properties: compatible: const: qcom,sm8650-dsi-phy-4nm From 99d519fed75bed8a66f90407ec6304b688426c47 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sun, 4 Feb 2024 18:04:39 +0100 Subject: [PATCH 055/295] drm/msm/dsi: Replace dsi_get_bpp() with mipi_dsi header function drm_mipi_dsi.h already provides a conversion function from MIPI_DSI_FMT_ to bpp, named mipi_dsi_pixel_format_to_bpp(). Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577065/ Link: https://lore.kernel.org/r/20240204-drm-msm-dsi-remove-open-coded-get-bpp-v1-1-c16212de7e86@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_host.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index deeecdfd6c4e..9fa0053fac74 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -183,16 +183,6 @@ struct msm_dsi_host { int irq; }; -static u32 dsi_get_bpp(const enum mipi_dsi_pixel_format fmt) -{ - switch (fmt) { - case MIPI_DSI_FMT_RGB565: return 16; - case MIPI_DSI_FMT_RGB666_PACKED: return 18; - case MIPI_DSI_FMT_RGB666: - case MIPI_DSI_FMT_RGB888: - default: return 24; - } -} static inline u32 dsi_read(struct msm_dsi_host *msm_host, u32 reg) { @@ -567,7 +557,7 @@ unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_d { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); u8 lanes = msm_host->lanes; - u32 bpp = dsi_get_bpp(msm_host->format); + u32 bpp = mipi_dsi_pixel_format_to_bpp(msm_host->format); unsigned long pclk_rate = dsi_get_pclk_rate(mode, msm_host->dsc, is_bonded_dsi); unsigned long pclk_bpp; @@ -610,7 +600,7 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) { - u32 bpp = dsi_get_bpp(msm_host->format); + u32 bpp = mipi_dsi_pixel_format_to_bpp(msm_host->format); unsigned int esc_mhz, esc_div; unsigned long byte_mhz; @@ -993,7 +983,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) /* image data and 1 byte write_memory_start cmd */ if (!msm_host->dsc) - wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; + wc = hdisplay * mipi_dsi_pixel_format_to_bpp(msm_host->format) / 8 + 1; else /* * When DSC is enabled, WC = slice_chunk_size * slice_per_pkt + 1. @@ -1413,7 +1403,7 @@ static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host, { int len, ret; int bllp_len = msm_host->mode->hdisplay * - dsi_get_bpp(msm_host->format) / 8; + mipi_dsi_pixel_format_to_bpp(msm_host->format) / 8; len = dsi_cmd_dma_add(msm_host, msg); if (len < 0) { From 06267d22f9ee6fd34150b6dcdb2fa6983e1a85bc Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sun, 4 Feb 2024 18:45:27 +0100 Subject: [PATCH 056/295] drm/msm/dpu: Only enable DSC_MODE_MULTIPLEX if dsc_merge is enabled When the topology calls for two interfaces on the current fixed topology of 2 DSC blocks, or uses 1 DSC block for a single interface (e.g. SC7280 with only one DSC block), there should be no merging of DSC output. This is already represented by the return value of dpu_encoder_use_dsc_merge(), but not yet used to correctly configure this flag. Fixes: 58dca9810749 ("drm/msm/disp/dpu1: Add support for DSC in encoder") Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577067/ Link: https://lore.kernel.org/r/20240204-dpu-dsc-multiplex-v1-1-080963233c52@somainline.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 8932f38a41b2..aca689314cce 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1860,7 +1860,9 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, dsc_common_mode = 0; pic_width = dsc->pic_width; - dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL; + dsc_common_mode = DSC_MODE_SPLIT_PANEL; + if (dpu_encoder_use_dsc_merge(enc_master->parent)) + dsc_common_mode |= DSC_MODE_MULTIPLEX; if (enc_master->intf_mode == INTF_MODE_VIDEO) dsc_common_mode |= DSC_MODE_VIDEO; From c6f60037bfa0dbba47889febf08de1c20dc8b3e0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:20:41 +0200 Subject: [PATCH 057/295] drm/msm/dpu: split irq_control into irq_enable and _disable The single helper for both enable and disable cases is too complicated, especially if we start adding more code to these helpers. Split it into irq_enable and irq_disable cases. Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577526/ Link: https://lore.kernel.org/r/20240208-fd_remove_phys_ops_atomic_mode_set-v4-1-caf5dcd125c0@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 36 ++++++++--- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 6 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 61 +++++++++--------- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 44 +++++++------ .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 29 ++++++--- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 62 ++++++++++++++----- 6 files changed, 155 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index aca689314cce..2bb249c56400 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -721,7 +721,7 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, } } -static void _dpu_encoder_irq_control(struct drm_encoder *drm_enc, bool enable) +static void _dpu_encoder_irq_enable(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc; int i; @@ -733,14 +733,32 @@ static void _dpu_encoder_irq_control(struct drm_encoder *drm_enc, bool enable) dpu_enc = to_dpu_encoder_virt(drm_enc); - DPU_DEBUG_ENC(dpu_enc, "enable:%d\n", enable); + DPU_DEBUG_ENC(dpu_enc, "\n"); for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - if (phys->ops.irq_control) - phys->ops.irq_control(phys, enable); + phys->ops.irq_enable(phys); + } +} + +static void _dpu_encoder_irq_disable(struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + int i; + + if (!drm_enc) { + DPU_ERROR("invalid encoder\n"); + return; } + dpu_enc = to_dpu_encoder_virt(drm_enc); + + DPU_DEBUG_ENC(dpu_enc, "\n"); + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + phys->ops.irq_disable(phys); + } } static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, @@ -766,11 +784,11 @@ static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, pm_runtime_get_sync(&dpu_kms->pdev->dev); /* enable all the irq */ - _dpu_encoder_irq_control(drm_enc, true); + _dpu_encoder_irq_enable(drm_enc); } else { /* disable all the irq */ - _dpu_encoder_irq_control(drm_enc, false); + _dpu_encoder_irq_disable(drm_enc); /* disable DPU core clks */ pm_runtime_put_sync(&dpu_kms->pdev->dev); @@ -831,7 +849,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, } if (is_vid_mode && dpu_enc->rc_state == DPU_ENC_RC_STATE_IDLE) - _dpu_encoder_irq_control(drm_enc, true); + _dpu_encoder_irq_enable(drm_enc); else _dpu_encoder_resource_control_helper(drm_enc, true); @@ -886,7 +904,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, if (is_vid_mode && dpu_enc->rc_state == DPU_ENC_RC_STATE_IDLE) { - _dpu_encoder_irq_control(drm_enc, true); + _dpu_encoder_irq_enable(drm_enc); } /* skip if is already OFF or IDLE, resources are off already */ else if (dpu_enc->rc_state == DPU_ENC_RC_STATE_OFF || @@ -961,7 +979,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, } if (is_vid_mode) - _dpu_encoder_irq_control(drm_enc, false); + _dpu_encoder_irq_disable(drm_enc); else _dpu_encoder_resource_control_helper(drm_enc, false); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 993f26343331..8c5b0c853572 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -85,7 +85,8 @@ struct dpu_encoder_phys; * @handle_post_kickoff: Do any work necessary post-kickoff work * @trigger_start: Process start event on physical encoder * @needs_single_flush: Whether encoder slaves need to be flushed - * @irq_control: Handler to enable/disable all the encoder IRQs + * @irq_enable: Handler to enable all the encoder IRQs + * @irq_disable: Handler to disable all the encoder IRQs * @prepare_idle_pc: phys encoder can update the vsync_enable status * on idle power collapse prepare * @restore: Restore all the encoder configs. @@ -110,7 +111,8 @@ struct dpu_encoder_phys_ops { void (*handle_post_kickoff)(struct dpu_encoder_phys *phys_enc); void (*trigger_start)(struct dpu_encoder_phys *phys_enc); bool (*needs_single_flush)(struct dpu_encoder_phys *phys_enc); - void (*irq_control)(struct dpu_encoder_phys *phys, bool enable); + void (*irq_enable)(struct dpu_encoder_phys *phys); + void (*irq_disable)(struct dpu_encoder_phys *phys); void (*prepare_idle_pc)(struct dpu_encoder_phys *phys_enc); void (*restore)(struct dpu_encoder_phys *phys); int (*get_line_count)(struct dpu_encoder_phys *phys); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index a301e2833177..de826f9745e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -291,40 +291,42 @@ end: return ret; } -static void dpu_encoder_phys_cmd_irq_control(struct dpu_encoder_phys *phys_enc, - bool enable) +static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc) { - trace_dpu_enc_phys_cmd_irq_ctrl(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, - enable, phys_enc->vblank_refcount); + trace_dpu_enc_phys_cmd_irq_enable(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0, + phys_enc->vblank_refcount); - if (enable) { + dpu_core_irq_register_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_PINGPONG], + dpu_encoder_phys_cmd_pp_tx_done_irq, + phys_enc); + dpu_core_irq_register_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_UNDERRUN], + dpu_encoder_phys_cmd_underrun_irq, + phys_enc); + dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, true); + + if (dpu_encoder_phys_cmd_is_master(phys_enc)) dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_PINGPONG], - dpu_encoder_phys_cmd_pp_tx_done_irq, - phys_enc); - dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_UNDERRUN], - dpu_encoder_phys_cmd_underrun_irq, - phys_enc); - dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, true); + phys_enc->irq[INTR_IDX_CTL_START], + dpu_encoder_phys_cmd_ctl_start_irq, + phys_enc); +} - if (dpu_encoder_phys_cmd_is_master(phys_enc)) - dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_CTL_START], - dpu_encoder_phys_cmd_ctl_start_irq, - phys_enc); - } else { - if (dpu_encoder_phys_cmd_is_master(phys_enc)) - dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_CTL_START]); +static void dpu_encoder_phys_cmd_irq_disable(struct dpu_encoder_phys *phys_enc) +{ + trace_dpu_enc_phys_cmd_irq_disable(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0, + phys_enc->vblank_refcount); + if (dpu_encoder_phys_cmd_is_master(phys_enc)) dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_UNDERRUN]); - dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false); - dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_PINGPONG]); - } + phys_enc->irq[INTR_IDX_CTL_START]); + + dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_UNDERRUN]); + dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false); + dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG]); } static void dpu_encoder_phys_cmd_tearcheck_config( @@ -713,7 +715,8 @@ static void dpu_encoder_phys_cmd_init_ops( ops->wait_for_tx_complete = dpu_encoder_phys_cmd_wait_for_tx_complete; ops->trigger_start = dpu_encoder_phys_cmd_trigger_start; ops->needs_single_flush = dpu_encoder_phys_cmd_needs_single_flush; - ops->irq_control = dpu_encoder_phys_cmd_irq_control; + ops->irq_enable = dpu_encoder_phys_cmd_irq_enable; + ops->irq_disable = dpu_encoder_phys_cmd_irq_disable; ops->restore = dpu_encoder_phys_cmd_enable_helper; ops->prepare_idle_pc = dpu_encoder_phys_cmd_prepare_idle_pc; ops->handle_post_kickoff = dpu_encoder_phys_cmd_handle_post_kickoff; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index f562beb6f797..3943d5588ddc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -616,30 +616,33 @@ static void dpu_encoder_phys_vid_handle_post_kickoff( } } -static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc, - bool enable) +static void dpu_encoder_phys_vid_irq_enable(struct dpu_encoder_phys *phys_enc) { int ret; - trace_dpu_enc_phys_vid_irq_ctrl(DRMID(phys_enc->parent), - phys_enc->hw_intf->idx - INTF_0, - enable, - phys_enc->vblank_refcount); + trace_dpu_enc_phys_vid_irq_enable(DRMID(phys_enc->parent), + phys_enc->hw_intf->idx - INTF_0, + phys_enc->vblank_refcount); - if (enable) { - ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true); - if (WARN_ON(ret)) - return; + ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true); + if (WARN_ON(ret)) + return; - dpu_core_irq_register_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_UNDERRUN], - dpu_encoder_phys_vid_underrun_irq, - phys_enc); - } else { - dpu_encoder_phys_vid_control_vblank_irq(phys_enc, false); - dpu_core_irq_unregister_callback(phys_enc->dpu_kms, - phys_enc->irq[INTR_IDX_UNDERRUN]); - } + dpu_core_irq_register_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_UNDERRUN], + dpu_encoder_phys_vid_underrun_irq, + phys_enc); +} + +static void dpu_encoder_phys_vid_irq_disable(struct dpu_encoder_phys *phys_enc) +{ + trace_dpu_enc_phys_vid_irq_disable(DRMID(phys_enc->parent), + phys_enc->hw_intf->idx - INTF_0, + phys_enc->vblank_refcount); + + dpu_encoder_phys_vid_control_vblank_irq(phys_enc, false); + dpu_core_irq_unregister_callback(phys_enc->dpu_kms, + phys_enc->irq[INTR_IDX_UNDERRUN]); } static int dpu_encoder_phys_vid_get_line_count( @@ -690,7 +693,8 @@ static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops) ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq; ops->wait_for_commit_done = dpu_encoder_phys_vid_wait_for_commit_done; ops->wait_for_tx_complete = dpu_encoder_phys_vid_wait_for_tx_complete; - ops->irq_control = dpu_encoder_phys_vid_irq_control; + ops->irq_enable = dpu_encoder_phys_vid_irq_enable; + ops->irq_disable = dpu_encoder_phys_vid_irq_disable; ops->prepare_for_kickoff = dpu_encoder_phys_vid_prepare_for_kickoff; ops->handle_post_kickoff = dpu_encoder_phys_vid_handle_post_kickoff; ops->needs_single_flush = dpu_encoder_phys_vid_needs_single_flush; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 4cd2d9e3131a..602013725484 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -511,21 +511,31 @@ static void dpu_encoder_phys_wb_done_irq(void *arg) } /** - * dpu_encoder_phys_wb_irq_ctrl - irq control of WB + * dpu_encoder_phys_wb_irq_enable - irq control of WB * @phys: Pointer to physical encoder - * @enable: indicates enable or disable interrupts */ -static void dpu_encoder_phys_wb_irq_ctrl( - struct dpu_encoder_phys *phys, bool enable) +static void dpu_encoder_phys_wb_irq_enable(struct dpu_encoder_phys *phys) { struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys); - if (enable && atomic_inc_return(&wb_enc->wbirq_refcount) == 1) + if (atomic_inc_return(&wb_enc->wbirq_refcount) == 1) dpu_core_irq_register_callback(phys->dpu_kms, - phys->irq[INTR_IDX_WB_DONE], dpu_encoder_phys_wb_done_irq, phys); - else if (!enable && - atomic_dec_return(&wb_enc->wbirq_refcount) == 0) + phys->irq[INTR_IDX_WB_DONE], + dpu_encoder_phys_wb_done_irq, + phys); +} + +/** + * dpu_encoder_phys_wb_irq_disable - irq control of WB + * @phys: Pointer to physical encoder + */ +static void dpu_encoder_phys_wb_irq_disable(struct dpu_encoder_phys *phys) +{ + + struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys); + + if (atomic_dec_return(&wb_enc->wbirq_refcount) == 0) dpu_core_irq_unregister_callback(phys->dpu_kms, phys->irq[INTR_IDX_WB_DONE]); } @@ -785,7 +795,8 @@ static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) ops->trigger_start = dpu_encoder_helper_trigger_start; ops->prepare_wb_job = dpu_encoder_phys_wb_prepare_wb_job; ops->cleanup_wb_job = dpu_encoder_phys_wb_cleanup_wb_job; - ops->irq_control = dpu_encoder_phys_wb_irq_ctrl; + ops->irq_enable = dpu_encoder_phys_wb_irq_enable; + ops->irq_disable = dpu_encoder_phys_wb_irq_disable; ops->is_valid_for_commit = dpu_encoder_phys_wb_is_valid_for_commit; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 35d03b121a0b..95ce7647ff76 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -514,24 +514,41 @@ TRACE_EVENT(dpu_enc_wait_event_timeout, __entry->expected_time, __entry->atomic_cnt) ); -TRACE_EVENT(dpu_enc_phys_cmd_irq_ctrl, - TP_PROTO(uint32_t drm_id, enum dpu_pingpong pp, bool enable, +TRACE_EVENT(dpu_enc_phys_cmd_irq_enable, + TP_PROTO(uint32_t drm_id, enum dpu_pingpong pp, int refcnt), - TP_ARGS(drm_id, pp, enable, refcnt), + TP_ARGS(drm_id, pp, refcnt), TP_STRUCT__entry( __field( uint32_t, drm_id ) __field( enum dpu_pingpong, pp ) - __field( bool, enable ) __field( int, refcnt ) ), TP_fast_assign( __entry->drm_id = drm_id; __entry->pp = pp; - __entry->enable = enable; __entry->refcnt = refcnt; ), - TP_printk("id=%u, pp=%d, enable=%s, refcnt=%d", __entry->drm_id, - __entry->pp, __entry->enable ? "true" : "false", + TP_printk("id=%u, pp=%d, refcnt=%d", __entry->drm_id, + __entry->pp, + __entry->refcnt) +); + +TRACE_EVENT(dpu_enc_phys_cmd_irq_disable, + TP_PROTO(uint32_t drm_id, enum dpu_pingpong pp, + int refcnt), + TP_ARGS(drm_id, pp, refcnt), + TP_STRUCT__entry( + __field( uint32_t, drm_id ) + __field( enum dpu_pingpong, pp ) + __field( int, refcnt ) + ), + TP_fast_assign( + __entry->drm_id = drm_id; + __entry->pp = pp; + __entry->refcnt = refcnt; + ), + TP_printk("id=%u, pp=%d, refcnt=%d", __entry->drm_id, + __entry->pp, __entry->refcnt) ); @@ -592,24 +609,41 @@ TRACE_EVENT(dpu_enc_phys_vid_post_kickoff, TP_printk("id=%u, intf_idx=%d", __entry->drm_id, __entry->intf_idx) ); -TRACE_EVENT(dpu_enc_phys_vid_irq_ctrl, - TP_PROTO(uint32_t drm_id, enum dpu_intf intf_idx, bool enable, +TRACE_EVENT(dpu_enc_phys_vid_irq_enable, + TP_PROTO(uint32_t drm_id, enum dpu_intf intf_idx, int refcnt), - TP_ARGS(drm_id, intf_idx, enable, refcnt), + TP_ARGS(drm_id, intf_idx, refcnt), TP_STRUCT__entry( __field( uint32_t, drm_id ) __field( enum dpu_intf, intf_idx ) - __field( bool, enable ) __field( int, refcnt ) ), TP_fast_assign( __entry->drm_id = drm_id; __entry->intf_idx = intf_idx; - __entry->enable = enable; __entry->refcnt = refcnt; ), - TP_printk("id=%u, intf_idx=%d enable=%s refcnt=%d", __entry->drm_id, - __entry->intf_idx, __entry->enable ? "true" : "false", + TP_printk("id=%u, intf_idx=%d refcnt=%d", __entry->drm_id, + __entry->intf_idx, + __entry->drm_id) +); + +TRACE_EVENT(dpu_enc_phys_vid_irq_disable, + TP_PROTO(uint32_t drm_id, enum dpu_intf intf_idx, + int refcnt), + TP_ARGS(drm_id, intf_idx, refcnt), + TP_STRUCT__entry( + __field( uint32_t, drm_id ) + __field( enum dpu_intf, intf_idx ) + __field( int, refcnt ) + ), + TP_fast_assign( + __entry->drm_id = drm_id; + __entry->intf_idx = intf_idx; + __entry->refcnt = refcnt; + ), + TP_printk("id=%u, intf_idx=%d refcnt=%d", __entry->drm_id, + __entry->intf_idx, __entry->drm_id) ); From ca8c1fd3eed8c9f24ae0d49505368dc2bed1c3fd Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:20:42 +0200 Subject: [PATCH 058/295] drm/msm/dpu: split _dpu_encoder_resource_control_helper() Follow the _dpu_encoder_irq_control() change and split the _dpu_encoder_resource_control_helper() into enable and disable parts. Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577525/ Link: https://lore.kernel.org/r/20240208-fd_remove_phys_ops_atomic_mode_set-v4-2-caf5dcd125c0@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 45 +++++++++++++-------- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 12 ++++-- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 2bb249c56400..b740bbbfbf4e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -761,8 +761,7 @@ static void _dpu_encoder_irq_disable(struct drm_encoder *drm_enc) } } -static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, - bool enable) +static void _dpu_encoder_resource_enable(struct drm_encoder *drm_enc) { struct msm_drm_private *priv; struct dpu_kms *dpu_kms; @@ -772,28 +771,42 @@ static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); - trace_dpu_enc_rc_helper(DRMID(drm_enc), enable); + trace_dpu_enc_rc_enable(DRMID(drm_enc)); if (!dpu_enc->cur_master) { DPU_ERROR("encoder master not set\n"); return; } - if (enable) { - /* enable DPU core clks */ - pm_runtime_get_sync(&dpu_kms->pdev->dev); + /* enable DPU core clks */ + pm_runtime_get_sync(&dpu_kms->pdev->dev); - /* enable all the irq */ - _dpu_encoder_irq_enable(drm_enc); + /* enable all the irq */ + _dpu_encoder_irq_enable(drm_enc); +} - } else { - /* disable all the irq */ - _dpu_encoder_irq_disable(drm_enc); +static void _dpu_encoder_resource_disable(struct drm_encoder *drm_enc) +{ + struct msm_drm_private *priv; + struct dpu_kms *dpu_kms; + struct dpu_encoder_virt *dpu_enc; - /* disable DPU core clks */ - pm_runtime_put_sync(&dpu_kms->pdev->dev); + dpu_enc = to_dpu_encoder_virt(drm_enc); + priv = drm_enc->dev->dev_private; + dpu_kms = to_dpu_kms(priv->kms); + + trace_dpu_enc_rc_disable(DRMID(drm_enc)); + + if (!dpu_enc->cur_master) { + DPU_ERROR("encoder master not set\n"); + return; } + /* disable all the irq */ + _dpu_encoder_irq_disable(drm_enc); + + /* disable DPU core clks */ + pm_runtime_put_sync(&dpu_kms->pdev->dev); } static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, @@ -851,7 +864,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, if (is_vid_mode && dpu_enc->rc_state == DPU_ENC_RC_STATE_IDLE) _dpu_encoder_irq_enable(drm_enc); else - _dpu_encoder_resource_control_helper(drm_enc, true); + _dpu_encoder_resource_enable(drm_enc); dpu_enc->rc_state = DPU_ENC_RC_STATE_ON; @@ -946,7 +959,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, * and in IDLE state the resources are already disabled */ if (dpu_enc->rc_state == DPU_ENC_RC_STATE_PRE_OFF) - _dpu_encoder_resource_control_helper(drm_enc, false); + _dpu_encoder_resource_disable(drm_enc); dpu_enc->rc_state = DPU_ENC_RC_STATE_OFF; @@ -981,7 +994,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, if (is_vid_mode) _dpu_encoder_irq_disable(drm_enc); else - _dpu_encoder_resource_control_helper(drm_enc, false); + _dpu_encoder_resource_disable(drm_enc); dpu_enc->rc_state = DPU_ENC_RC_STATE_IDLE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 95ce7647ff76..bd92fb2979aa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -273,6 +273,14 @@ DEFINE_EVENT(dpu_drm_obj_template, dpu_crtc_runtime_resume, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) ); +DEFINE_EVENT(dpu_drm_obj_template, dpu_enc_rc_enable, + TP_PROTO(uint32_t drm_id), + TP_ARGS(drm_id) +); +DEFINE_EVENT(dpu_drm_obj_template, dpu_enc_rc_disable, + TP_PROTO(uint32_t drm_id), + TP_ARGS(drm_id) +); TRACE_EVENT(dpu_enc_enable, TP_PROTO(uint32_t drm_id, int hdisplay, int vdisplay), @@ -342,10 +350,6 @@ DECLARE_EVENT_CLASS(dpu_enc_id_enable_template, TP_printk("id=%u, enable=%s", __entry->drm_id, __entry->enable ? "true" : "false") ); -DEFINE_EVENT(dpu_enc_id_enable_template, dpu_enc_rc_helper, - TP_PROTO(uint32_t drm_id, bool enable), - TP_ARGS(drm_id, enable) -); DEFINE_EVENT(dpu_enc_id_enable_template, dpu_enc_vblank_cb, TP_PROTO(uint32_t drm_id, bool enable), TP_ARGS(drm_id, enable) From d13f638c9b88e9921d39d133a797e80aa1c235f0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:20:43 +0200 Subject: [PATCH 059/295] drm/msm/dpu: drop dpu_encoder_phys_ops.atomic_mode_set The atomic_mode_set() callback only sets the phys_enc's IRQ data. As the INTF and WB are statically allocated to each encoder/phys_enc, drop the atomic_mode_set callback and set the IRQs during encoder init. For the CMD panel usecase some of IRQ indexes depend on the selected resources. Move setting them to the irq_enable() callback. Reviewed-by: Abhinav Kumar Tested-by: Abhinav Kumar # sc7280 Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577529/ Link: https://lore.kernel.org/r/20240208-fd_remove_phys_ops_atomic_mode_set-v4-3-caf5dcd125c0@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 -- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 5 --- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 32 ++++++++----------- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 13 ++------ .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 11 +------ 5 files changed, 17 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b740bbbfbf4e..679131f5c035 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1159,8 +1159,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); phys->cached_mode = crtc_state->adjusted_mode; - if (phys->ops.atomic_mode_set) - phys->ops.atomic_mode_set(phys, crtc_state, conn_state); } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 8c5b0c853572..7eb8bdfe6bbe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -69,8 +69,6 @@ struct dpu_encoder_phys; * @is_master: Whether this phys_enc is the current master * encoder. Can be switched at enable time. Based * on split_role and current mode (CMD/VID). - * @atomic_mode_set: DRM Call. Set a DRM mode. - * This likely caches the mode, for use at enable. * @enable: DRM Call. Enable a DRM mode. * @disable: DRM Call. Disable mode. * @atomic_check: DRM Call. Atomic check new DRM state. @@ -96,9 +94,6 @@ struct dpu_encoder_phys; struct dpu_encoder_phys_ops { void (*prepare_commit)(struct dpu_encoder_phys *encoder); bool (*is_master)(struct dpu_encoder_phys *encoder); - void (*atomic_mode_set)(struct dpu_encoder_phys *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state); void (*enable)(struct dpu_encoder_phys *encoder); void (*disable)(struct dpu_encoder_phys *encoder); int (*atomic_check)(struct dpu_encoder_phys *encoder, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index de826f9745e5..fc1d5736d7fc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -142,23 +142,6 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg) dpu_encoder_underrun_callback(phys_enc->parent, phys_enc); } -static void dpu_encoder_phys_cmd_atomic_mode_set( - struct dpu_encoder_phys *phys_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start; - - phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done; - - if (phys_enc->has_intf_te) - phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr; - else - phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr; - - phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun; -} - static int _dpu_encoder_phys_cmd_handle_ppdone_timeout( struct dpu_encoder_phys *phys_enc) { @@ -297,6 +280,14 @@ static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc) phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->vblank_refcount); + phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start; + phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done; + + if (phys_enc->has_intf_te) + phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr; + else + phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr; + dpu_core_irq_register_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG], dpu_encoder_phys_cmd_pp_tx_done_irq, @@ -327,6 +318,10 @@ static void dpu_encoder_phys_cmd_irq_disable(struct dpu_encoder_phys *phys_enc) dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_UNDERRUN]); dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false); dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG]); + + phys_enc->irq[INTR_IDX_CTL_START] = 0; + phys_enc->irq[INTR_IDX_PINGPONG] = 0; + phys_enc->irq[INTR_IDX_RDPTR] = 0; } static void dpu_encoder_phys_cmd_tearcheck_config( @@ -706,7 +701,6 @@ static void dpu_encoder_phys_cmd_init_ops( struct dpu_encoder_phys_ops *ops) { ops->is_master = dpu_encoder_phys_cmd_is_master; - ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set; ops->enable = dpu_encoder_phys_cmd_enable; ops->disable = dpu_encoder_phys_cmd_disable; ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq; @@ -745,6 +739,8 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev, dpu_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->intf_mode = INTF_MODE_CMD; + phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun; + cmd_enc->stream_sel = 0; if (!phys_enc->hw_intf) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 3943d5588ddc..2aa72b578764 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -350,16 +350,6 @@ static bool dpu_encoder_phys_vid_needs_single_flush( return phys_enc->split_role != ENC_ROLE_SOLO; } -static void dpu_encoder_phys_vid_atomic_mode_set( - struct dpu_encoder_phys *phys_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync; - - phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun; -} - static int dpu_encoder_phys_vid_control_vblank_irq( struct dpu_encoder_phys *phys_enc, bool enable) @@ -687,7 +677,6 @@ static int dpu_encoder_phys_vid_get_frame_count( static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops) { ops->is_master = dpu_encoder_phys_vid_is_master; - ops->atomic_mode_set = dpu_encoder_phys_vid_atomic_mode_set; ops->enable = dpu_encoder_phys_vid_enable; ops->disable = dpu_encoder_phys_vid_disable; ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq; @@ -726,6 +715,8 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev, dpu_encoder_phys_vid_init_ops(&phys_enc->ops); phys_enc->intf_mode = INTF_MODE_VIDEO; + phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync; + phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun; DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->hw_intf->idx); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 602013725484..a0a28230fc31 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -539,15 +539,6 @@ static void dpu_encoder_phys_wb_irq_disable(struct dpu_encoder_phys *phys) dpu_core_irq_unregister_callback(phys->dpu_kms, phys->irq[INTR_IDX_WB_DONE]); } -static void dpu_encoder_phys_wb_atomic_mode_set( - struct dpu_encoder_phys *phys_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - - phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done; -} - static void _dpu_encoder_phys_wb_handle_wbdone_timeout( struct dpu_encoder_phys *phys_enc) { @@ -784,7 +775,6 @@ static bool dpu_encoder_phys_wb_is_valid_for_commit(struct dpu_encoder_phys *phy static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) { ops->is_master = dpu_encoder_phys_wb_is_master; - ops->atomic_mode_set = dpu_encoder_phys_wb_atomic_mode_set; ops->enable = dpu_encoder_phys_wb_enable; ops->disable = dpu_encoder_phys_wb_disable; ops->atomic_check = dpu_encoder_phys_wb_atomic_check; @@ -831,6 +821,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev, dpu_encoder_phys_wb_init_ops(&phys_enc->ops); phys_enc->intf_mode = INTF_MODE_WB_LINE; + phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done; atomic_set(&wb_enc->wbirq_refcount, 0); From 71174f362d6750c789a3137cb7ea6d695dc5b659 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:20:44 +0200 Subject: [PATCH 060/295] drm/msm/dpu: move writeback's atomic_check to dpu_writeback.c dpu_encoder_phys_wb is the only user of encoder's atomic_check callback. Move corresponding checks to drm_writeback_connector's implementation and drop the dpu_encoder_phys_wb_atomic_check() function. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Tested-by: Paloma Arellano Patchwork: https://patchwork.freedesktop.org/patch/577524/ Link: https://lore.kernel.org/r/20240208-fd_remove_phys_ops_atomic_mode_set-v4-4-caf5dcd125c0@linaro.org --- .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 54 ---------------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 61 ++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h | 3 +- 4 files changed, 68 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index a0a28230fc31..8220cd920e6f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -354,59 +354,6 @@ static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc) } } -/** - * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic states - * @phys_enc: Pointer to physical encoder - * @crtc_state: Pointer to CRTC atomic state - * @conn_state: Pointer to connector atomic state - */ -static int dpu_encoder_phys_wb_atomic_check( - struct dpu_encoder_phys *phys_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct drm_framebuffer *fb; - const struct drm_display_mode *mode = &crtc_state->mode; - - DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n", - phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay); - - if (!conn_state || !conn_state->connector) { - DPU_ERROR("invalid connector state\n"); - return -EINVAL; - } else if (conn_state->connector->status != - connector_status_connected) { - DPU_ERROR("connector not connected %d\n", - conn_state->connector->status); - return -EINVAL; - } - - if (!conn_state->writeback_job || !conn_state->writeback_job->fb) - return 0; - - fb = conn_state->writeback_job->fb; - - DPU_DEBUG("[fb_id:%u][fb:%u,%u]\n", fb->base.id, - fb->width, fb->height); - - if (fb->width != mode->hdisplay) { - DPU_ERROR("invalid fb w=%d, mode w=%d\n", fb->width, - mode->hdisplay); - return -EINVAL; - } else if (fb->height != mode->vdisplay) { - DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height, - mode->vdisplay); - return -EINVAL; - } else if (fb->width > phys_enc->hw_wb->caps->maxlinewidth) { - DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n", - fb->width, phys_enc->hw_wb->caps->maxlinewidth); - return -EINVAL; - } - - return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state); -} - - /** * _dpu_encoder_phys_wb_update_flush - flush hardware update * @phys_enc: Pointer to physical encoder @@ -777,7 +724,6 @@ static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) ops->is_master = dpu_encoder_phys_wb_is_master; ops->enable = dpu_encoder_phys_wb_enable; ops->disable = dpu_encoder_phys_wb_disable; - ops->atomic_check = dpu_encoder_phys_wb_atomic_check; ops->wait_for_commit_done = dpu_encoder_phys_wb_wait_for_commit_done; ops->prepare_for_kickoff = dpu_encoder_phys_wb_prepare_for_kickoff; ops->handle_post_kickoff = dpu_encoder_phys_wb_handle_post_kickoff; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 723cc1d82143..48728be27e15 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -630,23 +630,26 @@ static int _dpu_kms_initialize_writeback(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; + const enum dpu_wb wb_idx = WB_2; + u32 maxlinewidth; int rc; memset(&info, 0, sizeof(info)); info.num_of_h_tiles = 1; /* use only WB idx 2 instance for DPU */ - info.h_tile_instance[0] = WB_2; + info.h_tile_instance[0] = wb_idx; info.intf_type = INTF_WB; + maxlinewidth = dpu_rm_get_wb(&dpu_kms->rm, info.h_tile_instance[0])->caps->maxlinewidth; + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL, &info); if (IS_ERR(encoder)) { DPU_ERROR("encoder init failed for dsi display\n"); return PTR_ERR(encoder); } - rc = dpu_writeback_init(dev, encoder, wb_formats, - n_formats); + rc = dpu_writeback_init(dev, encoder, wb_formats, n_formats, maxlinewidth); if (rc) { DPU_ERROR("dpu_writeback_init, rc = %d\n", rc); return rc; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index 2a5a68366582..16f144cbc0c9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -4,6 +4,7 @@ */ #include +#include #include "dpu_writeback.h" @@ -24,6 +25,61 @@ static int dpu_wb_conn_get_modes(struct drm_connector *connector) dev->mode_config.max_height); } +static int dpu_wb_conn_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_writeback_connector *wb_conn = drm_connector_to_writeback(connector); + struct dpu_wb_connector *dpu_wb_conn = to_dpu_wb_conn(wb_conn); + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(state, connector); + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + const struct drm_display_mode *mode; + struct drm_framebuffer *fb; + + DPU_DEBUG("[atomic_check:%d]\n", connector->base.id); + + if (!conn_state || !conn_state->connector) { + DPU_ERROR("invalid connector state\n"); + return -EINVAL; + } else if (conn_state->connector->status != connector_status_connected) { + DPU_ERROR("connector not connected %d\n", conn_state->connector->status); + return -EINVAL; + } + + crtc = conn_state->crtc; + if (!crtc) + return 0; + + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + mode = &crtc_state->mode; + + fb = conn_state->writeback_job->fb; + + DPU_DEBUG("[fb_id:%u][fb:%u,%u][mode:\"%s\":%ux%u]\n", fb->base.id, fb->width, fb->height, + mode->name, mode->hdisplay, mode->vdisplay); + + if (fb->width != mode->hdisplay) { + DPU_ERROR("invalid fb w=%d, mode w=%d\n", fb->width, mode->hdisplay); + return -EINVAL; + } else if (fb->height != mode->vdisplay) { + DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height, mode->vdisplay); + return -EINVAL; + } else if (fb->width > dpu_wb_conn->maxlinewidth) { + DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n", + fb->width, dpu_wb_conn->maxlinewidth); + return -EINVAL; + } + + return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state); +} + static const struct drm_connector_funcs dpu_wb_conn_funcs = { .reset = drm_atomic_helper_connector_reset, .fill_modes = drm_helper_probe_single_connector_modes, @@ -59,12 +115,13 @@ static void dpu_wb_conn_cleanup_job(struct drm_writeback_connector *connector, static const struct drm_connector_helper_funcs dpu_wb_conn_helper_funcs = { .get_modes = dpu_wb_conn_get_modes, + .atomic_check = dpu_wb_conn_atomic_check, .prepare_writeback_job = dpu_wb_conn_prepare_job, .cleanup_writeback_job = dpu_wb_conn_cleanup_job, }; int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc, - const u32 *format_list, u32 num_formats) + const u32 *format_list, u32 num_formats, u32 maxlinewidth) { struct dpu_wb_connector *dpu_wb_conn; int rc = 0; @@ -73,6 +130,8 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc, if (!dpu_wb_conn) return -ENOMEM; + dpu_wb_conn->maxlinewidth = maxlinewidth; + drm_connector_helper_add(&dpu_wb_conn->base.base, &dpu_wb_conn_helper_funcs); /* DPU initializes the encoder and sets it up completely for writeback diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h index 5a75ea916101..4b11cca8014c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.h @@ -18,6 +18,7 @@ struct dpu_wb_connector { struct drm_writeback_connector base; struct drm_encoder *wb_enc; + u32 maxlinewidth; }; static inline struct dpu_wb_connector *to_dpu_wb_conn(struct drm_writeback_connector *conn) @@ -26,6 +27,6 @@ static inline struct dpu_wb_connector *to_dpu_wb_conn(struct drm_writeback_conne } int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc, - const u32 *format_list, u32 num_formats); + const u32 *format_list, u32 num_formats, u32 maxlinewidth); #endif /*_DPU_WRITEBACK_H */ From b0b621f41b45b18fe47cb0f612ec86623f9b709c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:20:45 +0200 Subject: [PATCH 061/295] drm/msm/dpu: drop dpu_encoder_phys_ops::atomic_check() Writeback was the last user of dpu_encoder_phys_ops's atomic_check() callback. As the code was moved to the dpu_writeback.c, the callback becomes unused. Drop it now. Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577528/ Link: https://lore.kernel.org/r/20240208-fd_remove_phys_ops_atomic_mode_set-v4-5-caf5dcd125c0@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 15 --------------- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 4 ---- 2 files changed, 19 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 679131f5c035..194dbb08331d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -591,7 +591,6 @@ static int dpu_encoder_virt_atomic_check( struct dpu_global_state *global_state; struct drm_framebuffer *fb; struct drm_dsc_config *dsc; - int i = 0; int ret = 0; if (!drm_enc || !crtc_state || !conn_state) { @@ -612,20 +611,6 @@ static int dpu_encoder_virt_atomic_check( trace_dpu_enc_atomic_check(DRMID(drm_enc)); - /* perform atomic check on the first physical encoder (master) */ - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - - if (phys->ops.atomic_check) - ret = phys->ops.atomic_check(phys, crtc_state, - conn_state); - if (ret) { - DPU_ERROR_ENC(dpu_enc, - "mode unsupported, phys idx %d\n", i); - return ret; - } - } - dsc = dpu_encoder_get_dsc_config(drm_enc); topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 7eb8bdfe6bbe..dd9e3603d120 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -71,7 +71,6 @@ struct dpu_encoder_phys; * on split_role and current mode (CMD/VID). * @enable: DRM Call. Enable a DRM mode. * @disable: DRM Call. Disable mode. - * @atomic_check: DRM Call. Atomic check new DRM state. * @control_vblank_irq Register/Deregister for VBLANK IRQ * @wait_for_commit_done: Wait for hardware to have flushed the * current pending frames to hardware @@ -96,9 +95,6 @@ struct dpu_encoder_phys_ops { bool (*is_master)(struct dpu_encoder_phys *encoder); void (*enable)(struct dpu_encoder_phys *encoder); void (*disable)(struct dpu_encoder_phys *encoder); - int (*atomic_check)(struct dpu_encoder_phys *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state); int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable); int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc); int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc); From 3b56d27ba1578c3d61f51de4102cf896a9a8617e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:23:08 +0200 Subject: [PATCH 062/295] drm/msm/dsi: Document DSC related pclk_rate and hdisplay calculations Provide actual documentation for the pclk and hdisplay calculations in the case of DSC compression being used. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/577534/ Link: https://lore.kernel.org/r/20240208-fd_document_dsc_pclk_rate-v4-1-56fe59d0a2e0@linaro.org --- drivers/gpu/drm/msm/dsi/dsi_host.c | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 9fa0053fac74..9d86a6aca6f2 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -519,6 +519,25 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); } +/** + * dsi_adjust_pclk_for_compression() - Adjust the pclk rate for compression case + * @mode: The selected mode for the DSI output + * @dsc: DRM DSC configuration for this DSI output + * + * Adjust the pclk rate by calculating a new hdisplay proportional to + * the compression ratio such that: + * new_hdisplay = old_hdisplay * compressed_bpp / uncompressed_bpp + * + * Porches do not need to be adjusted: + * - For VIDEO mode they are not compressed by DSC and are passed as is. + * - For CMD mode there are no actual porches. Instead these fields + * currently represent the overhead to the image data transfer. As such, they + * are calculated for the final mode parameters (after the compression) and + * are not to be adjusted too. + * + * FIXME: Reconsider this if/when CMD mode handling is rewritten to use + * transfer time and data overhead as a starting point of the calculations. + */ static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode, const struct drm_dsc_config *dsc) { @@ -941,8 +960,18 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (ret) return; - /* Divide the display by 3 but keep back/font porch and - * pulse width same + /* + * DPU sends 3 bytes per pclk cycle to DSI. If widebus is + * enabled, bus width is extended to 6 bytes. + * + * Calculate the number of pclks needed to transmit one line of + * the compressed data. + + * The back/font porch and pulse width are kept intact. For + * VIDEO mode they represent timing parameters rather than + * actual data transfer, see the documentation for + * dsi_adjust_pclk_for_compression(). For CMD mode they are + * unused anyway. */ h_total -= hdisplay; if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) From 00c3959d63ae52e98b8e6776c9dba65291f8d137 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Mon, 12 Feb 2024 18:20:11 +0530 Subject: [PATCH 063/295] drm/i915: Add bigjoiner force enable option to debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For validation purposes, it might be useful to be able to force Bigjoiner mode, even if current dotclock/resolution do not require that. Lets add such to option to debugfs. v2: - Apparently intel_dp_need_bigjoiner can't be used, when debugfs entry is created so lets just check manually the DISPLAY_VER. v3: - Switch to intel_connector from drm_connector(Jani Nikula) - Remove redundant modeset lock(Jani Nikula) - Use kstrtobool_from_user for boolean value(Jani Nikula) v4: - Apply the changes to proper function(Jani Nikula) v5: - Removed unnecessary check from i915_bigjoiner_enable_show (Ville Syrjälä) - Added eDP connector check to intel_connector_debugfs_add (Ville Syrjälä) - Removed debug message in order to prevent dmesg flooding (Ville Syrjälä) v6: - Assume now always that m->private is intel_connector - Fixed other similar conflicts v7: - Move bigjoiner force option to intel_connector(Ville Syrjälä) - Use DEFINE_SHOW_STORE_ATTRIBUTE instead of defining fops manually.(Ville Syrjälä) v8: - Pass intel_connector to debugfs_create_file, instead of drm_connector. (Jani Nikula) Signed-off-by: Stanislav Lisovskiy Acked-by: Jani Nikula Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20240212125011.66174-1-uma.shankar@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 47 +++++++++++++++++++ .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/display/intel_dp.c | 4 +- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 6f2d13c8ccf7..a962b48bcf13 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1391,6 +1391,20 @@ out: drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); return ret; } +static int i915_bigjoiner_enable_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + struct drm_crtc *crtc; + + crtc = connector->base.state->crtc; + if (connector->base.status != connector_status_connected || !crtc) + return -ENODEV; + + seq_printf(m, "Bigjoiner enable: %d\n", connector->force_bigjoiner_enable); + + return 0; +} + static ssize_t i915_dsc_output_format_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) @@ -1412,6 +1426,30 @@ static ssize_t i915_dsc_output_format_write(struct file *file, return len; } +static ssize_t i915_bigjoiner_enable_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 drm_crtc *crtc; + bool bigjoiner_en = 0; + int ret; + + crtc = connector->base.state->crtc; + if (connector->base.status != connector_status_connected || !crtc) + return -ENODEV; + + ret = kstrtobool_from_user(ubuf, len, &bigjoiner_en); + if (ret < 0) + return ret; + + connector->force_bigjoiner_enable = bigjoiner_en; + *offp += len; + + return len; +} + static int i915_dsc_output_format_open(struct inode *inode, struct file *file) { @@ -1505,6 +1543,8 @@ static const struct file_operations i915_dsc_fractional_bpp_fops = { .write = i915_dsc_fractional_bpp_write }; +DEFINE_SHOW_STORE_ATTRIBUTE(i915_bigjoiner_enable); + /* * Returns the Current CRTC's bpc. * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc @@ -1586,6 +1626,13 @@ void intel_connector_debugfs_add(struct intel_connector *connector) connector, &i915_dsc_fractional_bpp_fops); } + if (DISPLAY_VER(i915) >= 11 && + (connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector_type == DRM_MODE_CONNECTOR_eDP)) { + debugfs_create_file("i915_bigjoiner_force_enable", 0644, root, + connector, &i915_bigjoiner_enable_fops); + } + if (connector_type == DRM_MODE_CONNECTOR_DSI || connector_type == DRM_MODE_CONNECTOR_eDP || connector_type == DRM_MODE_CONNECTOR_DisplayPort || diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 01eb6e4e6049..0d4012097db1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -626,6 +626,8 @@ struct intel_connector { struct intel_dp *mst_port; + bool force_bigjoiner_enable; + struct { struct drm_dp_aux *dsc_decompression_aux; u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5045c34a16be..217196196e50 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1205,11 +1205,13 @@ bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_connector *connector = intel_dp->attached_connector; if (!intel_dp_can_bigjoiner(intel_dp)) return false; - return clock > i915->max_dotclk_freq || hdisplay > 5120; + return clock > i915->max_dotclk_freq || hdisplay > 5120 || + connector->force_bigjoiner_enable; } static enum drm_mode_status From 5c5a7fa612139e481e2fab368ddd86ae18866547 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 12 Feb 2024 19:52:36 +0200 Subject: [PATCH 064/295] drm/i915: Prevent HW access during init from SDVO TV get_modes hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent accessing the HW from the SDVO/TV get_modes connector hook. Returning 0 from the hook will make the caller - drm_helper_probe_single_connector_modes() - return a default/EDID override mode list to users. This matches the case where intel_sdvo_get_tv_modes() fails to retrieve the current mode list due to a HW access failure. v2: Clarify the commit message wrt. which modes get_modes() returns. (Jouni) Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20240212175237.2625812-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_sdvo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 66dab0a37e65..eb65c8124e60 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2312,6 +2312,9 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector) drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + if (!intel_display_driver_check_access(i915)) + return 0; + /* * Read the list of supported input resolutions for the selected TV * format. From 3a86cb16ab329b235ecd26adce584e5cb0c808d4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 12 Feb 2024 19:52:37 +0200 Subject: [PATCH 065/295] drm/i915: Prevent HW access during init from connector get_modes hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent accessing the HW from the get_modes hooks of connectors deriving the mode list from the display's EDID. drm_edid_connector_add_modes() will return the mode list based on the EDID which was cached during a previous detection/get_modes call. This also fixes the NULL deref problem (10085) which was introduced/revealed by commit bab87ef4db9a ("drm/i915: Disable hotplug detection handlers during driver init/shutdown") After the above change MST connectors will not change state during driver init/shutdown; thus some of these connectors with no I2C/DDC adapter registered for them (since the given MST port has no sink connected) may stay then in the 'unknown' connector status. The get_modes() hook should not try to use the I2C/DDC adapter in this state (which would lead to the above NULL deref) which this patch ensures. v2: - Remove the redundant check from intel_crt_ddc_get_modes(). - Rebase on latest drm-tip. - Add Fixes: line / related commit notes. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10085 Fixes: bab87ef4db9a ("drm/i915: Disable hotplug detection handlers during driver init/shutdown") Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20240212175237.2625812-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_crt.c | 3 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ drivers/gpu/drm/i915/display/intel_dvo.c | 5 +++++ drivers/gpu/drm/i915/display/intel_sdvo.c | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index b9733a73e21d..93479db0f89f 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -933,6 +933,9 @@ static int intel_crt_get_modes(struct drm_connector *connector) struct i2c_adapter *ddc; int ret; + if (!intel_display_driver_check_access(dev_priv)) + return drm_edid_connector_add_modes(connector); + wakeref = intel_display_power_get(dev_priv, intel_encoder->power_domain); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 5fa25a5a36b5..5307ddd4edcf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1197,6 +1197,7 @@ static bool intel_dp_mst_initial_fastset_check(struct intel_encoder *encoder, static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); + struct drm_i915_private *i915 = to_i915(intel_connector->base.dev); struct intel_dp *intel_dp = intel_connector->mst_port; const struct drm_edid *drm_edid; int ret; @@ -1204,6 +1205,9 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) if (drm_connector_is_unregistered(connector)) return intel_connector_update_modes(connector, NULL); + if (!intel_display_driver_check_access(i915)) + return drm_edid_connector_add_modes(connector); + drm_edid = drm_dp_mst_edid_read(connector, &intel_dp->mst_mgr, intel_connector->port); ret = intel_connector_update_modes(connector, drm_edid); diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 8ca9ae4798a8..c076da75b066 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -30,6 +30,7 @@ #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -338,8 +339,12 @@ intel_dvo_detect(struct drm_connector *_connector, bool force) static int intel_dvo_get_modes(struct drm_connector *_connector) { struct intel_connector *connector = to_intel_connector(_connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int num_modes; + if (!intel_display_driver_check_access(i915)) + return drm_edid_connector_add_modes(&connector->base); + /* * We should probably have an i2c driver get_modes function for those * devices which will have a fixed set of modes determined by the chip diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index eb65c8124e60..3b79488357ba 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2202,12 +2202,16 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) static int intel_sdvo_get_ddc_modes(struct drm_connector *connector) { + struct drm_i915_private *i915 = to_i915(connector->dev); int num_modes = 0; const struct drm_edid *drm_edid; drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + if (!intel_display_driver_check_access(i915)) + return drm_edid_connector_add_modes(connector); + /* set the bus switch and get the modes */ drm_edid = intel_sdvo_get_edid(connector); From d9b904d2efdf2abb9e0f7162544da562101872cb Mon Sep 17 00:00:00 2001 From: Ravi Kumar Vodapalli Date: Wed, 14 Feb 2024 12:39:30 +0530 Subject: [PATCH 066/295] drm/i915/display: update pll values in sync with Bspec for MTL DP/eDP and HDMI C20 PHY PLL values were updated for MTL platform Signed-off-by: Ravi Kumar Vodapalli Reviewed-by: Mika Kahola Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240214070930.1028456-1-ravi.kumar.vodapalli@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 288a00e083c8..64e0f820a789 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -848,10 +848,10 @@ static const struct intel_c20pll_state mtl_c20_dp_hbr3 = { static const struct intel_c20pll_state mtl_c20_dp_uhbr10 = { .clock = 1000000, /* 10 Gbps */ .tx = { 0xbe21, /* tx cfg0 */ - 0x4800, /* tx cfg1 */ + 0xe800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, - .cmn = {0x0500, /* cmn cfg0*/ + .cmn = {0x0700, /* cmn cfg0*/ 0x0005, /* cmn cfg1 */ 0x0000, /* cmn cfg2 */ 0x0000, /* cmn cfg3 */ @@ -1641,7 +1641,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_594 = { static const struct intel_c20pll_state mtl_c20_hdmi_300 = { .clock = 3000000, .tx = { 0xbe98, /* tx cfg0 */ - 0x9800, /* tx cfg1 */ + 0x8800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, .cmn = { 0x0500, /* cmn cfg0*/ @@ -1649,8 +1649,8 @@ static const struct intel_c20pll_state mtl_c20_hdmi_300 = { 0x0000, /* cmn cfg2 */ 0x0000, /* cmn cfg3 */ }, - .mpllb = { 0x209c, /* mpllb cfg0 */ - 0x7d10, /* mpllb cfg1 */ + .mpllb = { 0x309c, /* mpllb cfg0 */ + 0x2110, /* mpllb cfg1 */ 0xca06, /* mpllb cfg2 */ 0xbe40, /* mpllb cfg3 */ 0x0000, /* mpllb cfg4 */ @@ -1666,7 +1666,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_300 = { static const struct intel_c20pll_state mtl_c20_hdmi_600 = { .clock = 6000000, .tx = { 0xbe98, /* tx cfg0 */ - 0x9800, /* tx cfg1 */ + 0x8800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, .cmn = { 0x0500, /* cmn cfg0*/ @@ -1674,8 +1674,8 @@ static const struct intel_c20pll_state mtl_c20_hdmi_600 = { 0x0000, /* cmn cfg2 */ 0x0000, /* cmn cfg3 */ }, - .mpllb = { 0x009c, /* mpllb cfg0 */ - 0x7d08, /* mpllb cfg1 */ + .mpllb = { 0x109c, /* mpllb cfg0 */ + 0x2108, /* mpllb cfg1 */ 0xca06, /* mpllb cfg2 */ 0xbe40, /* mpllb cfg3 */ 0x0000, /* mpllb cfg4 */ @@ -1691,7 +1691,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_600 = { static const struct intel_c20pll_state mtl_c20_hdmi_800 = { .clock = 8000000, .tx = { 0xbe98, /* tx cfg0 */ - 0x9800, /* tx cfg1 */ + 0x8800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, .cmn = { 0x0500, /* cmn cfg0*/ @@ -1699,8 +1699,8 @@ static const struct intel_c20pll_state mtl_c20_hdmi_800 = { 0x0000, /* cmn cfg2 */ 0x0000, /* cmn cfg3 */ }, - .mpllb = { 0x00d0, /* mpllb cfg0 */ - 0x7d08, /* mpllb cfg1 */ + .mpllb = { 0x10d0, /* mpllb cfg0 */ + 0x2108, /* mpllb cfg1 */ 0x4a06, /* mpllb cfg2 */ 0xbe40, /* mpllb cfg3 */ 0x0000, /* mpllb cfg4 */ @@ -1716,7 +1716,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_800 = { static const struct intel_c20pll_state mtl_c20_hdmi_1000 = { .clock = 10000000, .tx = { 0xbe98, /* tx cfg0 */ - 0x9800, /* tx cfg1 */ + 0x8800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, .cmn = { 0x0500, /* cmn cfg0*/ @@ -1725,7 +1725,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_1000 = { 0x0000, /* cmn cfg3 */ }, .mpllb = { 0x1104, /* mpllb cfg0 */ - 0x7d08, /* mpllb cfg1 */ + 0x2108, /* mpllb cfg1 */ 0x0a06, /* mpllb cfg2 */ 0xbe40, /* mpllb cfg3 */ 0x0000, /* mpllb cfg4 */ @@ -1741,7 +1741,7 @@ static const struct intel_c20pll_state mtl_c20_hdmi_1000 = { static const struct intel_c20pll_state mtl_c20_hdmi_1200 = { .clock = 12000000, .tx = { 0xbe98, /* tx cfg0 */ - 0x9800, /* tx cfg1 */ + 0x8800, /* tx cfg1 */ 0x0000, /* tx cfg2 */ }, .cmn = { 0x0500, /* cmn cfg0*/ @@ -1749,8 +1749,8 @@ static const struct intel_c20pll_state mtl_c20_hdmi_1200 = { 0x0000, /* cmn cfg2 */ 0x0000, /* cmn cfg3 */ }, - .mpllb = { 0x0138, /* mpllb cfg0 */ - 0x7d08, /* mpllb cfg1 */ + .mpllb = { 0x1138, /* mpllb cfg0 */ + 0x2108, /* mpllb cfg1 */ 0x5486, /* mpllb cfg2 */ 0xfe40, /* mpllb cfg3 */ 0x0000, /* mpllb cfg4 */ From 425b463859eda4f4c071e517267acdd1c0d731bd Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Wed, 14 Feb 2024 11:46:30 -0300 Subject: [PATCH 067/295] drm/i915: Update ADL-N PCI IDs Extend the list of ADL-N PCI IDs to contain two new entries. Bspec: 68397 Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240214144629.106702-2-gustavo.sousa@intel.com --- include/drm/i915_pciids.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 07779a11758e..28a96aa1e08f 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -672,7 +672,9 @@ #define INTEL_ADLN_IDS(info) \ INTEL_VGA_DEVICE(0x46D0, info), \ INTEL_VGA_DEVICE(0x46D1, info), \ - INTEL_VGA_DEVICE(0x46D2, info) + INTEL_VGA_DEVICE(0x46D2, info), \ + INTEL_VGA_DEVICE(0x46D3, info), \ + INTEL_VGA_DEVICE(0x46D4, info) /* RPL-S */ #define INTEL_RPLS_IDS(info) \ From 733c454e0d149356eaf10eaf77cdbcd4ae3d9924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 9 Feb 2024 20:38:05 +0200 Subject: [PATCH 068/295] drm/i915: Fix PLL state check for gmch platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GMCH DPLL state check was mistakenly removed in commit 87fc875a2b85 ("drm/i915/dg2: Skip shared DPLL handling"). Bring it back. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240209183809.16887-2-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1b844cac4c58..ba1c84257702 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5216,9 +5216,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); - if (dev_priv->display.dpll.mgr) { + if (dev_priv->display.dpll.mgr) PIPE_CONF_CHECK_P(shared_dpll); + /* FIXME convert everything over the dpll_mgr */ + if (dev_priv->display.dpll.mgr || HAS_GMCH(dev_priv)) { PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); PIPE_CONF_CHECK_X(dpll_hw_state.fp0); From 8d18f12f97bff220ec1d8f0133906045f68a5701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 9 Feb 2024 20:38:06 +0200 Subject: [PATCH 069/295] drm/i915: Include the CRTC name in the ELD buffer mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most crtc state mismatches include the CRTC id+name in the prints. Also include it in the ELD buffer mismatch prints. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240209183809.16887-3-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_display.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ba1c84257702..2ff60bfedbb3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4852,10 +4852,12 @@ memcmp_diff_len(const u8 *a, const u8 *b, size_t len) } static void -pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, - bool fastset, const char *name, +pipe_config_buffer_mismatch(bool fastset, const struct intel_crtc *crtc, + const char *name, const u8 *a, const u8 *b, size_t len) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + if (fastset) { if (!drm_debug_enabled(DRM_UT_KMS)) return; @@ -4864,7 +4866,8 @@ pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, len = memcmp_diff_len(a, b, len); drm_dbg_kms(&dev_priv->drm, - "fastset requirement not met in %s buffer\n", name); + "[CRTC:%d:%s] fastset requirement not met in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, 16, 0, a, len, false); print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, @@ -4873,7 +4876,8 @@ pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, /* only dump up to the last difference */ len = memcmp_diff_len(a, b, len); - drm_err(&dev_priv->drm, "mismatch in %s buffer\n", name); + drm_err(&dev_priv->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, 16, 0, a, len, false); print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, @@ -5072,7 +5076,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, BUILD_BUG_ON(sizeof(current_config->name) != (len)); \ BUILD_BUG_ON(sizeof(pipe_config->name) != (len)); \ if (!intel_compare_buffer(current_config->name, pipe_config->name, (len))) { \ - pipe_config_buffer_mismatch(dev_priv, fastset, __stringify(name), \ + pipe_config_buffer_mismatch(fastset, crtc, __stringify(name), \ current_config->name, \ pipe_config->name, \ (len)); \ From b56e24be5916cf8471f3cea998ad4352a78671ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 9 Feb 2024 20:38:07 +0200 Subject: [PATCH 070/295] drm/i915: Reuse ibx_dump_hw_state() for gmch platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GMCH platform DPLLs are similar to the IBX+ PCH DPLLs so we can just use the same state dump function for both. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240209183809.16887-4-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index e7e0a4cf9f93..c6cc7465b92c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4458,13 +4458,7 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *i915, /* fallback for platforms that don't use the shared dpll * infrastructure */ - drm_dbg_kms(&i915->drm, - "dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, " - "fp0: 0x%x, fp1: 0x%x\n", - hw_state->dpll, - hw_state->dpll_md, - hw_state->fp0, - hw_state->fp1); + ibx_dump_hw_state(i915, hw_state); } } From 7ab52cb3489e4001444acdc23979fbf59305570c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 9 Feb 2024 20:38:08 +0200 Subject: [PATCH 071/295] drm/i915: Add PLL .compare_hw_state() vfunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chunk up the humongous dpll_hw_state comparison check into per-platform variants, implemented in the dpll_mgr. This is step one in allowing each platform (or perhaps even PLL) type to have a custom hw state structure instead of having to smash it all into one. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240209183809.16887-5-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_display.c | 78 ++++++++------- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 95 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 3 + 3 files changed, 141 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2ff60bfedbb3..3d09900bf562 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4908,6 +4908,36 @@ pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, va_end(args); } +static void +pipe_config_pll_mismatch(bool fastset, + const struct intel_crtc *crtc, + const char *name, + const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (fastset) { + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] fastset requirement not met in %s\n", + crtc->base.base.id, crtc->base.name, name); + drm_dbg_kms(&i915->drm, "expected:\n"); + intel_dpll_dump_hw_state(i915, a); + drm_dbg_kms(&i915->drm, "found:\n"); + intel_dpll_dump_hw_state(i915, b); + } else { + drm_err(&i915->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); + drm_err(&i915->drm, "expected:\n"); + intel_dpll_dump_hw_state(i915, a); + drm_err(&i915->drm, "found:\n"); + intel_dpll_dump_hw_state(i915, b); + } +} + static bool fastboot_enabled(struct drm_i915_private *dev_priv) { /* Enable fastboot by default on Skylake and newer */ @@ -5017,7 +5047,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_TIMINGS(name) do { \ +#define PIPE_CONF_CHECK_PLL(name) do { \ + if (!intel_dpll_compare_hw_state(dev_priv, ¤t_config->name, \ + &pipe_config->name)) { \ + pipe_config_pll_mismatch(fastset, crtc, __stringify(name), \ + ¤t_config->name, \ + &pipe_config->name); \ + ret = false; \ + } \ +} while (0) + +#define PIPE_CONF_CHECK_TIMINGS(name) do { \ PIPE_CONF_CHECK_I(name.crtc_hdisplay); \ PIPE_CONF_CHECK_I(name.crtc_htotal); \ PIPE_CONF_CHECK_I(name.crtc_hblank_start); \ @@ -5224,40 +5264,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_P(shared_dpll); /* FIXME convert everything over the dpll_mgr */ - if (dev_priv->display.dpll.mgr || HAS_GMCH(dev_priv)) { - PIPE_CONF_CHECK_X(dpll_hw_state.dpll); - PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); - PIPE_CONF_CHECK_X(dpll_hw_state.fp0); - PIPE_CONF_CHECK_X(dpll_hw_state.fp1); - PIPE_CONF_CHECK_X(dpll_hw_state.wrpll); - PIPE_CONF_CHECK_X(dpll_hw_state.spll); - PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); - PIPE_CONF_CHECK_X(dpll_hw_state.div0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); - PIPE_CONF_CHECK_X(dpll_hw_state.pll0); - PIPE_CONF_CHECK_X(dpll_hw_state.pll1); - PIPE_CONF_CHECK_X(dpll_hw_state.pll2); - PIPE_CONF_CHECK_X(dpll_hw_state.pll3); - PIPE_CONF_CHECK_X(dpll_hw_state.pll6); - PIPE_CONF_CHECK_X(dpll_hw_state.pll8); - PIPE_CONF_CHECK_X(dpll_hw_state.pll9); - PIPE_CONF_CHECK_X(dpll_hw_state.pll10); - PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); - } + if (dev_priv->display.dpll.mgr || HAS_GMCH(dev_priv)) + PIPE_CONF_CHECK_PLL(dpll_hw_state); PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c6cc7465b92c..ff480f171f75 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -109,6 +109,8 @@ struct intel_dpll_mgr { void (*update_ref_clks)(struct drm_i915_private *i915); void (*dump_hw_state)(struct drm_i915_private *i915, const struct intel_dpll_hw_state *hw_state); + bool (*compare_hw_state)(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b); }; static void @@ -644,6 +646,15 @@ static void ibx_dump_hw_state(struct drm_i915_private *i915, hw_state->fp1); } +static bool ibx_compare_hw_state(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + return a->dpll == b->dpll && + a->dpll_md == b->dpll_md && + a->fp0 == b->fp0 && + a->fp1 == b->fp1; +} + static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { .enable = ibx_pch_dpll_enable, .disable = ibx_pch_dpll_disable, @@ -662,6 +673,7 @@ static const struct intel_dpll_mgr pch_pll_mgr = { .get_dplls = ibx_get_dpll, .put_dplls = intel_put_dpll, .dump_hw_state = ibx_dump_hw_state, + .compare_hw_state = ibx_compare_hw_state, }; static void hsw_ddi_wrpll_enable(struct drm_i915_private *i915, @@ -1220,6 +1232,13 @@ static void hsw_dump_hw_state(struct drm_i915_private *i915, hw_state->wrpll, hw_state->spll); } +static bool hsw_compare_hw_state(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + return a->wrpll == b->wrpll && + a->spll == b->spll; +} + static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { .enable = hsw_ddi_wrpll_enable, .disable = hsw_ddi_wrpll_disable, @@ -1278,6 +1297,7 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { .put_dplls = intel_put_dpll, .update_ref_clks = hsw_update_dpll_ref_clks, .dump_hw_state = hsw_dump_hw_state, + .compare_hw_state = hsw_compare_hw_state, }; struct skl_dpll_regs { @@ -1929,6 +1949,14 @@ static void skl_dump_hw_state(struct drm_i915_private *i915, hw_state->cfgcr2); } +static bool skl_compare_hw_state(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + return a->ctrl1 == b->ctrl1 && + a->cfgcr1 == b->cfgcr1 && + a->cfgcr2 == b->cfgcr2; +} + static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { .enable = skl_ddi_pll_enable, .disable = skl_ddi_pll_disable, @@ -1959,6 +1987,7 @@ static const struct intel_dpll_mgr skl_pll_mgr = { .put_dplls = intel_put_dpll, .update_ref_clks = skl_update_dpll_ref_clks, .dump_hw_state = skl_dump_hw_state, + .compare_hw_state = skl_compare_hw_state, }; static void bxt_ddi_pll_enable(struct drm_i915_private *i915, @@ -2392,6 +2421,21 @@ static void bxt_dump_hw_state(struct drm_i915_private *i915, hw_state->pcsdw12); } +static bool bxt_compare_hw_state(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + return a->ebb0 == b->ebb0 && + a->ebb4 == b->ebb4 && + a->pll0 == b->pll0 && + a->pll1 == b->pll1 && + a->pll2 == b->pll2 && + a->pll3 == b->pll3 && + a->pll6 == b->pll6 && + a->pll8 == b->pll8 && + a->pll10 == b->pll10 && + a->pcsdw12 == b->pcsdw12; +} + static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { .enable = bxt_ddi_pll_enable, .disable = bxt_ddi_pll_disable, @@ -2413,6 +2457,7 @@ static const struct intel_dpll_mgr bxt_pll_mgr = { .put_dplls = intel_put_dpll, .update_ref_clks = bxt_update_dpll_ref_clks, .dump_hw_state = bxt_dump_hw_state, + .compare_hw_state = bxt_compare_hw_state, }; static void icl_wrpll_get_multipliers(int bestdiv, int *pdiv, @@ -4005,6 +4050,25 @@ static void icl_dump_hw_state(struct drm_i915_private *i915, hw_state->mg_pll_tdc_coldst_bias); } +static bool icl_compare_hw_state(const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + /* FIXME split combo vs. mg more thoroughly */ + return a->cfgcr0 == b->cfgcr0 && + a->cfgcr1 == b->cfgcr1 && + a->div0 == b->div0 && + a->mg_refclkin_ctl == b->mg_refclkin_ctl && + a->mg_clktop2_coreclkctl1 == b->mg_clktop2_coreclkctl1 && + a->mg_clktop2_hsclkctl == b->mg_clktop2_hsclkctl && + a->mg_pll_div0 == b->mg_pll_div0 && + a->mg_pll_div1 == b->mg_pll_div1 && + a->mg_pll_lf == b->mg_pll_lf && + a->mg_pll_frac_lock == b->mg_pll_frac_lock && + a->mg_pll_ssc == b->mg_pll_ssc && + a->mg_pll_bias == b->mg_pll_bias && + a->mg_pll_tdc_coldst_bias == b->mg_pll_tdc_coldst_bias; +} + static const struct intel_shared_dpll_funcs combo_pll_funcs = { .enable = combo_pll_enable, .disable = combo_pll_disable, @@ -4046,6 +4110,7 @@ static const struct intel_dpll_mgr icl_pll_mgr = { .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct dpll_info ehl_plls[] = { @@ -4063,6 +4128,7 @@ static const struct intel_dpll_mgr ehl_pll_mgr = { .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct intel_shared_dpll_funcs dkl_pll_funcs = { @@ -4094,6 +4160,7 @@ static const struct intel_dpll_mgr tgl_pll_mgr = { .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct dpll_info rkl_plls[] = { @@ -4110,6 +4177,7 @@ static const struct intel_dpll_mgr rkl_pll_mgr = { .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct dpll_info dg1_plls[] = { @@ -4127,6 +4195,7 @@ static const struct intel_dpll_mgr dg1_pll_mgr = { .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct dpll_info adls_plls[] = { @@ -4144,6 +4213,7 @@ static const struct intel_dpll_mgr adls_pll_mgr = { .put_dplls = icl_put_dplls, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; static const struct dpll_info adlp_plls[] = { @@ -4166,6 +4236,7 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = icl_dump_hw_state, + .compare_hw_state = icl_compare_hw_state, }; /** @@ -4462,6 +4533,30 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *i915, } } +/** + * intel_dpll_compare_hw_state - compare the two states + * @i915: i915 drm device + * @a: first DPLL hw state + * @b: second DPLL hw state + * + * Compare DPLL hw states @a and @b. + * + * Returns: true if the states are equal, false if the differ + */ +bool intel_dpll_compare_hw_state(struct drm_i915_private *i915, + const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) +{ + if (i915->display.dpll.mgr) { + return i915->display.dpll.mgr->compare_hw_state(a, b); + } else { + /* fallback for platforms that don't use the shared dpll + * infrastructure + */ + return ibx_compare_hw_state(a, b); + } +} + static void verify_single_dpll_state(struct drm_i915_private *i915, struct intel_shared_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 616afe861b46..cc0e1386309d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -378,6 +378,9 @@ void intel_dpll_sanitize_state(struct drm_i915_private *i915); void intel_dpll_dump_hw_state(struct drm_i915_private *i915, const struct intel_dpll_hw_state *hw_state); +bool intel_dpll_compare_hw_state(struct drm_i915_private *i915, + const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b); 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); From 1b923307a1b0067a302b394e73311aeaebc06f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 9 Feb 2024 20:38:09 +0200 Subject: [PATCH 072/295] drm/i915: Enable fastboot across the board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's nothing magical about vlv+ platforms vs. fastboot. If it works somewhere it should work everywhere, assuming we've not missed any crucial state checks. That seems unlikely on older platforms with less state to check anyway. Just enable fastboot across the board, and the remove the remnants of the optional stuff (we already removed the modparam for fastboot anyway). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240209183809.16887-6-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_display.c | 22 -------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3d09900bf562..607117ac2168 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4938,20 +4938,6 @@ pipe_config_pll_mismatch(bool fastset, } } -static bool fastboot_enabled(struct drm_i915_private *dev_priv) -{ - /* Enable fastboot by default on Skylake and newer */ - if (DISPLAY_VER(dev_priv) >= 9) - return true; - - /* Enable fastboot by default on VLV and CHV */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return true; - - /* Disabled by default on all others */ - return false; -} - bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, @@ -4960,14 +4946,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); bool ret = true; - bool fixup_inherited = fastset && - current_config->inherited && !pipe_config->inherited; - - if (fixup_inherited && !fastboot_enabled(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "initial modeset and fastboot not set\n"); - ret = false; - } #define PIPE_CONF_CHECK_X(name) do { \ if (current_config->name != pipe_config->name) { \ From 26aba0d1c35ff78434d8cb1dd97bd6b4cbdfe851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Feb 2024 03:33:31 +0200 Subject: [PATCH 073/295] drm/i915/cdclk: Extract cdclk_divider() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the cdclk divider calculation into a helper. We'll have more users of this soon. We can now also get rid of the intermediate 'unsquashed_cdclk' variable. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240207013334.29606-2-ville.syrjala@linux.intel.com Reviewed-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_cdclk.c | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 26200ee3e23f..d79485e17ed1 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1406,6 +1406,20 @@ static const struct intel_cdclk_vals lnl_cdclk_table[] = { {} }; +static const int cdclk_squash_len = 16; + +static int cdclk_squash_divider(u16 waveform) +{ + return hweight16(waveform ?: 0xffff); +} + +static int cdclk_divider(int cdclk, int vco, u16 waveform) +{ + /* 2 * cd2x divider */ + return DIV_ROUND_CLOSEST(vco * cdclk_squash_divider(waveform), + cdclk * cdclk_squash_len); +} + static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk) { const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table; @@ -1744,10 +1758,10 @@ static u32 bxt_cdclk_cd2x_pipe(struct drm_i915_private *dev_priv, enum pipe pipe } static u32 bxt_cdclk_cd2x_div_sel(struct drm_i915_private *dev_priv, - int cdclk, int vco) + int cdclk, int vco, u16 waveform) { /* cdclk = vco / 2 / div{1,1.5,2,4} */ - switch (DIV_ROUND_CLOSEST(vco, cdclk)) { + switch (cdclk_divider(cdclk, vco, waveform)) { default: drm_WARN_ON(&dev_priv->drm, cdclk != dev_priv->display.cdclk.hw.bypass); @@ -1826,13 +1840,6 @@ static bool cdclk_pll_is_unknown(unsigned int vco) return vco == ~0; } -static const int cdclk_squash_len = 16; - -static int cdclk_squash_divider(u16 waveform) -{ - return hweight16(waveform ?: 0xffff); -} - static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, const struct intel_cdclk_config *old_cdclk_config, const struct intel_cdclk_config *new_cdclk_config, @@ -1906,16 +1913,12 @@ static u32 bxt_cdclk_ctl(struct drm_i915_private *i915, { int cdclk = cdclk_config->cdclk; int vco = cdclk_config->vco; - int unsquashed_cdclk; u16 waveform; u32 val; waveform = cdclk_squash_waveform(i915, cdclk); - unsquashed_cdclk = DIV_ROUND_CLOSEST(cdclk * cdclk_squash_len, - cdclk_squash_divider(waveform)); - - val = bxt_cdclk_cd2x_div_sel(i915, unsquashed_cdclk, vco) | + val = bxt_cdclk_cd2x_div_sel(i915, cdclk, vco, waveform) | bxt_cdclk_cd2x_pipe(i915, pipe); /* From 76184fa3d32ed9b43da7c451cbbb45e567d20196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Feb 2024 03:33:32 +0200 Subject: [PATCH 074/295] drm/i915/cdclk: Squash waveform is 16 bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Have cdclk_squash_waveform() return a u16 since that's how many bits we have in the waveform. We alreday use u16 everywhere else. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240207013334.29606-3-ville.syrjala@linux.intel.com Reviewed-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index d79485e17ed1..a0013e37d53c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1778,7 +1778,7 @@ static u32 bxt_cdclk_cd2x_div_sel(struct drm_i915_private *dev_priv, } } -static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv, +static u16 cdclk_squash_waveform(struct drm_i915_private *dev_priv, int cdclk) { const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table; From c0151c695fbefcef816432e00d2f8d427ebf3125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Feb 2024 03:33:33 +0200 Subject: [PATCH 075/295] drm/i915/cdclk: Remove the hardcoded divider from cdclk_compute_crawl_and_squash_midpoint() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cdclk_compute_crawl_and_squash_midpoint() was still assuming that cd2x divider == 1 (ie. full divider == 2). Remove that assumption by computing the dividers properly. We'll also toss in a WARN in case the divider somehow ends up different between the old and new cdclk configs. That should never happen given we have div==2 in all the cdclk table entries for the affected platforms. If in the future we need a config where the divider also needs to be changed then we likely need to add an extra step into the cdclk programming sequence to make sure things stay within legal limits throughout the process. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240207013334.29606-4-ville.syrjala@linux.intel.com Reviewed-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_cdclk.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a0013e37d53c..ca00586fdbc8 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1846,7 +1846,7 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91 struct intel_cdclk_config *mid_cdclk_config) { u16 old_waveform, new_waveform, mid_waveform; - int div = 2; + int old_div, new_div, mid_div; /* Return if PLL is in an unknown state, force a complete disable and re-enable. */ if (cdclk_pll_is_unknown(old_cdclk_config->vco)) @@ -1865,6 +1865,18 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91 old_waveform == new_waveform) return false; + old_div = cdclk_divider(old_cdclk_config->cdclk, + old_cdclk_config->vco, old_waveform); + new_div = cdclk_divider(new_cdclk_config->cdclk, + new_cdclk_config->vco, new_waveform); + + /* + * Should not happen currently. We might need more midpoint + * transitions if we need to also change the cd2x divider. + */ + if (drm_WARN_ON(&i915->drm, old_div != new_div)) + return false; + *mid_cdclk_config = *new_cdclk_config; /* @@ -1877,15 +1889,17 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91 if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) { mid_cdclk_config->vco = old_cdclk_config->vco; + mid_div = old_div; mid_waveform = new_waveform; } else { mid_cdclk_config->vco = new_cdclk_config->vco; + mid_div = new_div; mid_waveform = old_waveform; } mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) * mid_cdclk_config->vco, - cdclk_squash_len * div); + cdclk_squash_len * mid_div); /* make sure the mid clock came out sane */ From 79e2ea2eaaa699916ebd74232c8f2ef949f8cb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Feb 2024 03:33:34 +0200 Subject: [PATCH 076/295] drm/i915/cdclk: Document CDCLK update methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a bit of documentation to briefly explain the methods by which we can change the CDCLK frequency. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240207013334.29606-5-ville.syrjala@linux.intel.com Reviewed-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_cdclk.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index ca00586fdbc8..30dae4fef6cb 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -63,6 +63,15 @@ * DMC will not change the active CDCLK frequency however, so that part * will still be performed by the driver directly. * + * Several methods exist to change the CDCLK frequency, which ones are + * supported depends on the platform: + * - Full PLL disable + re-enable with new VCO frequency. Pipes must be inactive. + * - CD2X divider update. Single pipe can be active as the divider update + * can be synchronized with the pipe's start of vblank. + * - Crawl the PLL smoothly to the new VCO frequency. Pipes can be active. + * - Squash waveform update. Pipes can be active. + * - Crawl and squash can also be done back to back. Pipes can be active. + * * RAWCLK is a fixed frequency clock, often used by various auxiliary * blocks such as AUX CH or backlight PWM. Hence the only thing we * really need to know about RAWCLK is its frequency so that various From fb750eefc4925f2bab01512101e73b69d585ad58 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 12 Feb 2024 09:16:39 +0000 Subject: [PATCH 077/295] drm/msm/dp: Fix spelling mistake "enale" -> "enable" There is a spelling mistake in a drm_dbg_dp message. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Neil Armstrong Patchwork: https://patchwork.freedesktop.org/patch/577760/ Link: https://lore.kernel.org/r/20240212091639.2397424-1-colin.i.king@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 03bbdf865d26..320f17fce9a6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1409,7 +1409,7 @@ static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl) ctrl->link_clks_on = true; - drm_dbg_dp(ctrl->drm_dev, "enale link clocks\n"); + drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", ctrl->stream_clks_on ? "on" : "off", ctrl->link_clks_on ? "on" : "off", From d2570ee67a4719802f7ce4ad79260a97f07c6bd9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:01:08 +0200 Subject: [PATCH 078/295] drm/msm/mdss: generate MDSS data for MDP5 platforms Older (mdp5) platforms do not use per-SoC compatible strings. Instead they use a single compat entry 'qcom,mdss'. To facilitate migrating these platforms to the DPU driver provide a way to generate the MDSS / UBWC data at runtime, when the DPU driver asks for it. It is not possible to generate this data structure at the probe time, since some platforms might not have MDP_CLK enabled, which makes reading HW_REV register useless and prone to possible crashes. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/577502/ Link: https://lore.kernel.org/r/20240208-fd-migrate-mdp5-v4-1-945d08ef3fa8@linaro.org --- drivers/gpu/drm/msm/msm_mdss.c | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 35423d10aafa..65657230bbff 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -3,6 +3,7 @@ * Copyright (c) 2018, The Linux Foundation */ +#include #include #include #include @@ -213,6 +214,49 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) } } +#define MDSS_HW_MAJ_MIN GENMASK(31, 16) + +#define MDSS_HW_MSM8996 0x1007 +#define MDSS_HW_MSM8937 0x100e +#define MDSS_HW_MSM8953 0x1010 +#define MDSS_HW_MSM8998 0x3000 +#define MDSS_HW_SDM660 0x3002 +#define MDSS_HW_SDM630 0x3003 + +/* + * MDP5 platforms use generic qcom,mdp5 compat string, so we have to generate this data + */ +static const struct msm_mdss_data *msm_mdss_generate_mdp5_mdss_data(struct msm_mdss *mdss) +{ + struct msm_mdss_data *data; + u32 hw_rev; + + data = devm_kzalloc(mdss->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + hw_rev = readl_relaxed(mdss->mmio + HW_REV); + hw_rev = FIELD_GET(MDSS_HW_MAJ_MIN, hw_rev); + + if (hw_rev == MDSS_HW_MSM8996 || + hw_rev == MDSS_HW_MSM8937 || + hw_rev == MDSS_HW_MSM8953 || + hw_rev == MDSS_HW_MSM8998 || + hw_rev == MDSS_HW_SDM660 || + hw_rev == MDSS_HW_SDM630) { + data->ubwc_dec_version = UBWC_1_0; + data->ubwc_enc_version = UBWC_1_0; + } + + if (hw_rev == MDSS_HW_MSM8996 || + hw_rev == MDSS_HW_MSM8998) + data->highest_bank_bit = 2; + else + data->highest_bank_bit = 1; + + return data; +} + const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) { struct msm_mdss *mdss; @@ -222,6 +266,13 @@ const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) mdss = dev_get_drvdata(dev); + /* + * We could not do it at the probe time, since hw revision register was + * not readable. Fill data structure now for the MDP5 platforms. + */ + if (!mdss->mdss_data && mdss->is_mdp5) + mdss->mdss_data = msm_mdss_generate_mdp5_mdss_data(mdss); + return mdss->mdss_data; } From 39b06ed6d4f325072f479bf5358cfe2013569e27 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:01:09 +0200 Subject: [PATCH 079/295] drm/msm/dpu: support binding to the mdp5 devices Existing MDP5 devices have slightly different bindings. The main register region is called `mdp_phys' instead of `mdp'. Also vbif register regions are a part of the parent, MDSS device. Add support for handling this binding differences. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/577505/ Link: https://lore.kernel.org/r/20240208-fd-migrate-mdp5-v4-2-945d08ef3fa8@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 98 +++++++++++++++++++------ drivers/gpu/drm/msm/msm_drv.h | 3 + drivers/gpu/drm/msm/msm_io_utils.c | 13 ++++ 3 files changed, 93 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 48728be27e15..0b1c23806590 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1200,6 +1200,78 @@ static int dpu_kms_init(struct drm_device *ddev) return 0; } +static int dpu_kms_mmap_mdp5(struct dpu_kms *dpu_kms) +{ + struct platform_device *pdev = dpu_kms->pdev; + struct platform_device *mdss_dev; + int ret; + + if (!dev_is_platform(dpu_kms->pdev->dev.parent)) + return -EINVAL; + + mdss_dev = to_platform_device(dpu_kms->pdev->dev.parent); + + dpu_kms->mmio = msm_ioremap(pdev, "mdp_phys"); + if (IS_ERR(dpu_kms->mmio)) { + ret = PTR_ERR(dpu_kms->mmio); + DPU_ERROR("mdp register memory map failed: %d\n", ret); + dpu_kms->mmio = NULL; + return ret; + } + DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + + dpu_kms->vbif[VBIF_RT] = msm_ioremap_mdss(mdss_dev, + dpu_kms->pdev, + "vbif_phys"); + if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { + ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]); + DPU_ERROR("vbif register memory map failed: %d\n", ret); + dpu_kms->vbif[VBIF_RT] = NULL; + return ret; + } + + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_mdss(mdss_dev, + dpu_kms->pdev, + "vbif_nrt_phys"); + if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { + dpu_kms->vbif[VBIF_NRT] = NULL; + DPU_DEBUG("VBIF NRT is not defined"); + } + + return 0; +} + +static int dpu_kms_mmap_dpu(struct dpu_kms *dpu_kms) +{ + struct platform_device *pdev = dpu_kms->pdev; + int ret; + + dpu_kms->mmio = msm_ioremap(pdev, "mdp"); + if (IS_ERR(dpu_kms->mmio)) { + ret = PTR_ERR(dpu_kms->mmio); + DPU_ERROR("mdp register memory map failed: %d\n", ret); + dpu_kms->mmio = NULL; + return ret; + } + DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + + dpu_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif"); + if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { + ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]); + DPU_ERROR("vbif register memory map failed: %d\n", ret); + dpu_kms->vbif[VBIF_RT] = NULL; + return ret; + } + + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(pdev, "vbif_nrt"); + if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { + dpu_kms->vbif[VBIF_NRT] = NULL; + DPU_DEBUG("VBIF NRT is not defined"); + } + + return 0; +} + static int dpu_dev_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1233,28 +1305,12 @@ static int dpu_dev_probe(struct platform_device *pdev) dpu_kms->base.irq = irq; - dpu_kms->mmio = msm_ioremap(pdev, "mdp"); - if (IS_ERR(dpu_kms->mmio)) { - ret = PTR_ERR(dpu_kms->mmio); - DPU_ERROR("mdp register memory map failed: %d\n", ret); - dpu_kms->mmio = NULL; + if (of_device_is_compatible(dpu_kms->pdev->dev.of_node, "qcom,mdp5")) + ret = dpu_kms_mmap_mdp5(dpu_kms); + else + ret = dpu_kms_mmap_dpu(dpu_kms); + if (ret) return ret; - } - DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); - - dpu_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif"); - if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { - ret = PTR_ERR(dpu_kms->vbif[VBIF_RT]); - DPU_ERROR("vbif register memory map failed: %d\n", ret); - dpu_kms->vbif[VBIF_RT] = NULL; - return ret; - } - - dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(pdev, "vbif_nrt"); - if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { - dpu_kms->vbif[VBIF_NRT] = NULL; - DPU_DEBUG("VBIF NRT is not defined"); - } ret = dpu_kms_parse_data_bus_icc_path(dpu_kms); if (ret) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 16a7cbc0b7dd..01e783130054 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -476,6 +476,9 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name); void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, phys_addr_t *size); void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name); +void __iomem *msm_ioremap_mdss(struct platform_device *mdss_pdev, + struct platform_device *dev, + const char *name); struct icc_path *msm_icc_get(struct device *dev, const char *name); diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c index 59d2788c4510..afedd61c3e28 100644 --- a/drivers/gpu/drm/msm/msm_io_utils.c +++ b/drivers/gpu/drm/msm/msm_io_utils.c @@ -50,6 +50,19 @@ struct clk *msm_clk_get(struct platform_device *pdev, const char *name) return clk; } +void __iomem *msm_ioremap_mdss(struct platform_device *mdss_pdev, + struct platform_device *pdev, + const char *name) +{ + struct resource *res; + + res = platform_get_resource_byname(mdss_pdev, IORESOURCE_MEM, name); + if (!res) + return ERR_PTR(-EINVAL); + + return devm_ioremap_resource(&pdev->dev, res); +} + static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name, bool quiet, phys_addr_t *psize) { From b8b123187035bebdfc4dd6932bdd3fc98ff8fdde Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:01:10 +0200 Subject: [PATCH 080/295] drm/msm: add a kernel param to select between MDP5 and DPU drivers For some of the platforms (e.g. SDM660, SDM630, MSM8996, etc.) it is possible to support this platform via the DPU driver (e.g. to provide support for DP, multirect, etc). Add a modparam to be able to switch between these two drivers. All platforms supported by both drivers are by default handled by the MDP5 driver. To let them be handled by the DPU driver pass the `msm.prefer_mdp5=false` kernel param. Reviewed-by: Stephen Boyd Reviewed-by: Carl Vanderlip Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577504/ Link: https://lore.kernel.org/r/20240208-fd-migrate-mdp5-v4-3-945d08ef3fa8@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 3 +++ drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 3 +++ drivers/gpu/drm/msm/msm_drv.c | 31 ++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 1 + 4 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 0b1c23806590..1c2975ea9c9c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1279,6 +1279,9 @@ static int dpu_dev_probe(struct platform_device *pdev) int irq; int ret = 0; + if (!msm_disp_drv_should_bind(&pdev->dev, true)) + return -ENODEV; + dpu_kms = devm_kzalloc(dev, sizeof(*dpu_kms), GFP_KERNEL); if (!dpu_kms) return -ENOMEM; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 25279c724fe0..e5f7052bcb87 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -852,6 +852,9 @@ static int mdp5_dev_probe(struct platform_device *pdev) DBG(""); + if (!msm_disp_drv_should_bind(&pdev->dev, false)) + return -ENODEV; + mdp5_kms = devm_kzalloc(&pdev->dev, sizeof(*mdp5_kms), GFP_KERNEL); if (!mdp5_kms) return -ENOMEM; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 50b65ffc24b1..f79134fc6cc0 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -969,6 +969,37 @@ static int add_components_mdp(struct device *master_dev, return 0; } +#if !IS_REACHABLE(CONFIG_DRM_MSM_MDP5) || !IS_REACHABLE(CONFIG_DRM_MSM_DPU) +bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver) +{ + /* If just a single driver is enabled, use it no matter what */ + return true; +} +#else + +static bool prefer_mdp5 = true; +MODULE_PARM_DESC(prefer_mdp5, "Select whether MDP5 or DPU driver should be preferred"); +module_param(prefer_mdp5, bool, 0444); + +/* list all platforms supported by both mdp5 and dpu drivers */ +static const char *const msm_mdp5_dpu_migration[] = { + NULL, +}; + +bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver) +{ + /* If it is not an MDP5 device, do not try MDP5 driver */ + if (!of_device_is_compatible(dev->of_node, "qcom,mdp5")) + return dpu_driver; + + /* If it is not in the migration list, use MDP5 */ + if (!of_device_compatible_match(dev->of_node, msm_mdp5_dpu_migration)) + return !dpu_driver; + + return prefer_mdp5 ? !dpu_driver : dpu_driver; +} +#endif + /* * We don't know what's the best binding to link the gpu with the drm device. * Fow now, we just hunt for all the possible gpus that we support, and add them diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 01e783130054..762e13e2df74 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -563,5 +563,6 @@ int msm_drv_probe(struct device *dev, struct msm_kms *kms); void msm_kms_shutdown(struct platform_device *pdev); +bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver); #endif /* __MSM_DRV_H__ */ From 7204df5e7e681238d457da03502f4b653403d7e7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 8 Feb 2024 17:01:11 +0200 Subject: [PATCH 081/295] drm/msm/dpu: add support for SDM660 and SDM630 platforms Bring in hardware support for the SDM660 and SDM630 platforms, which belong to the same DPU generation as MSM8998. Note, by default these platforms are still handled by the MDP5 driver unless the `msm.prefer_mdp5=false' parameter is provided. Co-developed-by: Konrad Dybcio Signed-off-by: Konrad Dybcio Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/577507/ Link: https://lore.kernel.org/r/20240208-fd-migrate-mdp5-v4-4-945d08ef3fa8@linaro.org --- .../msm/disp/dpu1/catalog/dpu_3_2_sdm660.h | 291 ++++++++++++++++++ .../msm/disp/dpu1/catalog/dpu_3_3_sdm630.h | 225 ++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 + drivers/gpu/drm/msm/msm_drv.c | 2 + 6 files changed, 524 insertions(+) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h new file mode 100644 index 000000000000..424815e7fb7d --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023. Linaro Inc. All rights reserved. + */ + +#ifndef _DPU_3_2_SDM660_H +#define _DPU_3_2_SDM660_H + +static const struct dpu_caps sdm660_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x7, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + +static const struct dpu_mdp_cfg sdm660_mdp = { + .name = "top_0", + .base = 0x0, .len = 0x458, + .features = BIT(DPU_MDP_VSYNC_SEL), + .clk_ctrls = { + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, + [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, + }, +}; + +static const struct dpu_ctl_cfg sdm660_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, +}; + +static const struct dpu_sspp_cfg sdm660_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x1ac, + .features = VIG_MSM8998_MASK, + .sblk = &dpu_vig_sblk_qseed3_1_2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG0, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x1ac, + .features = VIG_MSM8998_MASK, + .sblk = &dpu_vig_sblk_qseed3_1_2, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG1, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA0, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA1, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x1ac, + .features = DMA_CURSOR_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA2, + }, +}; + +static const struct dpu_lm_cfg sdm660_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_2, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + }, +}; + +static const struct dpu_pingpong_cfg sdm660_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x70000, .len = 0xd4, + .features = PINGPONG_SDM845_TE2_MASK, + .sblk = &sdm845_pp_sblk_te, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x70800, .len = 0xd4, + .features = PINGPONG_SDM845_TE2_MASK, + .sblk = &sdm845_pp_sblk_te, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x71000, .len = 0xd4, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x71800, .len = 0xd4, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15), + }, +}; + +static const struct dpu_dsc_cfg sdm660_dsc[] = { + { + .name = "dsc_0", .id = DSC_0, + .base = 0x80000, .len = 0x140, + }, { + .name = "dsc_1", .id = DSC_1, + .base = 0x80400, .len = 0x140, + }, +}; + +static const struct dpu_dspp_cfg sdm660_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &msm8998_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &msm8998_dspp_sblk, + }, +}; + +static const struct dpu_intf_cfg sdm660_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x6a000, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 21, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), + .intr_tear_rd_ptr = -1, + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x6a800, .len = 0x280, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .prog_fetch_lines_worst_case = 21, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), + .intr_tear_rd_ptr = -1, + }, { + .name = "intf_2", .id = INTF_2, + .base = 0x6b000, .len = 0x280, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_1, + .prog_fetch_lines_worst_case = 21, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29), + .intr_tear_rd_ptr = -1, + }, +}; + +static const struct dpu_perf_cfg sdm660_perf_data = { + .max_bw_low = 6600000, + .max_bw_high = 6600000, + .min_core_ib = 3100000, + .min_llcc_ib = 800000, + .min_dram_ib = 800000, + .undersized_prefill_lines = 2, + .xtra_prefill_lines = 2, + .dest_scale_prefill_lines = 3, + .macrotile_prefill_lines = 4, + .yuv_nv12_prefill_lines = 8, + .linear_prefill_lines = 1, + .downscaling_prefill_lines = 1, + .amortizable_threshold = 25, + .min_prefill_lines = 25, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(msm8998_qos_linear), + .entries = msm8998_qos_linear + }, + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), + .entries = msm8998_qos_macrotile + }, + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), + .entries = msm8998_qos_nrt + }, + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 200, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sdm660_mdss_ver = { + .core_major_ver = 3, + .core_minor_ver = 2, +}; + +const struct dpu_mdss_cfg dpu_sdm660_cfg = { + .mdss_ver = &sdm660_mdss_ver, + .caps = &sdm660_dpu_caps, + .mdp = &sdm660_mdp, + .ctl_count = ARRAY_SIZE(sdm660_ctl), + .ctl = sdm660_ctl, + .sspp_count = ARRAY_SIZE(sdm660_sspp), + .sspp = sdm660_sspp, + .mixer_count = ARRAY_SIZE(sdm660_lm), + .mixer = sdm660_lm, + .dspp_count = ARRAY_SIZE(sdm660_dspp), + .dspp = sdm660_dspp, + .pingpong_count = ARRAY_SIZE(sdm660_pp), + .pingpong = sdm660_pp, + .dsc_count = ARRAY_SIZE(sdm660_dsc), + .dsc = sdm660_dsc, + .intf_count = ARRAY_SIZE(sdm660_intf), + .intf = sdm660_intf, + .vbif_count = ARRAY_SIZE(msm8998_vbif), + .vbif = msm8998_vbif, + .perf = &sdm660_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h new file mode 100644 index 000000000000..df01227fc364 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023. Linaro Inc. All rights reserved. + */ + +#ifndef _DPU_3_3_SDM630_H +#define _DPU_3_3_SDM630_H + +static const struct dpu_caps sdm630_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, + .max_mixer_blendstages = 0x7, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = DEFAULT_DPU_LINE_WIDTH, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + +static const struct dpu_mdp_cfg sdm630_mdp = { + .name = "top_0", + .base = 0x0, .len = 0x458, + .features = BIT(DPU_MDP_VSYNC_SEL), + .clk_ctrls = { + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, + }, +}; + +static const struct dpu_ctl_cfg sdm630_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, +}; + +static const struct dpu_sspp_cfg sdm630_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x1ac, + .features = VIG_MSM8998_MASK, + .sblk = &dpu_vig_sblk_qseed3_1_2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG0, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA0, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA1, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x1ac, + .features = DMA_CURSOR_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA2, + }, +}; + +static const struct dpu_lm_cfg sdm630_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x320, + .features = MIXER_MSM8998_MASK, + .sblk = &msm8998_lm_sblk, + .pingpong = PINGPONG_2, + }, +}; + +static const struct dpu_pingpong_cfg sdm630_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x70000, .len = 0xd4, + .features = PINGPONG_SDM845_TE2_MASK, + .sblk = &sdm845_pp_sblk_te, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x71000, .len = 0xd4, + .features = PINGPONG_SDM845_MASK, + .sblk = &sdm845_pp_sblk, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14), + }, +}; + +static const struct dpu_dspp_cfg sdm630_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .features = DSPP_SC7180_MASK, + .sblk = &msm8998_dspp_sblk, + }, +}; + +static const struct dpu_intf_cfg sdm630_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x6a000, .len = 0x280, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 21, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), + .intr_tear_rd_ptr = -1, + }, { + .name = "intf_1", .id = INTF_1, + .base = 0x6a800, .len = 0x280, + .type = INTF_DSI, + .controller_id = MSM_DSI_CONTROLLER_0, + .prog_fetch_lines_worst_case = 21, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27), + .intr_tear_rd_ptr = -1, + }, +}; + +static const struct dpu_perf_cfg sdm630_perf_data = { + .max_bw_low = 4100000, + .max_bw_high = 4100000, + .min_core_ib = 3200000, + .min_llcc_ib = 800000, + .min_dram_ib = 800000, + .undersized_prefill_lines = 2, + .xtra_prefill_lines = 2, + .dest_scale_prefill_lines = 3, + .macrotile_prefill_lines = 4, + .yuv_nv12_prefill_lines = 8, + .linear_prefill_lines = 1, + .downscaling_prefill_lines = 1, + .amortizable_threshold = 25, + .min_prefill_lines = 25, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .safe_lut_tbl = {0xfffc, 0xff00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(msm8998_qos_linear), + .entries = msm8998_qos_linear + }, + {.nentry = ARRAY_SIZE(msm8998_qos_macrotile), + .entries = msm8998_qos_macrotile + }, + {.nentry = ARRAY_SIZE(msm8998_qos_nrt), + .entries = msm8998_qos_nrt + }, + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 200, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version sdm630_mdss_ver = { + .core_major_ver = 3, + .core_minor_ver = 3, +}; + +const struct dpu_mdss_cfg dpu_sdm630_cfg = { + .mdss_ver = &sdm630_mdss_ver, + .caps = &sdm630_dpu_caps, + .mdp = &sdm630_mdp, + .ctl_count = ARRAY_SIZE(sdm630_ctl), + .ctl = sdm630_ctl, + .sspp_count = ARRAY_SIZE(sdm630_sspp), + .sspp = sdm630_sspp, + .mixer_count = ARRAY_SIZE(sdm630_lm), + .mixer = sdm630_lm, + .dspp_count = ARRAY_SIZE(sdm630_dspp), + .dspp = sdm630_dspp, + .pingpong_count = ARRAY_SIZE(sdm630_pp), + .pingpong = sdm630_pp, + .intf_count = ARRAY_SIZE(sdm630_intf), + .intf = sdm630_intf, + .vbif_count = ARRAY_SIZE(msm8998_vbif), + .vbif = msm8998_vbif, + .perf = &sdm630_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 54e8717403a0..ccbee0f40ad7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -680,6 +680,8 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { *************************************************************/ #include "catalog/dpu_3_0_msm8998.h" +#include "catalog/dpu_3_2_sdm660.h" +#include "catalog/dpu_3_3_sdm630.h" #include "catalog/dpu_4_0_sdm845.h" #include "catalog/dpu_4_1_sdm670.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index ba82ef4560a6..a54c135e3147 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -832,6 +832,8 @@ struct dpu_mdss_cfg { }; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; +extern const struct dpu_mdss_cfg dpu_sdm630_cfg; +extern const struct dpu_mdss_cfg dpu_sdm660_cfg; extern const struct dpu_mdss_cfg dpu_sdm845_cfg; extern const struct dpu_mdss_cfg dpu_sdm670_cfg; extern const struct dpu_mdss_cfg dpu_sm8150_cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 1c2975ea9c9c..363b6410700f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1380,6 +1380,8 @@ static const struct dev_pm_ops dpu_pm_ops = { static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, + { .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, }, + { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, }, { .compatible = "qcom,sdm845-dpu", .data = &dpu_sdm845_cfg, }, { .compatible = "qcom,sc7180-dpu", .data = &dpu_sc7180_cfg, }, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index f79134fc6cc0..97790faffd23 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -983,6 +983,8 @@ module_param(prefer_mdp5, bool, 0444); /* list all platforms supported by both mdp5 and dpu drivers */ static const char *const msm_mdp5_dpu_migration[] = { + "qcom,sdm630-mdp5", + "qcom,sdm660-mdp5", NULL, }; From 49e27d3c9cd67fd5851f8b5518645b9bf3d2c6c0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 3 Dec 2023 03:05:29 +0300 Subject: [PATCH 082/295] drm/msm/dpu: finalise global state object Add calls to finalise global state object and corresponding lock. Fixes: de3916c70a24 ("drm/msm/dpu: Track resources in global state") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/570175/ Link: https://lore.kernel.org/r/20231203000532.1290480-3-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 363b6410700f..bb90e5fc2e87 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -374,6 +374,12 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) return 0; } +static void dpu_kms_global_obj_fini(struct dpu_kms *dpu_kms) +{ + drm_atomic_private_obj_fini(&dpu_kms->global_state); + drm_modeset_lock_fini(&dpu_kms->global_state_lock); +} + static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) { struct icc_path *path0; @@ -804,6 +810,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) dpu_kms->hw_vbif[i] = NULL; } + dpu_kms_global_obj_fini(dpu_kms); + dpu_kms->catalog = NULL; dpu_kms->hw_mdp = NULL; From abbf3108bc631c229ed484e6bb2255898746a34c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 3 Dec 2023 03:05:30 +0300 Subject: [PATCH 083/295] drm/msm/dpu: drop global_state_lock Since the commit b962a12050a3 ("drm/atomic: integrate modeset lock with private objects") the DRM framework no longer requires the external lock for private objects. Drop the lock, letting the DRM to manage private object locking. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/570174/ Link: https://lore.kernel.org/r/20231203000532.1290480-4-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 -------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - 2 files changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index bb90e5fc2e87..2af62d8fa9a7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -317,11 +317,6 @@ struct dpu_global_state *dpu_kms_get_global_state(struct drm_atomic_state *s) struct msm_drm_private *priv = s->dev->dev_private; struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); struct drm_private_state *priv_state; - int ret; - - ret = drm_modeset_lock(&dpu_kms->global_state_lock, s->acquire_ctx); - if (ret) - return ERR_PTR(ret); priv_state = drm_atomic_get_private_obj_state(s, &dpu_kms->global_state); @@ -362,8 +357,6 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) { struct dpu_global_state *state; - drm_modeset_lock_init(&dpu_kms->global_state_lock); - state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; @@ -377,7 +370,6 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) static void dpu_kms_global_obj_fini(struct dpu_kms *dpu_kms) { drm_atomic_private_obj_fini(&dpu_kms->global_state); - drm_modeset_lock_fini(&dpu_kms->global_state_lock); } static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index d1207f4ec3ae..b5db3fc76ca6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -85,7 +85,6 @@ struct dpu_kms { * Global private object state, Do not access directly, use * dpu_kms_global_get_state() */ - struct drm_modeset_lock global_state_lock; struct drm_private_obj global_state; struct dpu_rm rm; From f9c27e649a0d2d7091c7939f74bf2ff83dac8867 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 3 Dec 2023 03:05:31 +0300 Subject: [PATCH 084/295] drm/msm/mdp5: migrate SMP dumping to using atomic_print_state The Shared Memory Pool (SMP) state is a part of the MDP5's private object state. Use existing infrastructure, atomic_print_state() callback, to dump SMP state (which also makes it included into debugfs/dri/N/state). This allows us to drop the custom debugfs file too. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/570179/ Link: https://lore.kernel.org/r/20231203000532.1290480-5-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c | 2 -- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 46 ++++++------------------ drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 12 ++----- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h | 4 ++- 4 files changed, 15 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c index 43443a435d59..b40ed3a847c8 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c @@ -31,8 +31,6 @@ static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus) if (dumpstate && __ratelimit(&rs)) { struct drm_printer p = drm_info_printer(mdp5_kms->dev->dev); drm_state_dump(mdp5_kms->dev, &p); - if (mdp5_kms->smp) - mdp5_smp_dump(mdp5_kms->smp, &p); } } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index e5f7052bcb87..d0aff128b1ed 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -119,9 +119,19 @@ static void mdp5_global_destroy_state(struct drm_private_obj *obj, kfree(mdp5_state); } +static void mdp5_global_print_state(struct drm_printer *p, + const struct drm_private_state *state) +{ + struct mdp5_global_state *mdp5_state = to_mdp5_global_state(state); + + if (mdp5_state->mdp5_kms->smp) + mdp5_smp_dump(mdp5_state->mdp5_kms->smp, p, mdp5_state); +} + static const struct drm_private_state_funcs mdp5_global_state_funcs = { .atomic_duplicate_state = mdp5_global_duplicate_state, .atomic_destroy_state = mdp5_global_destroy_state, + .atomic_print_state = mdp5_global_print_state, }; static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms) @@ -206,39 +216,6 @@ static void mdp5_kms_destroy(struct msm_kms *kms) mdp5_destroy(mdp5_kms); } -#ifdef CONFIG_DEBUG_FS -static int smp_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct msm_drm_private *priv = dev->dev_private; - struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); - struct drm_printer p = drm_seq_file_printer(m); - - if (!mdp5_kms->smp) { - drm_printf(&p, "no SMP pool\n"); - return 0; - } - - mdp5_smp_dump(mdp5_kms->smp, &p); - - return 0; -} - -static struct drm_info_list mdp5_debugfs_list[] = { - {"smp", smp_show }, -}; - -static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) -{ - drm_debugfs_create_files(mdp5_debugfs_list, - ARRAY_SIZE(mdp5_debugfs_list), - minor->debugfs_root, minor); - - return 0; -} -#endif - static const struct mdp_kms_funcs kms_funcs = { .base = { .hw_init = mdp5_hw_init, @@ -256,9 +233,6 @@ static const struct mdp_kms_funcs kms_funcs = { .complete_commit = mdp5_complete_commit, .get_format = mdp_get_format, .destroy = mdp5_kms_destroy, -#ifdef CONFIG_DEBUG_FS - .debugfs_init = mdp5_kms_debugfs_init, -#endif }, .set_irqmask = mdp5_set_irqmask, }; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 8b59562e29e2..b4bebb425d22 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -325,22 +325,17 @@ void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state state->released = 0; } -void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p) +void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p, + struct mdp5_global_state *global_state) { struct mdp5_kms *mdp5_kms = get_kms(smp); struct mdp5_hw_pipe_state *hwpstate; struct mdp5_smp_state *state; - struct mdp5_global_state *global_state; int total = 0, i, j; drm_printf(p, "name\tinuse\tplane\n"); drm_printf(p, "----\t-----\t-----\n"); - if (drm_can_sleep()) - drm_modeset_lock(&mdp5_kms->glob_state_lock, NULL); - - global_state = mdp5_get_existing_global_state(mdp5_kms); - /* grab these *after* we hold the state_lock */ hwpstate = &global_state->hwpipe; state = &global_state->smp; @@ -365,9 +360,6 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p) drm_printf(p, "TOTAL:\t%d\t(of %d)\n", total, smp->blk_cnt); drm_printf(p, "AVAIL:\t%d\n", smp->blk_cnt - bitmap_weight(state->state, smp->blk_cnt)); - - if (drm_can_sleep()) - drm_modeset_unlock(&mdp5_kms->glob_state_lock); } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h index d8b6a11413d9..21732ed485be 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h @@ -69,7 +69,9 @@ struct mdp5_smp; struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg); -void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p); +struct mdp5_global_state; +void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p, + struct mdp5_global_state *global_state); uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, const struct mdp_format *format, From ffa0c87f172bf7a0132aa960db412f8d63b2f533 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 3 Dec 2023 03:05:32 +0300 Subject: [PATCH 085/295] drm/msm/mdp5: drop global_state_lock Since the commit b962a12050a3 ("drm/atomic: integrate modeset lock with private objects") the DRM framework no longer requires the external lock for private objects. Drop the lock, letting the DRM to manage private object locking. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/570183/ Link: https://lore.kernel.org/r/20231203000532.1290480-6-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 8 -------- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h | 1 - 2 files changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index d0aff128b1ed..a874fd95cc20 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -84,11 +84,6 @@ struct mdp5_global_state *mdp5_get_global_state(struct drm_atomic_state *s) struct msm_drm_private *priv = s->dev->dev_private; struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); struct drm_private_state *priv_state; - int ret; - - ret = drm_modeset_lock(&mdp5_kms->glob_state_lock, s->acquire_ctx); - if (ret) - return ERR_PTR(ret); priv_state = drm_atomic_get_private_obj_state(s, &mdp5_kms->glob_state); if (IS_ERR(priv_state)) @@ -138,8 +133,6 @@ static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms) { struct mdp5_global_state *state; - drm_modeset_lock_init(&mdp5_kms->glob_state_lock); - state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; @@ -580,7 +573,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms) pm_runtime_disable(&mdp5_kms->pdev->dev); drm_atomic_private_obj_fini(&mdp5_kms->glob_state); - drm_modeset_lock_fini(&mdp5_kms->glob_state_lock); } static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt, diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h index ee68e9913f8c..fac9f05aa639 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h @@ -40,7 +40,6 @@ struct mdp5_kms { * Global private object state, Do not access directly, use * mdp5_global_get_state() */ - struct drm_modeset_lock glob_state_lock; struct drm_private_obj glob_state; struct mdp5_smp *smp; From 3b09cc7799c10621104a19fa7f0f40e119964a97 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 15 Feb 2024 09:53:08 +0100 Subject: [PATCH 086/295] drm/mediatek: dsi: Use GENMASK() for register mask definitions Change magic numerical masks with usage of the GENMASK() macro to improve readability. This commit brings no functional changes. Reviewed-by: Alexandre Mergnat Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20240215085316.56835-2-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 45 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index a2fdfc8ddb15..c66e18006070 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -58,18 +58,18 @@ #define DSI_TXRX_CTRL 0x18 #define VC_NUM BIT(1) -#define LANE_NUM (0xf << 2) +#define LANE_NUM GENMASK(5, 2) #define DIS_EOT BIT(6) #define NULL_EN BIT(7) #define TE_FREERUN BIT(8) #define EXT_TE_EN BIT(9) #define EXT_TE_EDGE BIT(10) -#define MAX_RTN_SIZE (0xf << 12) +#define MAX_RTN_SIZE GENMASK(15, 12) #define HSTX_CKLP_EN BIT(16) #define DSI_PSCTRL 0x1c -#define DSI_PS_WC 0x3fff -#define DSI_PS_SEL (3 << 16) +#define DSI_PS_WC GENMASK(13, 0) +#define DSI_PS_SEL GENMASK(17, 16) #define PACKED_PS_16BIT_RGB565 (0 << 16) #define LOOSELY_PS_18BIT_RGB666 (1 << 16) #define PACKED_PS_18BIT_RGB666 (2 << 16) @@ -109,26 +109,26 @@ #define LD0_WAKEUP_EN BIT(2) #define DSI_PHY_TIMECON0 0x110 -#define LPX (0xff << 0) -#define HS_PREP (0xff << 8) -#define HS_ZERO (0xff << 16) -#define HS_TRAIL (0xff << 24) +#define LPX GENMASK(7, 0) +#define HS_PREP GENMASK(15, 8) +#define HS_ZERO GENMASK(23, 16) +#define HS_TRAIL GENMASK(31, 24) #define DSI_PHY_TIMECON1 0x114 -#define TA_GO (0xff << 0) -#define TA_SURE (0xff << 8) -#define TA_GET (0xff << 16) -#define DA_HS_EXIT (0xff << 24) +#define TA_GO GENMASK(7, 0) +#define TA_SURE GENMASK(15, 8) +#define TA_GET GENMASK(23, 16) +#define DA_HS_EXIT GENMASK(31, 24) #define DSI_PHY_TIMECON2 0x118 -#define CONT_DET (0xff << 0) -#define CLK_ZERO (0xff << 16) -#define CLK_TRAIL (0xff << 24) +#define CONT_DET GENMASK(7, 0) +#define CLK_ZERO GENMASK(23, 16) +#define CLK_TRAIL GENMASK(31, 24) #define DSI_PHY_TIMECON3 0x11c -#define CLK_HS_PREP (0xff << 0) -#define CLK_HS_POST (0xff << 8) -#define CLK_HS_EXIT (0xff << 16) +#define CLK_HS_PREP GENMASK(7, 0) +#define CLK_HS_POST GENMASK(15, 8) +#define CLK_HS_EXIT GENMASK(23, 16) #define DSI_VM_CMD_CON 0x130 #define VM_CMD_EN BIT(0) @@ -138,13 +138,14 @@ #define FORCE_COMMIT BIT(0) #define BYPASS_SHADOW BIT(1) -#define CONFIG (0xff << 0) +/* CMDQ related bits */ +#define CONFIG GENMASK(7, 0) #define SHORT_PACKET 0 #define LONG_PACKET 2 #define BTA BIT(2) -#define DATA_ID (0xff << 8) -#define DATA_0 (0xff << 16) -#define DATA_1 (0xff << 24) +#define DATA_ID GENMASK(15, 8) +#define DATA_0 GENMASK(23, 16) +#define DATA_1 GENMASK(31, 24) #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) From fae6f815505301b92d9113764f4d76d0bfe45607 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 15 Feb 2024 09:53:09 +0100 Subject: [PATCH 087/295] drm/mediatek: dsi: Fix DSI RGB666 formats and definitions The register bits definitions for RGB666 formats are wrong in multiple ways: first, in the DSI_PS_SEL bits region, the Packed 18-bits RGB666 format is selected with bit 1, while the Loosely Packed one is bit 2, and second - the definition name "LOOSELY_PS_18BIT_RGB666" is wrong because the loosely packed format is 24 bits instead! Either way, functions mtk_dsi_ps_control_vact() and mtk_dsi_ps_control() do not even agree on the DSI_PS_SEL bit to set in DSI_PSCTRL: one sets loosely packed (24) on RGB666, the other sets packed (18), and the other way around for RGB666_PACKED. Fixing this entire stack of issues is done in one go: - Use the correct bit for the Loosely Packed RGB666 definition - Rename LOOSELY_PS_18BIT_RGB666 to LOOSELY_PS_24BIT_RGB666 - Change ps_bpp_mode in mtk_dsi_ps_control_vact() to set: - Loosely Packed, 24-bits for MIPI_DSI_FMT_RGB666 - Packed, 18-bits for MIPI_DSI_FMT_RGB666_PACKED Fixes: 2e54c14e310f ("drm/mediatek: Add DSI sub driver") Reviewed-by: Alexandre Mergnat Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20240215085316.56835-3-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index c66e18006070..8af0afbe9e3d 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -71,8 +71,8 @@ #define DSI_PS_WC GENMASK(13, 0) #define DSI_PS_SEL GENMASK(17, 16) #define PACKED_PS_16BIT_RGB565 (0 << 16) -#define LOOSELY_PS_18BIT_RGB666 (1 << 16) -#define PACKED_PS_18BIT_RGB666 (2 << 16) +#define PACKED_PS_18BIT_RGB666 (1 << 16) +#define LOOSELY_PS_24BIT_RGB666 (2 << 16) #define PACKED_PS_24BIT_RGB888 (3 << 16) #define DSI_VSA_NL 0x20 @@ -370,10 +370,10 @@ static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi) ps_bpp_mode |= PACKED_PS_24BIT_RGB888; break; case MIPI_DSI_FMT_RGB666: - ps_bpp_mode |= PACKED_PS_18BIT_RGB666; + ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666; break; case MIPI_DSI_FMT_RGB666_PACKED: - ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666; + ps_bpp_mode |= PACKED_PS_18BIT_RGB666; break; case MIPI_DSI_FMT_RGB565: ps_bpp_mode |= PACKED_PS_16BIT_RGB565; @@ -427,7 +427,7 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi) dsi_tmp_buf_bpp = 3; break; case MIPI_DSI_FMT_RGB666: - tmp_reg = LOOSELY_PS_18BIT_RGB666; + tmp_reg = LOOSELY_PS_24BIT_RGB666; dsi_tmp_buf_bpp = 3; break; case MIPI_DSI_FMT_RGB666_PACKED: From 5c6186a8f07e89f769d99c522cae78a121277b2d Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 15 Feb 2024 09:53:10 +0100 Subject: [PATCH 088/295] drm/mediatek: dsi: Cleanup functions mtk_dsi_ps_control{_vact}() Function mtk_dsi_ps_control() is a subset of mtk_dsi_ps_control_vact(): merge the two in one mtk_dsi_ps_control() function by adding one function parameter `config_vact` which, when true, writes the VACT related registers. Reviewed-by: Fei Shao Reviewed-by: Alexandre Mergnat Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20240215085316.56835-4-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 78 ++++++++++-------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 8af0afbe9e3d..0a83875ec1ba 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -351,40 +351,6 @@ static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi) mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN); } -static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi) -{ - struct videomode *vm = &dsi->vm; - u32 dsi_buf_bpp, ps_wc; - u32 ps_bpp_mode; - - if (dsi->format == MIPI_DSI_FMT_RGB565) - dsi_buf_bpp = 2; - else - dsi_buf_bpp = 3; - - ps_wc = vm->hactive * dsi_buf_bpp; - ps_bpp_mode = ps_wc; - - switch (dsi->format) { - case MIPI_DSI_FMT_RGB888: - ps_bpp_mode |= PACKED_PS_24BIT_RGB888; - break; - case MIPI_DSI_FMT_RGB666: - ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666; - break; - case MIPI_DSI_FMT_RGB666_PACKED: - ps_bpp_mode |= PACKED_PS_18BIT_RGB666; - break; - case MIPI_DSI_FMT_RGB565: - ps_bpp_mode |= PACKED_PS_16BIT_RGB565; - break; - } - - writel(vm->vactive, dsi->regs + DSI_VACT_NL); - writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL); - writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); -} - static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) { u32 tmp_reg; @@ -416,36 +382,42 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); } -static void mtk_dsi_ps_control(struct mtk_dsi *dsi) +static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact) { - u32 dsi_tmp_buf_bpp; - u32 tmp_reg; + struct videomode *vm = &dsi->vm; + u32 dsi_buf_bpp, ps_wc; + u32 ps_bpp_mode; + + if (dsi->format == MIPI_DSI_FMT_RGB565) + dsi_buf_bpp = 2; + else + dsi_buf_bpp = 3; + + ps_wc = vm->hactive * dsi_buf_bpp; + ps_bpp_mode = ps_wc; switch (dsi->format) { + default: + fallthrough; case MIPI_DSI_FMT_RGB888: - tmp_reg = PACKED_PS_24BIT_RGB888; - dsi_tmp_buf_bpp = 3; + ps_bpp_mode |= PACKED_PS_24BIT_RGB888; break; case MIPI_DSI_FMT_RGB666: - tmp_reg = LOOSELY_PS_24BIT_RGB666; - dsi_tmp_buf_bpp = 3; + ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666; break; case MIPI_DSI_FMT_RGB666_PACKED: - tmp_reg = PACKED_PS_18BIT_RGB666; - dsi_tmp_buf_bpp = 3; + ps_bpp_mode |= PACKED_PS_18BIT_RGB666; break; case MIPI_DSI_FMT_RGB565: - tmp_reg = PACKED_PS_16BIT_RGB565; - dsi_tmp_buf_bpp = 2; - break; - default: - tmp_reg = PACKED_PS_24BIT_RGB888; - dsi_tmp_buf_bpp = 3; + ps_bpp_mode |= PACKED_PS_16BIT_RGB565; break; } - tmp_reg += dsi->vm.hactive * dsi_tmp_buf_bpp & DSI_PS_WC; - writel(tmp_reg, dsi->regs + DSI_PSCTRL); + if (config_vact) { + writel(vm->vactive, dsi->regs + DSI_VACT_NL); + writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); + } + writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL); } static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) @@ -521,7 +493,7 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); - mtk_dsi_ps_control(dsi); + mtk_dsi_ps_control(dsi, false); } static void mtk_dsi_start(struct mtk_dsi *dsi) @@ -666,7 +638,7 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) mtk_dsi_reset_engine(dsi); mtk_dsi_phy_timconfig(dsi); - mtk_dsi_ps_control_vact(dsi); + mtk_dsi_ps_control(dsi, true); mtk_dsi_set_vm_cmd(dsi); mtk_dsi_config_vdo_timing(dsi); mtk_dsi_set_interrupt_enable(dsi); From aaeb9335fb38c8d3f746e0fb06d4c7ae90985714 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 15 Feb 2024 09:53:11 +0100 Subject: [PATCH 089/295] drm/mediatek: dsi: Use bitfield macros where useful Instead of open coding bitshifting for various register fields, use the bitfield macro FIELD_PREP(): this allows to enhance the human readability, decrease likeliness of mistakes (and register field overflowing) and also to simplify the code. The latter is especially seen in mtk_dsi_rxtx_control(), where it was possible to change a switch to a short for loop and to also remove the need to check for maximum DSI lanes == 4 thanks to the FIELD_PREP macro masking the value. While at it, also add the missing DA_HS_SYNC bitmask, used in mtk_dsi_phy_timconfig(). Reviewed-by: Alexandre Mergnat Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20240215085316.56835-5-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 95 ++++++++++++++++-------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 0a83875ec1ba..a330bb94c44a 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -3,6 +3,7 @@ * Copyright (c) 2015 MediaTek Inc. */ +#include #include #include #include @@ -70,16 +71,19 @@ #define DSI_PSCTRL 0x1c #define DSI_PS_WC GENMASK(13, 0) #define DSI_PS_SEL GENMASK(17, 16) -#define PACKED_PS_16BIT_RGB565 (0 << 16) -#define PACKED_PS_18BIT_RGB666 (1 << 16) -#define LOOSELY_PS_24BIT_RGB666 (2 << 16) -#define PACKED_PS_24BIT_RGB888 (3 << 16) +#define PACKED_PS_16BIT_RGB565 0 +#define PACKED_PS_18BIT_RGB666 1 +#define LOOSELY_PS_24BIT_RGB666 2 +#define PACKED_PS_24BIT_RGB888 3 #define DSI_VSA_NL 0x20 #define DSI_VBP_NL 0x24 #define DSI_VFP_NL 0x28 #define DSI_VACT_NL 0x2C +#define VACT_NL GENMASK(14, 0) #define DSI_SIZE_CON 0x38 +#define DSI_HEIGHT GENMASK(30, 16) +#define DSI_WIDTH GENMASK(14, 0) #define DSI_HSA_WC 0x50 #define DSI_HBP_WC 0x54 #define DSI_HFP_WC 0x58 @@ -122,6 +126,7 @@ #define DSI_PHY_TIMECON2 0x118 #define CONT_DET GENMASK(7, 0) +#define DA_HS_SYNC GENMASK(15, 8) #define CLK_ZERO GENMASK(23, 16) #define CLK_TRAIL GENMASK(31, 24) @@ -253,14 +258,23 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) timing->clk_hs_zero = timing->clk_hs_trail * 4; timing->clk_hs_exit = 2 * timing->clk_hs_trail; - timcon0 = timing->lpx | timing->da_hs_prepare << 8 | - timing->da_hs_zero << 16 | timing->da_hs_trail << 24; - timcon1 = timing->ta_go | timing->ta_sure << 8 | - timing->ta_get << 16 | timing->da_hs_exit << 24; - timcon2 = 1 << 8 | timing->clk_hs_zero << 16 | - timing->clk_hs_trail << 24; - timcon3 = timing->clk_hs_prepare | timing->clk_hs_post << 8 | - timing->clk_hs_exit << 16; + timcon0 = FIELD_PREP(LPX, timing->lpx) | + FIELD_PREP(HS_PREP, timing->da_hs_prepare) | + FIELD_PREP(HS_ZERO, timing->da_hs_zero) | + FIELD_PREP(HS_TRAIL, timing->da_hs_trail); + + timcon1 = FIELD_PREP(TA_GO, timing->ta_go) | + FIELD_PREP(TA_SURE, timing->ta_sure) | + FIELD_PREP(TA_GET, timing->ta_get) | + FIELD_PREP(DA_HS_EXIT, timing->da_hs_exit); + + timcon2 = FIELD_PREP(DA_HS_SYNC, 1) | + FIELD_PREP(CLK_ZERO, timing->clk_hs_zero) | + FIELD_PREP(CLK_TRAIL, timing->clk_hs_trail); + + timcon3 = FIELD_PREP(CLK_HS_PREP, timing->clk_hs_prepare) | + FIELD_PREP(CLK_HS_POST, timing->clk_hs_post) | + FIELD_PREP(CLK_HS_EXIT, timing->clk_hs_exit); writel(timcon0, dsi->regs + DSI_PHY_TIMECON0); writel(timcon1, dsi->regs + DSI_PHY_TIMECON1); @@ -353,71 +367,61 @@ static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi) static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) { - u32 tmp_reg; + u32 regval, tmp_reg = 0; + u8 i; - switch (dsi->lanes) { - case 1: - tmp_reg = 1 << 2; - break; - case 2: - tmp_reg = 3 << 2; - break; - case 3: - tmp_reg = 7 << 2; - break; - case 4: - tmp_reg = 0xf << 2; - break; - default: - tmp_reg = 0xf << 2; - break; - } + /* Number of DSI lanes (max 4 lanes), each bit enables one DSI lane. */ + for (i = 0; i < dsi->lanes; i++) + tmp_reg |= BIT(i); + + regval = FIELD_PREP(LANE_NUM, tmp_reg); if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) - tmp_reg |= HSTX_CKLP_EN; + regval |= HSTX_CKLP_EN; if (dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) - tmp_reg |= DIS_EOT; + regval |= DIS_EOT; - writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); + writel(regval, dsi->regs + DSI_TXRX_CTRL); } static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact) { - struct videomode *vm = &dsi->vm; - u32 dsi_buf_bpp, ps_wc; - u32 ps_bpp_mode; + u32 dsi_buf_bpp, ps_val, ps_wc, vact_nl; if (dsi->format == MIPI_DSI_FMT_RGB565) dsi_buf_bpp = 2; else dsi_buf_bpp = 3; - ps_wc = vm->hactive * dsi_buf_bpp; - ps_bpp_mode = ps_wc; + /* Word count */ + ps_wc = FIELD_PREP(DSI_PS_WC, dsi->vm.hactive * dsi_buf_bpp); + ps_val = ps_wc; + /* Pixel Stream type */ switch (dsi->format) { default: fallthrough; case MIPI_DSI_FMT_RGB888: - ps_bpp_mode |= PACKED_PS_24BIT_RGB888; + ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_24BIT_RGB888); break; case MIPI_DSI_FMT_RGB666: - ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666; + ps_val |= FIELD_PREP(DSI_PS_SEL, LOOSELY_PS_24BIT_RGB666); break; case MIPI_DSI_FMT_RGB666_PACKED: - ps_bpp_mode |= PACKED_PS_18BIT_RGB666; + ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_18BIT_RGB666); break; case MIPI_DSI_FMT_RGB565: - ps_bpp_mode |= PACKED_PS_16BIT_RGB565; + ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_16BIT_RGB565); break; } if (config_vact) { - writel(vm->vactive, dsi->regs + DSI_VACT_NL); + vact_nl = FIELD_PREP(VACT_NL, dsi->vm.vactive); + writel(vact_nl, dsi->regs + DSI_VACT_NL); writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); } - writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL); + writel(ps_val, dsi->regs + DSI_PSCTRL); } static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) @@ -444,7 +448,8 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) writel(vm->vactive, dsi->regs + DSI_VACT_NL); if (dsi->driver_data->has_size_ctl) - writel(vm->vactive << 16 | vm->hactive, + writel(FIELD_PREP(DSI_HEIGHT, vm->vactive) | + FIELD_PREP(DSI_WIDTH, vm->hactive), dsi->regs + DSI_SIZE_CON); horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); From ff4e452146295a9311dec3c845a8bf533ed63379 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 15 Feb 2024 09:53:12 +0100 Subject: [PATCH 090/295] drm/mediatek: dsi: Replace open-coded instance of HZ_PER_MHZ In mtk_dsi_phy_timconfig(), we're dividing the `data_rate` variable, expressed in Hz to retrieve a value in MHz: instead of open-coding, use the HZ_PER_MHZ definition, available in linux/units.h. Reviewed-by: Alexandre Mergnat Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20240215085316.56835-6-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_dsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index a330bb94c44a..52758cab0abf 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -13,6 +13,7 @@ #include #include #include +#include #include