From f0de40a131d9bd9b722f371f9fca35e81662fc53 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:34 -0700 Subject: [PATCH 01/84] drm/msm: Reorder lock vs submit alloc This lets us drop the NORETRY. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496114/ Link: https://lore.kernel.org/r/20220802155152.1727594-2-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_submit.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index c9e4aeb14f4a..b7c61a99d274 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -36,7 +36,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, if (sz > SIZE_MAX) return ERR_PTR(-ENOMEM); - submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + submit = kzalloc(sz, GFP_KERNEL); if (!submit) return ERR_PTR(-ENOMEM); @@ -771,25 +771,21 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, trace_msm_gpu_submit(pid_nr(pid), ring->id, submitid, args->nr_bos, args->nr_cmds); - ret = mutex_lock_interruptible(&queue->lock); - if (ret) - goto out_post_unlock; - if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) { out_fence_fd = get_unused_fd_flags(O_CLOEXEC); if (out_fence_fd < 0) { ret = out_fence_fd; - goto out_unlock; + return ret; } } - submit = submit_create(dev, gpu, queue, args->nr_bos, - args->nr_cmds); - if (IS_ERR(submit)) { - ret = PTR_ERR(submit); - submit = NULL; - goto out_unlock; - } + submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds); + if (IS_ERR(submit)) + return PTR_ERR(submit); + + ret = mutex_lock_interruptible(&queue->lock); + if (ret) + goto out_post_unlock; submit->pid = pid; submit->ident = submitid; @@ -965,9 +961,9 @@ out_unlock: if (ret && (out_fence_fd >= 0)) put_unused_fd(out_fence_fd); mutex_unlock(&queue->lock); +out_post_unlock: if (submit) msm_gem_submit_put(submit); -out_post_unlock: if (!IS_ERR_OR_NULL(post_deps)) { for (i = 0; i < args->nr_out_syncobjs; ++i) { kfree(post_deps[i].chain); From fc1dd04c3841c45e2bc811ed96af62af5fc77911 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:35 -0700 Subject: [PATCH 02/84] drm/msm: Small submit cleanup Move more initialization into submit_create(). Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496120/ Link: https://lore.kernel.org/r/20220802155152.1727594-3-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_submit.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index b7c61a99d274..c7819781879c 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -26,6 +26,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, struct msm_gpu_submitqueue *queue, uint32_t nr_bos, uint32_t nr_cmds) { + static atomic_t ident = ATOMIC_INIT(0); struct msm_gem_submit *submit; uint64_t sz; int ret; @@ -52,9 +53,13 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, submit->gpu = gpu; submit->cmd = (void *)&submit->bos[nr_bos]; submit->queue = queue; + submit->pid = get_pid(task_pid(current)); submit->ring = gpu->rb[queue->ring_nr]; submit->fault_dumped = false; + /* Get a unique identifier for the submission for logging purposes */ + submit->ident = atomic_inc_return(&ident) - 1; + INIT_LIST_HEAD(&submit->node); return submit; @@ -718,7 +723,6 @@ static void msm_process_post_deps(struct msm_submit_post_dep *post_deps, int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file) { - static atomic_t ident = ATOMIC_INIT(0); struct msm_drm_private *priv = dev->dev_private; struct drm_msm_gem_submit *args = data; struct msm_file_private *ctx = file->driver_priv; @@ -729,10 +733,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct msm_submit_post_dep *post_deps = NULL; struct drm_syncobj **syncobjs_to_reset = NULL; int out_fence_fd = -1; - struct pid *pid = get_pid(task_pid(current)); bool has_ww_ticket = false; unsigned i; - int ret, submitid; + int ret; if (!gpu) return -ENXIO; @@ -764,12 +767,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (!queue) return -ENOENT; - /* Get a unique identifier for the submission for logging purposes */ - submitid = atomic_inc_return(&ident) - 1; - ring = gpu->rb[queue->ring_nr]; - trace_msm_gpu_submit(pid_nr(pid), ring->id, submitid, - args->nr_bos, args->nr_cmds); if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) { out_fence_fd = get_unused_fd_flags(O_CLOEXEC); @@ -783,13 +781,13 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (IS_ERR(submit)) return PTR_ERR(submit); + trace_msm_gpu_submit(pid_nr(submit->pid), ring->id, submit->ident, + args->nr_bos, args->nr_cmds); + ret = mutex_lock_interruptible(&queue->lock); if (ret) goto out_post_unlock; - submit->pid = pid; - submit->ident = submitid; - if (args->flags & MSM_SUBMIT_SUDO) submit->in_rb = true; From 05ba44b3704e2115251c340fc72db609a0b97f3b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:36 -0700 Subject: [PATCH 03/84] drm/msm: Split out idr_lock Otherwise if we hit reclaim pinning objects in the submit path, we'll be blocking retire_worker trying to free a submit. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496116/ Link: https://lore.kernel.org/r/20220802155152.1727594-4-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_drv.c | 4 ++-- drivers/gpu/drm/msm/msm_gem_submit.c | 10 ++++++++-- drivers/gpu/drm/msm/msm_gpu.h | 4 +++- drivers/gpu/drm/msm/msm_submitqueue.c | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1ed4cd09dbf8..d7ca025457b6 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -883,13 +883,13 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, * retired, so if the fence is not found it means there is nothing * to wait for */ - ret = mutex_lock_interruptible(&queue->lock); + ret = mutex_lock_interruptible(&queue->idr_lock); if (ret) return ret; fence = idr_find(&queue->fence_idr, fence_id); if (fence) fence = dma_fence_get_rcu(fence); - mutex_unlock(&queue->lock); + mutex_unlock(&queue->idr_lock); if (!fence) return 0; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index c7819781879c..16c662808522 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -72,9 +72,9 @@ void __msm_gem_submit_destroy(struct kref *kref) unsigned i; if (submit->fence_id) { - mutex_lock(&submit->queue->lock); + mutex_lock(&submit->queue->idr_lock); idr_remove(&submit->queue->fence_idr, submit->fence_id); - mutex_unlock(&submit->queue->lock); + mutex_unlock(&submit->queue->idr_lock); } dma_fence_put(submit->user_fence); @@ -881,6 +881,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, submit->nr_cmds = i; + mutex_lock(&queue->idr_lock); + /* * If using userspace provided seqno fence, validate that the id * is available before arming sched job. Since access to fence_idr @@ -889,6 +891,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, */ if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) && idr_find(&queue->fence_idr, args->fence)) { + mutex_unlock(&queue->idr_lock); ret = -EINVAL; goto out; } @@ -921,6 +924,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, submit->user_fence, 1, INT_MAX, GFP_KERNEL); } + + mutex_unlock(&queue->idr_lock); + if (submit->fence_id < 0) { ret = submit->fence_id; submit->fence_id = 0; diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 4d935fedd2ac..962d2070bcdf 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -466,7 +466,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, * @node: node in the context's list of submitqueues * @fence_idr: maps fence-id to dma_fence for userspace visible fence * seqno, protected by submitqueue lock - * @lock: submitqueue lock + * @idr_lock: for serializing access to fence_idr + * @lock: submitqueue lock for serializing submits on a queue * @ref: reference count * @entity: the submit job-queue */ @@ -479,6 +480,7 @@ struct msm_gpu_submitqueue { struct msm_file_private *ctx; struct list_head node; struct idr fence_idr; + struct mutex idr_lock; struct mutex lock; struct kref ref; struct drm_sched_entity *entity; diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index f486a3cd4e55..c6929e205b51 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -200,6 +200,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, *id = queue->id; idr_init(&queue->fence_idr); + mutex_init(&queue->idr_lock); mutex_init(&queue->lock); list_add_tail(&queue->node, &ctx->submitqueues); From 01780d02634a3a99ba0c3ca52d06d0cdfdf82331 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:37 -0700 Subject: [PATCH 04/84] drm/msm/gem: Check for active in shrinker path Currently in our shrinker path we shouldn't be encountering anything that is active, but this will change in subsequent patches. So check if there are unsignaled fences. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496117/ Link: https://lore.kernel.org/r/20220802155152.1727594-5-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 10 ++++++++++ drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_shrinker.c | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 8ddbd2e001d4..b55d252aef17 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -870,6 +870,16 @@ static void update_inactive(struct msm_gem_object *msm_obj) mutex_unlock(&priv->mm_lock); } +bool msm_gem_active(struct drm_gem_object *obj) +{ + GEM_WARN_ON(!msm_gem_is_locked(obj)); + + if (to_msm_bo(obj)->pin_count) + return true; + + return !dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true)); +} + int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) { bool write = !!(op & MSM_PREP_WRITE); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 432032ad4aed..0ab0dc4f8c25 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -173,6 +173,7 @@ void msm_gem_put_vaddr(struct drm_gem_object *obj); int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu); void msm_gem_active_put(struct drm_gem_object *obj); +bool msm_gem_active(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 0317055e3253..0ab058734777 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -43,6 +43,9 @@ purge(struct msm_gem_object *msm_obj) if (!is_purgeable(msm_obj)) return false; + if (msm_gem_active(&msm_obj->base)) + return false; + /* * This will move the obj out of still_in_list to * the purged list @@ -58,6 +61,9 @@ evict(struct msm_gem_object *msm_obj) if (is_unevictable(msm_obj)) return false; + if (msm_gem_active(&msm_obj->base)) + return false; + msm_gem_evict(&msm_obj->base); return true; From 901df24d7ca69c38a9a100b6732cc538a6c255a2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:38 -0700 Subject: [PATCH 05/84] drm/msm/gem: Rename update_inactive Really what this is doing is updating various LRU lists. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496115/ Link: https://lore.kernel.org/r/20220802155152.1727594-6-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b55d252aef17..97467364dc0a 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -19,7 +19,7 @@ #include "msm_gpu.h" #include "msm_mmu.h" -static void update_inactive(struct msm_gem_object *msm_obj); +static void update_lru(struct drm_gem_object *obj); static dma_addr_t physaddr(struct drm_gem_object *obj) { @@ -132,7 +132,7 @@ static struct page **get_pages(struct drm_gem_object *obj) if (msm_obj->flags & MSM_BO_WC) sync_for_device(msm_obj); - update_inactive(msm_obj); + update_lru(obj); } return msm_obj->pages; @@ -193,7 +193,7 @@ struct page **msm_gem_get_pages(struct drm_gem_object *obj) if (!IS_ERR(p)) { msm_obj->pin_count++; - update_inactive(msm_obj); + update_lru(obj); } msm_gem_unlock(obj); @@ -207,7 +207,7 @@ void msm_gem_put_pages(struct drm_gem_object *obj) msm_gem_lock(obj); msm_obj->pin_count--; GEM_WARN_ON(msm_obj->pin_count < 0); - update_inactive(msm_obj); + update_lru(obj); msm_gem_unlock(obj); } @@ -449,7 +449,7 @@ void msm_gem_unpin_locked(struct drm_gem_object *obj) msm_obj->pin_count--; GEM_WARN_ON(msm_obj->pin_count < 0); - update_inactive(msm_obj); + update_lru(obj); } struct msm_gem_vma *msm_gem_get_vma_locked(struct drm_gem_object *obj, @@ -658,7 +658,7 @@ static void *get_vaddr(struct drm_gem_object *obj, unsigned madv) goto fail; } - update_inactive(msm_obj); + update_lru(obj); } return msm_obj->vaddr; @@ -730,7 +730,7 @@ int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv) * between inactive lists */ if (msm_obj->active_count == 0) - update_inactive(msm_obj); + update_lru(obj); msm_gem_unlock(obj); @@ -757,7 +757,7 @@ void msm_gem_purge(struct drm_gem_object *obj) put_iova_vmas(obj); msm_obj->madv = __MSM_MADV_PURGED; - update_inactive(msm_obj); + update_lru(obj); drm_gem_free_mmap_offset(obj); @@ -792,7 +792,7 @@ void msm_gem_evict(struct drm_gem_object *obj) put_pages(obj); - update_inactive(msm_obj); + update_lru(obj); } void msm_gem_vunmap(struct drm_gem_object *obj) @@ -835,13 +835,14 @@ void msm_gem_active_put(struct drm_gem_object *obj) GEM_WARN_ON(!msm_gem_is_locked(obj)); if (--msm_obj->active_count == 0) { - update_inactive(msm_obj); + update_lru(obj); } } -static void update_inactive(struct msm_gem_object *msm_obj) +static void update_lru(struct drm_gem_object *obj) { - struct msm_drm_private *priv = msm_obj->base.dev->dev_private; + struct msm_drm_private *priv = obj->dev->dev_private; + struct msm_gem_object *msm_obj = to_msm_bo(obj); GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); From e7cd5ee9aa77d9639566c721ad6dda8c25673235 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:39 -0700 Subject: [PATCH 06/84] drm/msm/gem: Rename to pin/unpin_pages Since that is what these fxns actually do.. they are getting *pinned* pages (as opposed to cases where we need pages, but don't need them pinned, like CPU mappings). Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496121/ Link: https://lore.kernel.org/r/20220802155152.1727594-7-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 20 ++++++++++++++------ drivers/gpu/drm/msm/msm_gem.h | 4 ++-- drivers/gpu/drm/msm/msm_gem_prime.c | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 97467364dc0a..3da64c7f65a2 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -177,30 +177,38 @@ static void put_pages(struct drm_gem_object *obj) } } -struct page **msm_gem_get_pages(struct drm_gem_object *obj) +static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); struct page **p; - msm_gem_lock(obj); + GEM_WARN_ON(!msm_gem_is_locked(obj)); if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) { - msm_gem_unlock(obj); return ERR_PTR(-EBUSY); } p = get_pages(obj); - if (!IS_ERR(p)) { msm_obj->pin_count++; update_lru(obj); } - msm_gem_unlock(obj); return p; } -void msm_gem_put_pages(struct drm_gem_object *obj) +struct page **msm_gem_pin_pages(struct drm_gem_object *obj) +{ + struct page **p; + + msm_gem_lock(obj); + p = msm_gem_pin_pages_locked(obj); + msm_gem_unlock(obj); + + return p; +} + +void msm_gem_unpin_pages(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 0ab0dc4f8c25..6fe521ccda45 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -159,8 +159,8 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace, uint64_t *iova); void msm_gem_unpin_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace); -struct page **msm_gem_get_pages(struct drm_gem_object *obj); -void msm_gem_put_pages(struct drm_gem_object *obj); +struct page **msm_gem_pin_pages(struct drm_gem_object *obj); +void msm_gem_unpin_pages(struct drm_gem_object *obj); int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index dcc8a573bc76..c1d91863df05 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -63,12 +63,12 @@ struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, int msm_gem_prime_pin(struct drm_gem_object *obj) { if (!obj->import_attach) - msm_gem_get_pages(obj); + msm_gem_pin_pages(obj); return 0; } void msm_gem_prime_unpin(struct drm_gem_object *obj) { if (!obj->import_attach) - msm_gem_put_pages(obj); + msm_gem_unpin_pages(obj); } From 9fd5ff7f284a8554f9fa585ce45585deacfd7761 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:40 -0700 Subject: [PATCH 07/84] drm/msm/gem: Consolidate pin/unpin paths Avoid having multiple spots where we increment/decrement pin_count (and associated LRU updating) Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496130/ Link: https://lore.kernel.org/r/20220802155152.1727594-8-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 3da64c7f65a2..407b18a24dc4 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -190,7 +190,7 @@ static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj) p = get_pages(obj); if (!IS_ERR(p)) { - msm_obj->pin_count++; + to_msm_bo(obj)->pin_count++; update_lru(obj); } @@ -213,9 +213,7 @@ void msm_gem_unpin_pages(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); msm_gem_lock(obj); - msm_obj->pin_count--; - GEM_WARN_ON(msm_obj->pin_count < 0); - update_lru(obj); + msm_gem_unpin_locked(obj); msm_gem_unlock(obj); } @@ -436,14 +434,13 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma) if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) return -EBUSY; - pages = get_pages(obj); + pages = msm_gem_pin_pages_locked(obj); if (IS_ERR(pages)) return PTR_ERR(pages); ret = msm_gem_map_vma(vma->aspace, vma, prot, msm_obj->sgt, obj->size); - - if (!ret) - msm_obj->pin_count++; + if (ret) + msm_gem_unpin_locked(obj); return ret; } From da53d8b54647482125e29ef80dd9acbb64f2d67f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:41 -0700 Subject: [PATCH 08/84] drm/msm/gem: Remove active refcnt At this point the pinned refcnt is sufficient, and the shrinker is already prepared to encounter objects which are still active according to fences attached to the resv. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496122/ Link: https://lore.kernel.org/r/20220802155152.1727594-9-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 45 ++-------------------------- drivers/gpu/drm/msm/msm_gem.h | 14 ++------- drivers/gpu/drm/msm/msm_gem_submit.c | 22 ++------------ 3 files changed, 8 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 407b18a24dc4..209438744bab 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -734,8 +734,7 @@ int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv) /* If the obj is inactive, we might need to move it * between inactive lists */ - if (msm_obj->active_count == 0) - update_lru(obj); + update_lru(obj); msm_gem_unlock(obj); @@ -788,7 +787,6 @@ void msm_gem_evict(struct drm_gem_object *obj) GEM_WARN_ON(!msm_gem_is_locked(obj)); GEM_WARN_ON(is_unevictable(msm_obj)); GEM_WARN_ON(!msm_obj->evictable); - GEM_WARN_ON(msm_obj->active_count); /* Get rid of any iommu mapping(s): */ put_iova_spaces(obj, false); @@ -813,37 +811,6 @@ void msm_gem_vunmap(struct drm_gem_object *obj) msm_obj->vaddr = NULL; } -void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct msm_drm_private *priv = obj->dev->dev_private; - - might_sleep(); - GEM_WARN_ON(!msm_gem_is_locked(obj)); - GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); - GEM_WARN_ON(msm_obj->dontneed); - - if (msm_obj->active_count++ == 0) { - mutex_lock(&priv->mm_lock); - if (msm_obj->evictable) - mark_unevictable(msm_obj); - list_move_tail(&msm_obj->mm_list, &gpu->active_list); - mutex_unlock(&priv->mm_lock); - } -} - -void msm_gem_active_put(struct drm_gem_object *obj) -{ - struct msm_gem_object *msm_obj = to_msm_bo(obj); - - might_sleep(); - GEM_WARN_ON(!msm_gem_is_locked(obj)); - - if (--msm_obj->active_count == 0) { - update_lru(obj); - } -} - static void update_lru(struct drm_gem_object *obj) { struct msm_drm_private *priv = obj->dev->dev_private; @@ -851,9 +818,6 @@ static void update_lru(struct drm_gem_object *obj) GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); - if (msm_obj->active_count != 0) - return; - mutex_lock(&priv->mm_lock); if (msm_obj->dontneed) @@ -926,7 +890,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m, stats->all.count++; stats->all.size += obj->size; - if (is_active(msm_obj)) { + if (msm_gem_active(obj)) { stats->active.count++; stats->active.size += obj->size; } @@ -954,7 +918,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m, } seq_printf(m, "%08x: %c %2d (%2d) %08llx %p", - msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', + msm_obj->flags, msm_gem_active(obj) ? 'A' : 'I', obj->name, kref_read(&obj->refcount), off, msm_obj->vaddr); @@ -1037,9 +1001,6 @@ static void msm_gem_free_object(struct drm_gem_object *obj) list_del(&msm_obj->mm_list); mutex_unlock(&priv->mm_lock); - /* object should not be on active list: */ - GEM_WARN_ON(is_active(msm_obj)); - put_iova_spaces(obj, true); if (obj->import_attach) { diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 6fe521ccda45..420ba49bf21a 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -138,7 +138,6 @@ struct msm_gem_object { char name[32]; /* Identifier to print for the debugfs files */ - int active_count; int pin_count; }; #define to_msm_bo(x) container_of(x, struct msm_gem_object, base) @@ -171,8 +170,6 @@ void *msm_gem_get_vaddr_active(struct drm_gem_object *obj); void msm_gem_put_vaddr_locked(struct drm_gem_object *obj); void msm_gem_put_vaddr(struct drm_gem_object *obj); int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); -void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu); -void msm_gem_active_put(struct drm_gem_object *obj); bool msm_gem_active(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); @@ -245,12 +242,6 @@ msm_gem_is_locked(struct drm_gem_object *obj) return dma_resv_is_locked(obj->resv) || (kref_read(&obj->refcount) == 0); } -static inline bool is_active(struct msm_gem_object *msm_obj) -{ - GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); - return msm_obj->active_count; -} - /* imported/exported objects are not purgeable: */ static inline bool is_unpurgeable(struct msm_gem_object *msm_obj) { @@ -391,9 +382,8 @@ struct msm_gem_submit { /* make sure these don't conflict w/ MSM_SUBMIT_BO_x */ #define BO_VALID 0x8000 /* is current addr in cmdstream correct/valid? */ #define BO_LOCKED 0x4000 /* obj lock is held */ -#define BO_ACTIVE 0x2000 /* active refcnt is held */ -#define BO_OBJ_PINNED 0x1000 /* obj (pages) is pinned and on active list */ -#define BO_VMA_PINNED 0x0800 /* vma (virtual address) is pinned */ +#define BO_OBJ_PINNED 0x2000 /* obj (pages) is pinned and on active list */ +#define BO_VMA_PINNED 0x1000 /* vma (virtual address) is pinned */ uint32_t flags; union { struct msm_gem_object *obj; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 16c662808522..adf358fb8e9d 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -243,17 +243,13 @@ static void submit_cleanup_bo(struct msm_gem_submit *submit, int i, if (flags & BO_OBJ_PINNED) msm_gem_unpin_locked(obj); - if (flags & BO_ACTIVE) - msm_gem_active_put(obj); - if (flags & BO_LOCKED) dma_resv_unlock(obj->resv); } static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i) { - unsigned cleanup_flags = BO_VMA_PINNED | BO_OBJ_PINNED | - BO_ACTIVE | BO_LOCKED; + unsigned cleanup_flags = BO_VMA_PINNED | BO_OBJ_PINNED | BO_LOCKED; submit_cleanup_bo(submit, i, cleanup_flags); if (!(submit->bos[i].flags & BO_VALID)) @@ -358,18 +354,6 @@ static int submit_pin_objects(struct msm_gem_submit *submit) submit->valid = true; - /* - * Increment active_count first, so if under memory pressure, we - * don't inadvertently evict a bo needed by the submit in order - * to pin an earlier bo in the same submit. - */ - for (i = 0; i < submit->nr_bos; i++) { - struct drm_gem_object *obj = &submit->bos[i].obj->base; - - msm_gem_active_get(obj, submit->gpu); - submit->bos[i].flags |= BO_ACTIVE; - } - for (i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = &submit->bos[i].obj->base; struct msm_gem_vma *vma; @@ -521,7 +505,7 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool error) unsigned i; if (error) - cleanup_flags |= BO_VMA_PINNED | BO_OBJ_PINNED | BO_ACTIVE; + cleanup_flags |= BO_VMA_PINNED | BO_OBJ_PINNED; for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -540,7 +524,7 @@ void msm_submit_retire(struct msm_gem_submit *submit) msm_gem_lock(obj); /* Note, VMA already fence-unpinned before submit: */ - submit_cleanup_bo(submit, i, BO_OBJ_PINNED | BO_ACTIVE); + submit_cleanup_bo(submit, i, BO_OBJ_PINNED); msm_gem_unlock(obj); drm_gem_object_put(obj); } From e7c2af13f811d0c23340154b7b2795876c71e4be Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:42 -0700 Subject: [PATCH 09/84] drm/gem: Add LRU/shrinker helper Add a simple LRU helper to assist with driver's shrinker implementation. It handles tracking the number of backing pages associated with a given LRU, and provides a helper to implement shrinker_scan. A driver can use multiple LRU instances to track objects in various states, for example a dontneed LRU for purgeable objects, a willneed LRU for evictable objects, and an unpinned LRU for objects without backing pages. All LRUs that the object can be moved between must share a single lock. v2: lockdep_assert_held() instead of WARN_ON(!mutex_is_locked()) v3: make drm_gem_lru_move_tail_locked() static until there is a user Cc: Daniel Vetter Cc: Thomas Zimmermann Cc: Dmitry Osipenko Signed-off-by: Rob Clark Reviewed-by: Dmitry Osipenko Patchwork: https://patchwork.freedesktop.org/patch/496128/ Link: https://lore.kernel.org/r/20220802155152.1727594-10-robdclark@gmail.com --- drivers/gpu/drm/drm_gem.c | 170 ++++++++++++++++++++++++++++++++++++++ include/drm/drm_gem.h | 55 ++++++++++++ 2 files changed, 225 insertions(+) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 86d670c71286..33f1d66dda60 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -165,6 +165,7 @@ void drm_gem_private_object_init(struct drm_device *dev, obj->resv = &obj->_resv; drm_vma_node_reset(&obj->vma_node); + INIT_LIST_HEAD(&obj->lru_node); } EXPORT_SYMBOL(drm_gem_private_object_init); @@ -951,6 +952,7 @@ drm_gem_object_release(struct drm_gem_object *obj) dma_resv_fini(&obj->_resv); drm_gem_free_mmap_offset(obj); + drm_gem_lru_remove(obj); } EXPORT_SYMBOL(drm_gem_object_release); @@ -1274,3 +1276,171 @@ drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, ww_acquire_fini(acquire_ctx); } EXPORT_SYMBOL(drm_gem_unlock_reservations); + +/** + * drm_gem_lru_init - initialize a LRU + * + * @lru: The LRU to initialize + * @lock: The lock protecting the LRU + */ +void +drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex *lock) +{ + lru->lock = lock; + lru->count = 0; + INIT_LIST_HEAD(&lru->list); +} +EXPORT_SYMBOL(drm_gem_lru_init); + +static void +drm_gem_lru_remove_locked(struct drm_gem_object *obj) +{ + obj->lru->count -= obj->size >> PAGE_SHIFT; + WARN_ON(obj->lru->count < 0); + list_del(&obj->lru_node); + obj->lru = NULL; +} + +/** + * drm_gem_lru_remove - remove object from whatever LRU it is in + * + * If the object is currently in any LRU, remove it. + * + * @obj: The GEM object to remove from current LRU + */ +void +drm_gem_lru_remove(struct drm_gem_object *obj) +{ + struct drm_gem_lru *lru = obj->lru; + + if (!lru) + return; + + mutex_lock(lru->lock); + drm_gem_lru_remove_locked(obj); + mutex_unlock(lru->lock); +} +EXPORT_SYMBOL(drm_gem_lru_remove); + +static void +drm_gem_lru_move_tail_locked(struct drm_gem_lru *lru, struct drm_gem_object *obj) +{ + lockdep_assert_held_once(lru->lock); + + if (obj->lru) + drm_gem_lru_remove_locked(obj); + + lru->count += obj->size >> PAGE_SHIFT; + list_add_tail(&obj->lru_node, &lru->list); + obj->lru = lru; +} + +/** + * drm_gem_lru_move_tail - move the object to the tail of the LRU + * + * If the object is already in this LRU it will be moved to the + * tail. Otherwise it will be removed from whichever other LRU + * it is in (if any) and moved into this LRU. + * + * @lru: The LRU to move the object into. + * @obj: The GEM object to move into this LRU + */ +void +drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj) +{ + mutex_lock(lru->lock); + drm_gem_lru_move_tail_locked(lru, obj); + mutex_unlock(lru->lock); +} +EXPORT_SYMBOL(drm_gem_lru_move_tail); + +/** + * drm_gem_lru_scan - helper to implement shrinker.scan_objects + * + * If the shrink callback succeeds, it is expected that the driver + * move the object out of this LRU. + * + * If the LRU possibly contain active buffers, it is the responsibility + * of the shrink callback to check for this (ie. dma_resv_test_signaled()) + * or if necessary block until the buffer becomes idle. + * + * @lru: The LRU to scan + * @nr_to_scan: The number of pages to try to reclaim + * @shrink: Callback to try to shrink/reclaim the object. + */ +unsigned long +drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, + bool (*shrink)(struct drm_gem_object *obj)) +{ + struct drm_gem_lru still_in_lru; + struct drm_gem_object *obj; + unsigned freed = 0; + + drm_gem_lru_init(&still_in_lru, lru->lock); + + mutex_lock(lru->lock); + + while (freed < nr_to_scan) { + obj = list_first_entry_or_null(&lru->list, typeof(*obj), lru_node); + + if (!obj) + break; + + drm_gem_lru_move_tail_locked(&still_in_lru, obj); + + /* + * If it's in the process of being freed, gem_object->free() + * may be blocked on lock waiting to remove it. So just + * skip it. + */ + if (!kref_get_unless_zero(&obj->refcount)) + continue; + + /* + * Now that we own a reference, we can drop the lock for the + * rest of the loop body, to reduce contention with other + * code paths that need the LRU lock + */ + mutex_unlock(lru->lock); + + /* + * Note that this still needs to be trylock, since we can + * hit shrinker in response to trying to get backing pages + * for this obj (ie. while it's lock is already held) + */ + if (!dma_resv_trylock(obj->resv)) + goto tail; + + if (shrink(obj)) { + freed += obj->size >> PAGE_SHIFT; + + /* + * If we succeeded in releasing the object's backing + * pages, we expect the driver to have moved the object + * out of this LRU + */ + WARN_ON(obj->lru == &still_in_lru); + WARN_ON(obj->lru == lru); + } + + dma_resv_unlock(obj->resv); + +tail: + drm_gem_object_put(obj); + mutex_lock(lru->lock); + } + + /* + * Move objects we've skipped over out of the temporary still_in_lru + * back into this LRU + */ + list_for_each_entry (obj, &still_in_lru.list, lru_node) + obj->lru = lru; + list_splice_tail(&still_in_lru.list, &lru->list); + lru->count += still_in_lru.count; + + mutex_unlock(lru->lock); + + return freed; +} +EXPORT_SYMBOL(drm_gem_lru_scan); diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 87cffc9efa85..f28a48a6f846 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -174,6 +174,41 @@ struct drm_gem_object_funcs { const struct vm_operations_struct *vm_ops; }; +/** + * struct drm_gem_lru - A simple LRU helper + * + * A helper for tracking GEM objects in a given state, to aid in + * driver's shrinker implementation. Tracks the count of pages + * for lockless &shrinker.count_objects, and provides + * &drm_gem_lru_scan for driver's &shrinker.scan_objects + * implementation. + */ +struct drm_gem_lru { + /** + * @lock: + * + * Lock protecting movement of GEM objects between LRUs. All + * LRUs that the object can move between should be protected + * by the same lock. + */ + struct mutex *lock; + + /** + * @count: + * + * The total number of backing pages of the GEM objects in + * this LRU. + */ + long count; + + /** + * @list: + * + * The LRU list. + */ + struct list_head list; +}; + /** * struct drm_gem_object - GEM buffer object * @@ -312,6 +347,20 @@ struct drm_gem_object { * */ const struct drm_gem_object_funcs *funcs; + + /** + * @lru_node: + * + * List node in a &drm_gem_lru. + */ + struct list_head lru_node; + + /** + * @lru: + * + * The current LRU list that the GEM object is on. + */ + struct drm_gem_lru *lru; }; /** @@ -420,4 +469,10 @@ void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, u32 handle, u64 *offset); +void drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex *lock); +void drm_gem_lru_remove(struct drm_gem_object *obj); +void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); +unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, + bool (*shrink)(struct drm_gem_object *obj)); + #endif /* __DRM_GEM_H__ */ From b352ba54a82072614f44c5ea352b5ea6e7f7b4c0 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:43 -0700 Subject: [PATCH 10/84] drm/msm/gem: Convert to using drm_gem_lru This converts over to use the shared GEM LRU/shrinker helpers. Note that it means we are no longer tracking purgeable or willneed buffers that are active separately. But the most recently pinned buffers should be at the tail of the various LRUs, and the shrinker is already prepared to encounter objects which are still active. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496131/ Link: https://lore.kernel.org/r/20220802155152.1727594-11-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_drv.c | 14 +-- drivers/gpu/drm/msm/msm_drv.h | 70 +++++++++++---- drivers/gpu/drm/msm/msm_gem.c | 56 +++--------- drivers/gpu/drm/msm/msm_gem.h | 93 -------------------- drivers/gpu/drm/msm/msm_gem_shrinker.c | 117 ++++++------------------- drivers/gpu/drm/msm/msm_gpu.c | 3 - drivers/gpu/drm/msm/msm_gpu.h | 6 -- 7 files changed, 103 insertions(+), 256 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index d7ca025457b6..1ca4a92ba96e 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -418,14 +418,18 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); - INIT_LIST_HEAD(&priv->inactive_willneed); - INIT_LIST_HEAD(&priv->inactive_dontneed); - INIT_LIST_HEAD(&priv->inactive_unpinned); - mutex_init(&priv->mm_lock); + /* + * Initialize the LRUs: + */ + mutex_init(&priv->lru.lock); + drm_gem_lru_init(&priv->lru.unbacked, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.pinned, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.willneed, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.dontneed, &priv->lru.lock); /* Teach lockdep about lock ordering wrt. shrinker: */ fs_reclaim_acquire(GFP_KERNEL); - might_lock(&priv->mm_lock); + might_lock(&priv->lru.lock); fs_reclaim_release(GFP_KERNEL); drm_mode_config_init(ddev); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b3689a2d27d7..208ae5bc5e6b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -142,28 +142,60 @@ struct msm_drm_private { struct mutex obj_lock; /** - * LRUs of inactive GEM objects. Every bo is either in one of the - * inactive lists (depending on whether or not it is shrinkable) or - * gpu->active_list (for the gpu it is active on[1]), or transiently - * on a temporary list as the shrinker is running. + * lru: * - * Note that inactive_willneed also contains pinned and vmap'd bos, - * but the number of pinned-but-not-active objects is small (scanout - * buffers, ringbuffer, etc). + * The various LRU's that a GEM object is in at various stages of + * it's lifetime. Objects start out in the unbacked LRU. When + * pinned (for scannout or permanently mapped GPU buffers, like + * ringbuffer, memptr, fw, etc) it moves to the pinned LRU. When + * unpinned, it moves into willneed or dontneed LRU depending on + * madvise state. When backing pages are evicted (willneed) or + * purged (dontneed) it moves back into the unbacked LRU. * - * These lists are protected by mm_lock (which should be acquired - * before per GEM object lock). One should *not* hold mm_lock in - * get_pages()/vmap()/etc paths, as they can trigger the shrinker. - * - * [1] if someone ever added support for the old 2d cores, there could be - * more than one gpu object + * The dontneed LRU is considered by the shrinker for objects + * that are candidate for purging, and the willneed LRU is + * considered for objects that could be evicted. */ - struct list_head inactive_willneed; /* inactive + potentially unpin/evictable */ - struct list_head inactive_dontneed; /* inactive + shrinkable */ - struct list_head inactive_unpinned; /* inactive + purged or unpinned */ - long shrinkable_count; /* write access under mm_lock */ - long evictable_count; /* write access under mm_lock */ - struct mutex mm_lock; + struct { + /** + * unbacked: + * + * The LRU for GEM objects without backing pages allocated. + * This mostly exists so that objects are always is one + * LRU. + */ + struct drm_gem_lru unbacked; + + /** + * pinned: + * + * The LRU for pinned GEM objects + */ + struct drm_gem_lru pinned; + + /** + * willneed: + * + * The LRU for unpinned GEM objects which are in madvise + * WILLNEED state (ie. can be evicted) + */ + struct drm_gem_lru willneed; + + /** + * dontneed: + * + * The LRU for unpinned GEM objects which are in madvise + * DONTNEED state (ie. can be purged) + */ + struct drm_gem_lru dontneed; + + /** + * lock: + * + * Protects manipulation of all of the LRUs. + */ + struct mutex lock; + } lru; struct workqueue_struct *wq; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 209438744bab..d4e8af46f4ef 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -174,6 +174,7 @@ static void put_pages(struct drm_gem_object *obj) put_pages_vram(obj); msm_obj->pages = NULL; + update_lru(obj); } } @@ -210,8 +211,6 @@ struct page **msm_gem_pin_pages(struct drm_gem_object *obj) void msm_gem_unpin_pages(struct drm_gem_object *obj) { - struct msm_gem_object *msm_obj = to_msm_bo(obj); - msm_gem_lock(obj); msm_gem_unpin_locked(obj); msm_gem_unlock(obj); @@ -761,7 +760,6 @@ void msm_gem_purge(struct drm_gem_object *obj) put_iova_vmas(obj); msm_obj->madv = __MSM_MADV_PURGED; - update_lru(obj); drm_gem_free_mmap_offset(obj); @@ -786,7 +784,6 @@ void msm_gem_evict(struct drm_gem_object *obj) GEM_WARN_ON(!msm_gem_is_locked(obj)); GEM_WARN_ON(is_unevictable(msm_obj)); - GEM_WARN_ON(!msm_obj->evictable); /* Get rid of any iommu mapping(s): */ put_iova_spaces(obj, false); @@ -794,8 +791,6 @@ void msm_gem_evict(struct drm_gem_object *obj) drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping); put_pages(obj); - - update_lru(obj); } void msm_gem_vunmap(struct drm_gem_object *obj) @@ -818,26 +813,20 @@ static void update_lru(struct drm_gem_object *obj) GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); - mutex_lock(&priv->mm_lock); + if (!msm_obj->pages) { + GEM_WARN_ON(msm_obj->pin_count); + GEM_WARN_ON(msm_obj->vmap_count); - if (msm_obj->dontneed) - mark_unpurgeable(msm_obj); - if (msm_obj->evictable) - mark_unevictable(msm_obj); - - list_del(&msm_obj->mm_list); - if ((msm_obj->madv == MSM_MADV_WILLNEED) && msm_obj->sgt) { - list_add_tail(&msm_obj->mm_list, &priv->inactive_willneed); - mark_evictable(msm_obj); - } else if (msm_obj->madv == MSM_MADV_DONTNEED) { - list_add_tail(&msm_obj->mm_list, &priv->inactive_dontneed); - mark_purgeable(msm_obj); + drm_gem_lru_move_tail(&priv->lru.unbacked, obj); + } else if (msm_obj->pin_count || msm_obj->vmap_count) { + drm_gem_lru_move_tail(&priv->lru.pinned, obj); + } else if (msm_obj->madv == MSM_MADV_WILLNEED) { + drm_gem_lru_move_tail(&priv->lru.willneed, obj); } else { - GEM_WARN_ON((msm_obj->madv != __MSM_MADV_PURGED) && msm_obj->sgt); - list_add_tail(&msm_obj->mm_list, &priv->inactive_unpinned); - } + GEM_WARN_ON(msm_obj->madv != MSM_MADV_DONTNEED); - mutex_unlock(&priv->mm_lock); + drm_gem_lru_move_tail(&priv->lru.dontneed, obj); + } } bool msm_gem_active(struct drm_gem_object *obj) @@ -995,12 +984,6 @@ static void msm_gem_free_object(struct drm_gem_object *obj) list_del(&msm_obj->node); mutex_unlock(&priv->obj_lock); - mutex_lock(&priv->mm_lock); - if (msm_obj->dontneed) - mark_unpurgeable(msm_obj); - list_del(&msm_obj->mm_list); - mutex_unlock(&priv->mm_lock); - put_iova_spaces(obj, true); if (obj->import_attach) { @@ -1160,13 +1143,6 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32 to_msm_bo(obj)->vram_node = &vma->node; - /* Call chain get_pages() -> update_inactive() tries to - * access msm_obj->mm_list, but it is not initialized yet. - * To avoid NULL pointer dereference error, initialize - * mm_list to be empty. - */ - INIT_LIST_HEAD(&msm_obj->mm_list); - msm_gem_lock(obj); pages = get_pages(obj); msm_gem_unlock(obj); @@ -1189,9 +1165,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32 mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER); } - mutex_lock(&priv->mm_lock); - list_add_tail(&msm_obj->mm_list, &priv->inactive_unpinned); - mutex_unlock(&priv->mm_lock); + drm_gem_lru_move_tail(&priv->lru.unbacked, obj); mutex_lock(&priv->obj_lock); list_add_tail(&msm_obj->node, &priv->objects); @@ -1247,9 +1221,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, msm_gem_unlock(obj); - mutex_lock(&priv->mm_lock); - list_add_tail(&msm_obj->mm_list, &priv->inactive_unpinned); - mutex_unlock(&priv->mm_lock); + drm_gem_lru_move_tail(&priv->lru.pinned, obj); mutex_lock(&priv->obj_lock); list_add_tail(&msm_obj->node, &priv->objects); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 420ba49bf21a..0403b27ff779 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -93,16 +93,6 @@ struct msm_gem_object { */ uint8_t madv; - /** - * Is object on inactive_dontneed list (ie. counted in priv->shrinkable_count)? - */ - bool dontneed : 1; - - /** - * Is object evictable (ie. counted in priv->evictable_count)? - */ - bool evictable : 1; - /** * count of active vmap'ing */ @@ -114,17 +104,6 @@ struct msm_gem_object { */ struct list_head node; - /** - * An object is either: - * inactive - on priv->inactive_dontneed or priv->inactive_willneed - * (depending on purgeability status) - * active - on one one of the gpu's active_list.. well, at - * least for now we don't have (I don't think) hw sync between - * 2d and 3d one devices which have both, meaning we need to - * block on submit if a bo is already on other ring - */ - struct list_head mm_list; - struct page **pages; struct sg_table *sgt; void *vaddr; @@ -206,12 +185,6 @@ msm_gem_lock(struct drm_gem_object *obj) dma_resv_lock(obj->resv, NULL); } -static inline bool __must_check -msm_gem_trylock(struct drm_gem_object *obj) -{ - return dma_resv_trylock(obj->resv); -} - static inline int msm_gem_lock_interruptible(struct drm_gem_object *obj) { @@ -260,77 +233,11 @@ static inline bool is_vunmapable(struct msm_gem_object *msm_obj) return (msm_obj->vmap_count == 0) && msm_obj->vaddr; } -static inline void mark_purgeable(struct msm_gem_object *msm_obj) -{ - struct msm_drm_private *priv = msm_obj->base.dev->dev_private; - - GEM_WARN_ON(!mutex_is_locked(&priv->mm_lock)); - - if (is_unpurgeable(msm_obj)) - return; - - if (GEM_WARN_ON(msm_obj->dontneed)) - return; - - priv->shrinkable_count += msm_obj->base.size >> PAGE_SHIFT; - msm_obj->dontneed = true; -} - -static inline void mark_unpurgeable(struct msm_gem_object *msm_obj) -{ - struct msm_drm_private *priv = msm_obj->base.dev->dev_private; - - GEM_WARN_ON(!mutex_is_locked(&priv->mm_lock)); - - if (is_unpurgeable(msm_obj)) - return; - - if (GEM_WARN_ON(!msm_obj->dontneed)) - return; - - priv->shrinkable_count -= msm_obj->base.size >> PAGE_SHIFT; - GEM_WARN_ON(priv->shrinkable_count < 0); - msm_obj->dontneed = false; -} - static inline bool is_unevictable(struct msm_gem_object *msm_obj) { return is_unpurgeable(msm_obj) || msm_obj->vaddr; } -static inline void mark_evictable(struct msm_gem_object *msm_obj) -{ - struct msm_drm_private *priv = msm_obj->base.dev->dev_private; - - WARN_ON(!mutex_is_locked(&priv->mm_lock)); - - if (is_unevictable(msm_obj)) - return; - - if (WARN_ON(msm_obj->evictable)) - return; - - priv->evictable_count += msm_obj->base.size >> PAGE_SHIFT; - msm_obj->evictable = true; -} - -static inline void mark_unevictable(struct msm_gem_object *msm_obj) -{ - struct msm_drm_private *priv = msm_obj->base.dev->dev_private; - - WARN_ON(!mutex_is_locked(&priv->mm_lock)); - - if (is_unevictable(msm_obj)) - return; - - if (WARN_ON(!msm_obj->evictable)) - return; - - priv->evictable_count -= msm_obj->base.size >> PAGE_SHIFT; - WARN_ON(priv->evictable_count < 0); - msm_obj->evictable = false; -} - void msm_gem_purge(struct drm_gem_object *obj); void msm_gem_evict(struct drm_gem_object *obj); void msm_gem_vunmap(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 0ab058734777..f1e52410f521 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -29,121 +29,61 @@ msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { struct msm_drm_private *priv = container_of(shrinker, struct msm_drm_private, shrinker); - unsigned count = priv->shrinkable_count; + unsigned count = priv->lru.dontneed.count; if (can_swap()) - count += priv->evictable_count; + count += priv->lru.willneed.count; return count; } static bool -purge(struct msm_gem_object *msm_obj) +purge(struct drm_gem_object *obj) { - if (!is_purgeable(msm_obj)) + if (!is_purgeable(to_msm_bo(obj))) return false; - if (msm_gem_active(&msm_obj->base)) + if (msm_gem_active(obj)) return false; - /* - * This will move the obj out of still_in_list to - * the purged list - */ - msm_gem_purge(&msm_obj->base); + msm_gem_purge(obj); return true; } static bool -evict(struct msm_gem_object *msm_obj) +evict(struct drm_gem_object *obj) { - if (is_unevictable(msm_obj)) + if (is_unevictable(to_msm_bo(obj))) return false; - if (msm_gem_active(&msm_obj->base)) + if (msm_gem_active(obj)) return false; - msm_gem_evict(&msm_obj->base); + msm_gem_evict(obj); return true; } -static unsigned long -scan(struct msm_drm_private *priv, unsigned nr_to_scan, struct list_head *list, - bool (*shrink)(struct msm_gem_object *msm_obj)) -{ - unsigned freed = 0; - struct list_head still_in_list; - - INIT_LIST_HEAD(&still_in_list); - - mutex_lock(&priv->mm_lock); - - while (freed < nr_to_scan) { - struct msm_gem_object *msm_obj = list_first_entry_or_null( - list, typeof(*msm_obj), mm_list); - - if (!msm_obj) - break; - - list_move_tail(&msm_obj->mm_list, &still_in_list); - - /* - * If it is in the process of being freed, msm_gem_free_object - * can be blocked on mm_lock waiting to remove it. So just - * skip it. - */ - if (!kref_get_unless_zero(&msm_obj->base.refcount)) - continue; - - /* - * Now that we own a reference, we can drop mm_lock for the - * rest of the loop body, to reduce contention with the - * retire_submit path (which could make more objects purgeable) - */ - - mutex_unlock(&priv->mm_lock); - - /* - * Note that this still needs to be trylock, since we can - * hit shrinker in response to trying to get backing pages - * for this obj (ie. while it's lock is already held) - */ - if (!msm_gem_trylock(&msm_obj->base)) - goto tail; - - if (shrink(msm_obj)) - freed += msm_obj->base.size >> PAGE_SHIFT; - - msm_gem_unlock(&msm_obj->base); - -tail: - drm_gem_object_put(&msm_obj->base); - mutex_lock(&priv->mm_lock); - } - - list_splice_tail(&still_in_list, list); - mutex_unlock(&priv->mm_lock); - - return freed; -} - static unsigned long msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) { struct msm_drm_private *priv = container_of(shrinker, struct msm_drm_private, shrinker); + long nr = sc->nr_to_scan; unsigned long freed; - freed = scan(priv, sc->nr_to_scan, &priv->inactive_dontneed, purge); + freed = drm_gem_lru_scan(&priv->lru.dontneed, nr, purge); + nr -= freed; if (freed > 0) trace_msm_gem_purge(freed << PAGE_SHIFT); - if (can_swap() && freed < sc->nr_to_scan) { - int evicted = scan(priv, sc->nr_to_scan - freed, - &priv->inactive_willneed, evict); + if (can_swap() && nr > 0) { + unsigned long evicted; + + evicted = drm_gem_lru_scan(&priv->lru.willneed, nr, evict); + nr -= evicted; if (evicted > 0) trace_msm_gem_evict(evicted << PAGE_SHIFT); @@ -179,12 +119,12 @@ msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan) static const int vmap_shrink_limit = 15; static bool -vmap_shrink(struct msm_gem_object *msm_obj) +vmap_shrink(struct drm_gem_object *obj) { - if (!is_vunmapable(msm_obj)) + if (!is_vunmapable(to_msm_bo(obj))) return false; - msm_gem_vunmap(&msm_obj->base); + msm_gem_vunmap(obj); return true; } @@ -194,17 +134,18 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) { struct msm_drm_private *priv = container_of(nb, struct msm_drm_private, vmap_notifier); - struct list_head *mm_lists[] = { - &priv->inactive_dontneed, - &priv->inactive_willneed, - priv->gpu ? &priv->gpu->active_list : NULL, + struct drm_gem_lru *lrus[] = { + &priv->lru.dontneed, + &priv->lru.willneed, + &priv->lru.pinned, NULL, }; unsigned idx, unmapped = 0; - for (idx = 0; mm_lists[idx] && unmapped < vmap_shrink_limit; idx++) { - unmapped += scan(priv, vmap_shrink_limit - unmapped, - mm_lists[idx], vmap_shrink); + for (idx = 0; lrus[idx] && unmapped < vmap_shrink_limit; idx++) { + unmapped += drm_gem_lru_scan(lrus[idx], + vmap_shrink_limit - unmapped, + vmap_shrink); } *(unsigned long *)ptr += unmapped; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index c2bfcf3f1f40..fba85f894314 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -846,7 +846,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, sched_set_fifo_low(gpu->worker->task); - INIT_LIST_HEAD(&gpu->active_list); mutex_init(&gpu->active_lock); mutex_init(&gpu->lock); init_waitqueue_head(&gpu->retire_event); @@ -974,8 +973,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) DBG("%s", gpu->name); - WARN_ON(!list_empty(&gpu->active_list)); - for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { msm_ringbuffer_destroy(gpu->rb[i]); gpu->rb[i] = NULL; diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 962d2070bcdf..a0885ff99e5b 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -187,12 +187,6 @@ struct msm_gpu { */ int cur_ctx_seqno; - /* - * List of GEM active objects on this gpu. Protected by - * msm_drm_private::mm_lock - */ - struct list_head active_list; - /** * lock: * From f371bcc0c2ac57a237849487c9aacbae394e69d1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:44 -0700 Subject: [PATCH 11/84] drm/msm/gem: Unpin buffers earlier We've already attached the fences, so obj->resv (which shrinker checks) tells us whether they are still active. So we can unpin sooner, before we drop the queue lock. This also avoids the need to grab the obj lock in the retire path, avoiding potential for lock contention between submit and retire. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496132/ Link: https://lore.kernel.org/r/20220802155152.1727594-12-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_submit.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index adf358fb8e9d..5599d93ec0d2 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -501,11 +501,11 @@ out: */ static void submit_cleanup(struct msm_gem_submit *submit, bool error) { - unsigned cleanup_flags = BO_LOCKED; + unsigned cleanup_flags = BO_LOCKED | BO_OBJ_PINNED; unsigned i; if (error) - cleanup_flags |= BO_VMA_PINNED | BO_OBJ_PINNED; + cleanup_flags |= BO_VMA_PINNED; for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -522,10 +522,6 @@ void msm_submit_retire(struct msm_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct drm_gem_object *obj = &submit->bos[i].obj->base; - msm_gem_lock(obj); - /* Note, VMA already fence-unpinned before submit: */ - submit_cleanup_bo(submit, i, BO_OBJ_PINNED); - msm_gem_unlock(obj); drm_gem_object_put(obj); } } From dd2f0d7859927e536b7316b36a9782053d3ad22c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:45 -0700 Subject: [PATCH 12/84] drm/msm/gem: Consolidate shrinker trace Combine separate trace events for purge vs evict into one. When we add support for purging/evicting active buffers we'll just add more info into this one trace event, rather than adding a bunch more events. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496133/ Link: https://lore.kernel.org/r/20220802155152.1727594-13-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_shrinker.c | 21 +++++++---------- drivers/gpu/drm/msm/msm_gpu_trace.h | 32 +++++++++++--------------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index f1e52410f521..12562370dcf5 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -71,26 +71,21 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) struct msm_drm_private *priv = container_of(shrinker, struct msm_drm_private, shrinker); long nr = sc->nr_to_scan; - unsigned long freed; + unsigned long freed, purged, evicted = 0; - freed = drm_gem_lru_scan(&priv->lru.dontneed, nr, purge); - nr -= freed; - - if (freed > 0) - trace_msm_gem_purge(freed << PAGE_SHIFT); + purged = drm_gem_lru_scan(&priv->lru.dontneed, nr, purge); + nr -= purged; if (can_swap() && nr > 0) { - unsigned long evicted; - evicted = drm_gem_lru_scan(&priv->lru.willneed, nr, evict); nr -= evicted; - - if (evicted > 0) - trace_msm_gem_evict(evicted << PAGE_SHIFT); - - freed += evicted; } + freed = purged + evicted; + + if (freed) + trace_msm_gem_shrink(sc->nr_to_scan, purged, evicted); + return (freed > 0) ? freed : SHRINK_STOP; } diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index ca0b08d7875b..8867fa0a0306 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -115,29 +115,23 @@ TRACE_EVENT(msm_gmu_freq_change, ); -TRACE_EVENT(msm_gem_purge, - TP_PROTO(u32 bytes), - TP_ARGS(bytes), +TRACE_EVENT(msm_gem_shrink, + TP_PROTO(u32 nr_to_scan, u32 purged, u32 evicted), + TP_ARGS(nr_to_scan, purged, evicted), TP_STRUCT__entry( - __field(u32, bytes) + __field(u32, nr_to_scan) + __field(u32, purged) + __field(u32, evicted) ), TP_fast_assign( - __entry->bytes = bytes; + __entry->nr_to_scan = nr_to_scan; + __entry->purged = purged; + __entry->evicted = evicted; ), - TP_printk("Purging %u bytes", __entry->bytes) -); - - -TRACE_EVENT(msm_gem_evict, - TP_PROTO(u32 bytes), - TP_ARGS(bytes), - TP_STRUCT__entry( - __field(u32, bytes) - ), - TP_fast_assign( - __entry->bytes = bytes; - ), - TP_printk("Evicting %u bytes", __entry->bytes) + TP_printk("nr_to_scan=%u pages, purged=%u pages, evicted=%u pages", + __entry->nr_to_scan, + __entry->purged, + __entry->evicted) ); From 025d27239a2f93b3eb415d4893266195a67d3fe5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:46 -0700 Subject: [PATCH 13/84] drm/msm/gem: Evict active GEM objects when necessary If we are under enough memory pressure, we should stall waiting for active buffers to become idle in order to evict. v2: Check for __GFP_ATOMIC before blocking Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496135/ Link: https://lore.kernel.org/r/20220802155152.1727594-14-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem_shrinker.c | 68 +++++++++++++++++++++----- drivers/gpu/drm/msm/msm_gpu_trace.h | 16 +++--- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 12562370dcf5..58e0513be5f4 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -24,6 +24,13 @@ static bool can_swap(void) return enable_eviction && get_nr_swap_pages() > 0; } +static bool can_block(struct shrink_control *sc) +{ + if (sc->gfp_mask & __GFP_ATOMIC) + return false; + return current_is_kswapd() || (sc->gfp_mask & __GFP_RECLAIM); +} + static unsigned long msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { @@ -65,26 +72,65 @@ evict(struct drm_gem_object *obj) return true; } +static bool +wait_for_idle(struct drm_gem_object *obj) +{ + enum dma_resv_usage usage = dma_resv_usage_rw(true); + return dma_resv_wait_timeout(obj->resv, usage, false, 1000) > 0; +} + +static bool +active_purge(struct drm_gem_object *obj) +{ + if (!wait_for_idle(obj)) + return false; + + return purge(obj); +} + +static bool +active_evict(struct drm_gem_object *obj) +{ + if (!wait_for_idle(obj)) + return false; + + return evict(obj); +} + static unsigned long msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) { struct msm_drm_private *priv = container_of(shrinker, struct msm_drm_private, shrinker); + struct { + struct drm_gem_lru *lru; + bool (*shrink)(struct drm_gem_object *obj); + bool cond; + unsigned long freed; + } stages[] = { + /* Stages of progressively more aggressive/expensive reclaim: */ + { &priv->lru.dontneed, purge, true }, + { &priv->lru.willneed, evict, can_swap() }, + { &priv->lru.dontneed, active_purge, can_block(sc) }, + { &priv->lru.willneed, active_evict, can_swap() && can_block(sc) }, + }; long nr = sc->nr_to_scan; - unsigned long freed, purged, evicted = 0; + unsigned long freed = 0; - purged = drm_gem_lru_scan(&priv->lru.dontneed, nr, purge); - nr -= purged; - - if (can_swap() && nr > 0) { - evicted = drm_gem_lru_scan(&priv->lru.willneed, nr, evict); - nr -= evicted; + for (unsigned i = 0; (nr > 0) && (i < ARRAY_SIZE(stages)); i++) { + if (!stages[i].cond) + continue; + stages[i].freed = + drm_gem_lru_scan(stages[i].lru, nr, stages[i].shrink); + nr -= stages[i].freed; + freed += stages[i].freed; } - freed = purged + evicted; - - if (freed) - trace_msm_gem_shrink(sc->nr_to_scan, purged, evicted); + if (freed) { + trace_msm_gem_shrink(sc->nr_to_scan, stages[0].freed, + stages[1].freed, stages[2].freed, + stages[3].freed); + } return (freed > 0) ? freed : SHRINK_STOP; } diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index 8867fa0a0306..ac40d857bc45 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -116,22 +116,26 @@ TRACE_EVENT(msm_gmu_freq_change, TRACE_EVENT(msm_gem_shrink, - TP_PROTO(u32 nr_to_scan, u32 purged, u32 evicted), - TP_ARGS(nr_to_scan, purged, evicted), + TP_PROTO(u32 nr_to_scan, u32 purged, u32 evicted, + u32 active_purged, u32 active_evicted), + TP_ARGS(nr_to_scan, purged, evicted, active_purged, active_evicted), TP_STRUCT__entry( __field(u32, nr_to_scan) __field(u32, purged) __field(u32, evicted) + __field(u32, active_purged) + __field(u32, active_evicted) ), TP_fast_assign( __entry->nr_to_scan = nr_to_scan; __entry->purged = purged; __entry->evicted = evicted; + __entry->active_purged = active_purged; + __entry->active_evicted = active_evicted; ), - TP_printk("nr_to_scan=%u pages, purged=%u pages, evicted=%u pages", - __entry->nr_to_scan, - __entry->purged, - __entry->evicted) + TP_printk("nr_to_scan=%u pg, purged=%u pg, evicted=%u pg, active_purged=%u pg, active_evicted=%u pg", + __entry->nr_to_scan, __entry->purged, __entry->evicted, + __entry->active_purged, __entry->active_evicted) ); From d4d7d3630d703ff19923b82534bc18e345477c6f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:47 -0700 Subject: [PATCH 14/84] drm/msm/gem: Add msm_gem_assert_locked() All use of msm_gem_is_locked() is just for WARN_ON()s, so extract out into an msm_gem_assert_locked() patch. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496136/ Link: https://lore.kernel.org/r/20220802155152.1727594-15-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.c | 36 +++++++++++++++++------------------ drivers/gpu/drm/msm/msm_gem.h | 8 +++++++- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index d4e8af46f4ef..1dee0d18abbb 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -97,7 +97,7 @@ static struct page **get_pages(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (!msm_obj->pages) { struct drm_device *dev = obj->dev; @@ -183,7 +183,7 @@ static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct page **p; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) { return ERR_PTR(-EBUSY); @@ -278,7 +278,7 @@ static uint64_t mmap_offset(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; int ret; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); /* Make it mmapable */ ret = drm_gem_create_mmap_offset(obj); @@ -307,7 +307,7 @@ static struct msm_gem_vma *add_vma(struct drm_gem_object *obj, struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) @@ -326,7 +326,7 @@ static struct msm_gem_vma *lookup_vma(struct drm_gem_object *obj, struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); list_for_each_entry(vma, &msm_obj->vmas, list) { if (vma->aspace == aspace) @@ -357,7 +357,7 @@ put_iova_spaces(struct drm_gem_object *obj, bool close) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); list_for_each_entry(vma, &msm_obj->vmas, list) { if (vma->aspace) { @@ -375,7 +375,7 @@ put_iova_vmas(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma, *tmp; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); list_for_each_entry_safe(vma, tmp, &msm_obj->vmas, list) { del_vma(vma); @@ -388,7 +388,7 @@ static struct msm_gem_vma *get_vma_locked(struct drm_gem_object *obj, { struct msm_gem_vma *vma; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); vma = lookup_vma(obj, aspace); @@ -428,7 +428,7 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma) if (msm_obj->flags & MSM_BO_CACHED_COHERENT) prot |= IOMMU_CACHE; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) return -EBUSY; @@ -448,7 +448,7 @@ void msm_gem_unpin_locked(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); msm_obj->pin_count--; GEM_WARN_ON(msm_obj->pin_count < 0); @@ -469,7 +469,7 @@ static int get_and_pin_iova_range_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma; int ret; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); vma = get_vma_locked(obj, aspace, range_start, range_end); if (IS_ERR(vma)) @@ -630,7 +630,7 @@ static void *get_vaddr(struct drm_gem_object *obj, unsigned madv) struct msm_gem_object *msm_obj = to_msm_bo(obj); int ret = 0; - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (obj->import_attach) return ERR_PTR(-ENODEV); @@ -703,7 +703,7 @@ void msm_gem_put_vaddr_locked(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); GEM_WARN_ON(msm_obj->vmap_count < 1); msm_obj->vmap_count--; @@ -745,7 +745,7 @@ void msm_gem_purge(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); GEM_WARN_ON(!is_purgeable(msm_obj)); /* Get rid of any iommu mapping(s): */ @@ -782,7 +782,7 @@ void msm_gem_evict(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); GEM_WARN_ON(is_unevictable(msm_obj)); /* Get rid of any iommu mapping(s): */ @@ -797,7 +797,7 @@ void msm_gem_vunmap(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (!msm_obj->vaddr || GEM_WARN_ON(!is_vunmapable(msm_obj))) return; @@ -811,7 +811,7 @@ static void update_lru(struct drm_gem_object *obj) struct msm_drm_private *priv = obj->dev->dev_private; struct msm_gem_object *msm_obj = to_msm_bo(obj); - GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); + msm_gem_assert_locked(&msm_obj->base); if (!msm_obj->pages) { GEM_WARN_ON(msm_obj->pin_count); @@ -831,7 +831,7 @@ static void update_lru(struct drm_gem_object *obj) bool msm_gem_active(struct drm_gem_object *obj) { - GEM_WARN_ON(!msm_gem_is_locked(obj)); + msm_gem_assert_locked(obj); if (to_msm_bo(obj)->pin_count) return true; diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 0403b27ff779..3c6add51d13b 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -215,6 +215,12 @@ msm_gem_is_locked(struct drm_gem_object *obj) return dma_resv_is_locked(obj->resv) || (kref_read(&obj->refcount) == 0); } +static inline void +msm_gem_assert_locked(struct drm_gem_object *obj) +{ + GEM_WARN_ON(!msm_gem_is_locked(obj)); +} + /* imported/exported objects are not purgeable: */ static inline bool is_unpurgeable(struct msm_gem_object *msm_obj) { @@ -229,7 +235,7 @@ static inline bool is_purgeable(struct msm_gem_object *msm_obj) static inline bool is_vunmapable(struct msm_gem_object *msm_obj) { - GEM_WARN_ON(!msm_gem_is_locked(&msm_obj->base)); + msm_gem_assert_locked(&msm_obj->base); return (msm_obj->vmap_count == 0) && msm_obj->vaddr; } From d95c196ddb6ccd2445760b003e6e8a43cd5e84ba Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 Aug 2022 08:51:48 -0700 Subject: [PATCH 15/84] drm/msm/gem: Convert to lockdep assert Utilize the power of lockdep for our GEM locking related sanity checking. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496139/ Link: https://lore.kernel.org/r/20220802155152.1727594-16-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_gem.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 3c6add51d13b..c4844cf3a585 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -197,8 +197,8 @@ msm_gem_unlock(struct drm_gem_object *obj) dma_resv_unlock(obj->resv); } -static inline bool -msm_gem_is_locked(struct drm_gem_object *obj) +static inline void +msm_gem_assert_locked(struct drm_gem_object *obj) { /* * Destroying the object is a special case.. msm_gem_free_object() @@ -212,13 +212,10 @@ msm_gem_is_locked(struct drm_gem_object *obj) * Unfortunately lockdep is not aware of this detail. So when the * refcount drops to zero, we pretend it is already locked. */ - return dma_resv_is_locked(obj->resv) || (kref_read(&obj->refcount) == 0); -} - -static inline void -msm_gem_assert_locked(struct drm_gem_object *obj) -{ - GEM_WARN_ON(!msm_gem_is_locked(obj)); + lockdep_assert_once( + (kref_read(&obj->refcount) == 0) || + (lockdep_is_held(&obj->resv->lock.base) != LOCK_STATE_NOT_HELD) + ); } /* imported/exported objects are not purgeable: */ From 6d29709de8028cfd5a827d02f93a5076ba632563 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 7 Aug 2022 10:28:48 -0700 Subject: [PATCH 16/84] drm/msm: Add fault-injection support Intended as a way to trigger error paths in mesa. Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/496710/ Link: https://lore.kernel.org/r/20220807172848.2432845-1-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_debugfs.c | 8 ++++++++ drivers/gpu/drm/msm/msm_drv.c | 15 +++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 7 +++++++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 7d2dab260f86..95f4374ae21c 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -7,6 +7,7 @@ #ifdef CONFIG_DEBUG_FS #include +#include #include #include @@ -326,6 +327,13 @@ void msm_debugfs_init(struct drm_minor *minor) if (priv->kms && priv->kms->funcs->debugfs_init) priv->kms->funcs->debugfs_init(priv->kms, minor); + +#ifdef CONFIG_FAULT_INJECTION + fault_create_debugfs_attr("fail_gem_alloc", minor->debugfs_root, + &fail_gem_alloc); + fault_create_debugfs_attr("fail_gem_iova", minor->debugfs_root, + &fail_gem_iova); +#endif } #endif diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1ca4a92ba96e..b564ff685f67 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -78,6 +79,11 @@ static bool modeset = true; MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)"); module_param(modeset, bool, 0600); +#ifdef CONFIG_FAULT_INJECTION +DECLARE_FAULT_ATTR(fail_gem_alloc); +DECLARE_FAULT_ATTR(fail_gem_iova); +#endif + static irqreturn_t msm_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -701,6 +707,9 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data, flags |= MSM_BO_WC; } + if (should_fail(&fail_gem_alloc, args->size)) + return -ENOMEM; + return msm_gem_new_handle(dev, file, args->size, args->flags, &args->handle, NULL); } @@ -762,6 +771,9 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, if (!priv->gpu) return -EINVAL; + if (should_fail(&fail_gem_iova, obj->size)) + return -ENOMEM; + /* * Don't pin the memory here - just get an address so that userspace can * be productive @@ -783,6 +795,9 @@ static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, if (priv->gpu->aspace == ctx->aspace) return -EOPNOTSUPP; + if (should_fail(&fail_gem_iova, obj->size)) + return -ENOMEM; + return msm_gem_set_iova(obj, ctx->aspace, iova); } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 208ae5bc5e6b..09c4585a8064 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -34,6 +34,13 @@ #include #include +#ifdef CONFIG_FAULT_INJECTION +extern struct fault_attr fail_gem_alloc; +extern struct fault_attr fail_gem_iova; +#else +# define should_fail(attr, size) 0 +#endif + struct msm_kms; struct msm_gpu; struct msm_mmu; From 70bccecfcaf6c506191aed487f3cf2695fc3008c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 23 Aug 2022 09:37:19 -0700 Subject: [PATCH 17/84] drm/msm/iommu: optimize map/unmap Using map_pages/unmap_pages cuts down on the # of pgtable walks needed in the process of finding where to insert/remove an entry. The end result is ~5-10x faster than mapping a single page at a time. v2: Rename iommu_pgsize(), drop obsolete comments, fix error handling in msm_iommu_pagetable_map() Signed-off-by: Rob Clark Reviewed-by: Sai Prakash Ranjan Patchwork: https://patchwork.freedesktop.org/patch/498892/ Link: https://lore.kernel.org/r/20220823163719.90399-1-robdclark@gmail.com --- drivers/gpu/drm/msm/msm_iommu.c | 101 +++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index a54ed354578b..5577cea7c009 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -21,6 +21,7 @@ struct msm_iommu_pagetable { struct msm_mmu base; struct msm_mmu *parent; struct io_pgtable_ops *pgtbl_ops; + unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */ phys_addr_t ttbr; u32 asid; }; @@ -29,23 +30,84 @@ static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu) return container_of(mmu, struct msm_iommu_pagetable, base); } +/* based on iommu_pgsize() in iommu.c: */ +static size_t calc_pgsize(struct msm_iommu_pagetable *pagetable, + unsigned long iova, phys_addr_t paddr, + size_t size, size_t *count) +{ + unsigned int pgsize_idx, pgsize_idx_next; + unsigned long pgsizes; + size_t offset, pgsize, pgsize_next; + unsigned long addr_merge = paddr | iova; + + /* Page sizes supported by the hardware and small enough for @size */ + pgsizes = pagetable->pgsize_bitmap & GENMASK(__fls(size), 0); + + /* Constrain the page sizes further based on the maximum alignment */ + if (likely(addr_merge)) + pgsizes &= GENMASK(__ffs(addr_merge), 0); + + /* Make sure we have at least one suitable page size */ + BUG_ON(!pgsizes); + + /* Pick the biggest page size remaining */ + pgsize_idx = __fls(pgsizes); + pgsize = BIT(pgsize_idx); + if (!count) + return pgsize; + + /* Find the next biggest support page size, if it exists */ + pgsizes = pagetable->pgsize_bitmap & ~GENMASK(pgsize_idx, 0); + if (!pgsizes) + goto out_set_count; + + pgsize_idx_next = __ffs(pgsizes); + pgsize_next = BIT(pgsize_idx_next); + + /* + * There's no point trying a bigger page size unless the virtual + * and physical addresses are similarly offset within the larger page. + */ + if ((iova ^ paddr) & (pgsize_next - 1)) + goto out_set_count; + + /* Calculate the offset to the next page size alignment boundary */ + offset = pgsize_next - (addr_merge & (pgsize_next - 1)); + + /* + * If size is big enough to accommodate the larger page, reduce + * the number of smaller pages. + */ + if (offset + pgsize_next <= size) + size = offset; + +out_set_count: + *count = size >> pgsize_idx; + return pgsize; +} + static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, size_t size) { struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); struct io_pgtable_ops *ops = pagetable->pgtbl_ops; - size_t unmapped = 0; - /* Unmap the block one page at a time */ while (size) { - unmapped += ops->unmap(ops, iova, 4096, NULL); - iova += 4096; - size -= 4096; + size_t unmapped, pgsize, count; + + pgsize = calc_pgsize(pagetable, iova, iova, size, &count); + + unmapped = ops->unmap_pages(ops, iova, pgsize, count, NULL); + if (!unmapped) + break; + + iova += unmapped; + size -= unmapped; } iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->domain); - return (unmapped == size) ? 0 : -EINVAL; + return (size == 0) ? 0 : -EINVAL; } static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, @@ -54,7 +116,6 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); struct io_pgtable_ops *ops = pagetable->pgtbl_ops; struct scatterlist *sg; - size_t mapped = 0; u64 addr = iova; unsigned int i; @@ -62,17 +123,26 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, size_t size = sg->length; phys_addr_t phys = sg_phys(sg); - /* Map the block one page at a time */ while (size) { - if (ops->map(ops, addr, phys, 4096, prot, GFP_KERNEL)) { - msm_iommu_pagetable_unmap(mmu, iova, mapped); + size_t pgsize, count, mapped = 0; + int ret; + + pgsize = calc_pgsize(pagetable, addr, phys, size, &count); + + ret = ops->map_pages(ops, addr, phys, pgsize, count, + prot, GFP_KERNEL, &mapped); + + /* map_pages could fail after mapping some of the pages, + * so update the counters before error handling. + */ + phys += mapped; + addr += mapped; + size -= mapped; + + if (ret) { + msm_iommu_pagetable_unmap(mmu, iova, addr - iova); return -EINVAL; } - - phys += 4096; - addr += 4096; - size -= 4096; - mapped += 4096; } } @@ -207,6 +277,7 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) /* Needed later for TLB flush */ pagetable->parent = parent; + pagetable->pgsize_bitmap = ttbr0_cfg.pgsize_bitmap; pagetable->ttbr = ttbr0_cfg.arm_lpae_s1_cfg.ttbr; /* From 80059b87a3033543e3cb6f9abcd513e13a3f9f06 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 21 Aug 2022 08:54:35 -0700 Subject: [PATCH 18/84] drm/msm: De-open-code some CP_EVENT_WRITE Replace some open coding to improve readability. Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/499272/ Link: https://lore.kernel.org/r/20220821155441.1092134-1-robdclark@gmail.com --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 0ab0e1dd8bbb..2c8b9899625b 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -68,7 +68,7 @@ static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ OUT_PKT3(ring, CP_EVENT_WRITE, 3); - OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); + OUT_RING(ring, CACHE_FLUSH_TS | CP_EVENT_WRITE_0_IRQ); OUT_RING(ring, rbmemptr(ring, fence)); OUT_RING(ring, submit->seqno); diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 0c6b2a6d0b4c..7cb8d9849c07 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -62,7 +62,7 @@ static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ OUT_PKT3(ring, CP_EVENT_WRITE, 3); - OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); + OUT_RING(ring, CACHE_FLUSH_TS | CP_EVENT_WRITE_0_IRQ); OUT_RING(ring, rbmemptr(ring, fence)); OUT_RING(ring, submit->seqno); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 4d501100b9e4..c8ad8aeca777 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -146,7 +146,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, */ OUT_PKT7(ring, CP_EVENT_WRITE, 1); - OUT_RING(ring, 0x31); + OUT_RING(ring, CACHE_INVALIDATE); if (!sysprof) { /* From 125e03b2b2bec7e749a3d5695febcfebc076481c Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:09 +0530 Subject: [PATCH 19/84] drm/msm: Remove unnecessary pm_runtime_get/put We already enable gpu power from msm_gpu_submit(), so avoid a duplicate pm_runtime_get/put from msm_job_run(). Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498390/ Link: https://lore.kernel.org/r/20220819015030.v5.1.Icf1e8f0c9b3e7e9933c3b48c70477d0582f3243f@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_ringbuffer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 56eecb4a72dc..cad4c3525f0b 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -29,8 +29,6 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) msm_gem_unlock(obj); } - pm_runtime_get_sync(&gpu->pdev->dev); - /* TODO move submit path over to using a per-ring lock.. */ mutex_lock(&gpu->lock); @@ -38,8 +36,6 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) mutex_unlock(&gpu->lock); - pm_runtime_put(&gpu->pdev->dev); - return dma_fence_get(submit->hw_fence); } From 5b26f37d1365dc0992ecf019a5f1047f98934c34 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:10 +0530 Subject: [PATCH 20/84] drm/msm: Take single rpm refcount on behalf of all submits Instead of separate refcount for each submit, take single rpm refcount on behalf of all the submits. This makes it easier to drop the rpm refcount during recovery in an upcoming patch. Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498392/ Link: https://lore.kernel.org/r/20220819015030.v5.2.Ifee853f6d8217a0fdacc459092bbc9e81a8a7ac7@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index fba85f894314..0a9406182ea7 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -664,11 +664,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, mutex_lock(&gpu->active_lock); gpu->active_submits--; WARN_ON(gpu->active_submits < 0); - if (!gpu->active_submits) + if (!gpu->active_submits) { msm_devfreq_idle(gpu); - mutex_unlock(&gpu->active_lock); + pm_runtime_put_autosuspend(&gpu->pdev->dev); + } - pm_runtime_put_autosuspend(&gpu->pdev->dev); + mutex_unlock(&gpu->active_lock); msm_gem_submit_put(submit); } @@ -757,14 +758,17 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) /* Update devfreq on transition from idle->active: */ mutex_lock(&gpu->active_lock); - if (!gpu->active_submits) + if (!gpu->active_submits) { + pm_runtime_get(&gpu->pdev->dev); msm_devfreq_active(gpu); + } gpu->active_submits++; mutex_unlock(&gpu->active_lock); gpu->funcs->submit(gpu, submit); gpu->cur_ctx_seqno = submit->queue->ctx->seqno; + pm_runtime_put(&gpu->pdev->dev); hangcheck_timer_reset(gpu); } From 06097e372accb843db7174b337367c5a3f97af52 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:11 +0530 Subject: [PATCH 21/84] drm/msm: Correct pm_runtime votes in recover worker In the scenario where there is one a single submit which is hung, gpu is power collapsed when it is retired. Because of this, by the time we call reover(), gpu state would be already clear. Fix this by correctly managing the pm runtime votes. Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498391/ Link: https://lore.kernel.org/r/20220819015030.v5.3.Ib07ecec3d5c17cb0e1efa6fcddaaa019ec2fb556@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 0a9406182ea7..da6242cbf87d 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -394,7 +394,6 @@ static void recover_worker(struct kthread_work *work) /* Record the crash state */ pm_runtime_get_sync(&gpu->pdev->dev); msm_gpu_crashstate_capture(gpu, submit, comm, cmd); - pm_runtime_put_sync(&gpu->pdev->dev); kfree(cmd); kfree(comm); @@ -442,6 +441,8 @@ static void recover_worker(struct kthread_work *work) } } + pm_runtime_put_sync(&gpu->pdev->dev); + mutex_unlock(&gpu->lock); msm_gpu_retire(gpu); From f350bfb92b5a89f8056b0e218e05522665e8ac9a Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:12 +0530 Subject: [PATCH 22/84] drm/msm: Fix cx collapse issue during recovery There are some hardware logic under CX domain. For a successful recovery, we should ensure cx headswitch collapses to ensure all the stale states are cleard out. This is especially true to for a6xx family where we can GMU co-processor. Currently, cx doesn't collapse due to a devlink between gpu and its smmu. So the *struct gpu device* needs to be runtime suspended to ensure that the iommu driver removes its vote on cx gdsc. Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498398/ Link: https://lore.kernel.org/r/20220819015030.v5.4.I4ac27a0b34ea796ce0f938bb509e257516bc6f57@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 32 ++++++++++++++++++++++++--- drivers/gpu/drm/msm/msm_gpu.c | 4 +--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index c8ad8aeca777..aa2ec9861361 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1261,7 +1261,7 @@ static void a6xx_recover(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - int i; + int i, active_submits; adreno_dump_info(gpu); @@ -1278,8 +1278,34 @@ static void a6xx_recover(struct msm_gpu *gpu) */ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); - gpu->funcs->pm_suspend(gpu); - gpu->funcs->pm_resume(gpu); + pm_runtime_dont_use_autosuspend(&gpu->pdev->dev); + + /* active_submit won't change until we make a submission */ + mutex_lock(&gpu->active_lock); + active_submits = gpu->active_submits; + + /* + * Temporarily clear active_submits count to silence a WARN() in the + * runtime suspend cb + */ + gpu->active_submits = 0; + + /* Drop the rpm refcount from active submits */ + if (active_submits) + pm_runtime_put(&gpu->pdev->dev); + + /* And the final one from recover worker */ + pm_runtime_put_sync(&gpu->pdev->dev); + + pm_runtime_use_autosuspend(&gpu->pdev->dev); + + if (active_submits) + pm_runtime_get(&gpu->pdev->dev); + + pm_runtime_get_sync(&gpu->pdev->dev); + + gpu->active_submits = active_submits; + mutex_unlock(&gpu->active_lock); msm_gpu_hw_init(gpu); } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index da6242cbf87d..9ec9a99ffe77 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -422,9 +422,7 @@ static void recover_worker(struct kthread_work *work) /* retire completed submits, plus the one that hung: */ retire_submits(gpu); - pm_runtime_get_sync(&gpu->pdev->dev); gpu->funcs->recover(gpu); - pm_runtime_put_sync(&gpu->pdev->dev); /* * Replay all remaining submits starting with highest priority @@ -441,7 +439,7 @@ static void recover_worker(struct kthread_work *work) } } - pm_runtime_put_sync(&gpu->pdev->dev); + pm_runtime_put(&gpu->pdev->dev); mutex_unlock(&gpu->lock); From 1f6cca404918d2d3bc476afb31b371a406009c06 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:13 +0530 Subject: [PATCH 23/84] drm/msm/a6xx: Ensure CX collapse during gpu recovery Because there could be transient votes from other drivers/tz/hyp which may keep the cx gdsc enabled, we should poll until cx gdsc collapses. We can use the reset framework to poll for cx gdsc collapse from gpucc clk driver. This feature requires support from the platform's gpucc driver. Signed-off-by: Akhil P Oommen Reviewed-by: Dmitry Baryshkov Reviewed-by: Philipp Zabel Patchwork: https://patchwork.freedesktop.org/patch/498397/ Link: https://lore.kernel.org/r/20220819015030.v5.5.I176567525af2b9439a7e485d0ca130528666a55c@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++++ drivers/gpu/drm/msm/msm_gpu.c | 4 ++++ drivers/gpu/drm/msm/msm_gpu.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index aa2ec9861361..2ea5fb332df5 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -10,6 +10,7 @@ #include #include +#include #include #define GPU_PAS_ID 13 @@ -1297,6 +1298,9 @@ static void a6xx_recover(struct msm_gpu *gpu) /* And the final one from recover worker */ pm_runtime_put_sync(&gpu->pdev->dev); + /* Call into gpucc driver to poll for cx gdsc collapse */ + reset_control_reset(gpu->cx_collapse); + pm_runtime_use_autosuspend(&gpu->pdev->dev); if (active_submits) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 9ec9a99ffe77..0098ee8438aa 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -903,6 +904,9 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, if (IS_ERR(gpu->gpu_cx)) gpu->gpu_cx = NULL; + gpu->cx_collapse = devm_reset_control_get_optional_exclusive(&pdev->dev, + "cx_collapse"); + gpu->pdev = pdev; platform_set_drvdata(pdev, &gpu->adreno_smmu); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index a0885ff99e5b..ff911e7305ce 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "msm_drv.h" #include "msm_fence.h" @@ -271,6 +272,9 @@ struct msm_gpu { bool hw_apriv; struct thermal_cooling_device *cooling; + + /* To poll for cx gdsc collapse during gpu recovery */ + struct reset_control *cx_collapse; }; static inline struct msm_gpu *dev_to_gpu(struct device *dev) From 3a9dd708b902a1a646c3725151554cbef16c2c28 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:14 +0530 Subject: [PATCH 24/84] drm/msm/a6xx: Improve gpu recovery sequence We can do a few more things to improve our chance at a successful gpu recovery, especially during a hangcheck timeout: 1. Halt CP and GMU core 2. Do RBBM GBIF HALT sequence 3. Do a soft reset of GPU core Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498400/ Link: https://lore.kernel.org/r/20220819015030.v5.6.Idf2ba51078e87ae7ceb75cc77a5bd4ff2bd31eab@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx.xml.h | 4 ++ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 77 ++++++++++++++++----------- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++ 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h index b03e2c413ab1..beea4a7fc1df 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h @@ -1413,6 +1413,10 @@ static inline uint32_t REG_A6XX_RBBM_PERFCTR_RBBM_SEL(uint32_t i0) { return 0x00 #define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL 0x00000011 +#define REG_A6XX_RBBM_GBIF_HALT 0x00000016 + +#define REG_A6XX_RBBM_GBIF_HALT_ACK 0x00000017 + #define REG_A6XX_RBBM_WAIT_FOR_GPU_IDLE_CMD 0x0000001c #define A6XX_RBBM_WAIT_FOR_GPU_IDLE_CMD_WAIT_GPU_IDLE 0x00000001 diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 310a317885a1..ec25f19a2985 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -873,9 +873,47 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) (val & 1), 100, 1000); } +#define GBIF_CLIENT_HALT_MASK BIT(0) +#define GBIF_ARB_HALT_MASK BIT(1) + +static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu) +{ + struct msm_gpu *gpu = &adreno_gpu->base; + + if (!a6xx_has_gbif(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf); + spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & + 0xf) == 0xf); + gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); + + return; + } + + /* Halt the gx side of GBIF */ + gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1); + spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1); + + /* Halt new client requests on GBIF */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & + (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK); + + /* Halt all AXI requests on GBIF */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK); + spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & + (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK); + + /* The GBIF halt needs to be explicitly cleared */ + gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0); +} + /* Force the GMU off in case it isn't responsive */ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + /* Flush all the queues */ a6xx_hfi_stop(gmu); @@ -887,6 +925,15 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) /* Make sure there are no outstanding RPMh votes */ a6xx_gmu_rpmh_off(gmu); + + /* Halt the gmu cm3 core */ + gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); + + a6xx_bus_clear_pending_transactions(adreno_gpu); + + /* Reset GPU core blocks */ + gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1); + udelay(100); } static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu) @@ -1014,36 +1061,6 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu) return true; } -#define GBIF_CLIENT_HALT_MASK BIT(0) -#define GBIF_ARB_HALT_MASK BIT(1) - -static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu) -{ - struct msm_gpu *gpu = &adreno_gpu->base; - - if (!a6xx_has_gbif(adreno_gpu)) { - gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf); - spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & - 0xf) == 0xf); - gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); - - return; - } - - /* Halt new client requests on GBIF */ - gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK); - spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & - (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK); - - /* Halt all AXI requests on GBIF */ - gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK); - spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) & - (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK); - - /* The GBIF halt needs to be explicitly cleared */ - gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0); -} - /* Gracefully try to shut down the GMU and by extension the GPU */ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 2ea5fb332df5..fdc578016e0b 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -988,6 +988,10 @@ static int hw_init(struct msm_gpu *gpu) /* Make sure the GMU keeps the GPU on while we set it up */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + /* Clear GBIF halt in case GX domain was not collapsed */ + if (a6xx_has_gbif(adreno_gpu)) + gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 0); + gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0); /* @@ -1273,6 +1277,9 @@ static void a6xx_recover(struct msm_gpu *gpu) if (hang_debug) a6xx_dump(gpu); + /* Halt SQE first */ + gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3); + /* * Turn off keep alive that might have been enabled by the hang * interrupt From d6463fd4e97545ef4f7069d13a5fa3ac0924dae2 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 19 Aug 2022 01:52:15 +0530 Subject: [PATCH 25/84] drm/msm/a6xx: Handle GMU prepare-slumber hfi failure When prepare-slumber hfi fails, we should follow a6xx_gmu_force_off() sequence. Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/498401/ Link: https://lore.kernel.org/r/20220819015030.v5.7.I54815c7c36b80d4725cd054e536365250454452f@changeid Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index ec25f19a2985..e033d6a67a20 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1086,7 +1086,11 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) a6xx_bus_clear_pending_transactions(adreno_gpu); /* tell the GMU we want to slumber */ - a6xx_gmu_notify_slumber(gmu); + ret = a6xx_gmu_notify_slumber(gmu); + if (ret) { + a6xx_gmu_force_off(gmu); + return; + } ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, From c51720a6d0b402ed418c904500f78ce1897a93bc Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 6 Jul 2022 12:32:08 -0700 Subject: [PATCH 26/84] drm/msm/dp: make eDP panel as the first connected connector Some userspace presumes that the first connected connector is the main display, where it's supposed to display e.g. the login screen. For laptops, this should be the main panel. This patch call drm_helper_move_panel_connectors_to_head() after drm_bridge_connector_init() to make sure eDP stay at head of connected connector list. This fixes unexpected corruption happen at eDP panel if eDP is not placed at head of connected connector list. Changes in v2: -- move drm_helper_move_panel_connectors_to_head() to dpu_kms_drm_obj_init() Changes in v4: -- move drm_helper_move_panel_connectors_to_head() to msm_drm_init() Signed-off-by: Kuogee Hsieh Reviewed-by: Abhinav Kumar Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Fixes: ef7837ff091c ("drm/msm/dp: Add DP controllers for sc7280") Patchwork: https://patchwork.freedesktop.org/patch/492581/ Link: https://lore.kernel.org/r/1657135928-31195-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b564ff685f67..3403d7da6cae 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -479,6 +479,8 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) } } + drm_helper_move_panel_connectors_to_head(ddev); + ddev->mode_config.funcs = &mode_config_funcs; ddev->mode_config.helper_private = &mode_config_helper_funcs; From 40395b5c112925d8bd08da9d355a2b35949e61c9 Mon Sep 17 00:00:00 2001 From: sunliming Date: Tue, 19 Jul 2022 09:56:22 +0800 Subject: [PATCH 27/84] drm/msm/dsi: fix the inconsistent indenting Fix the inconsistent indenting in function msm_dsi_dphy_timing_calc_v3(). Fix the following smatch warnings: drivers/gpu/drm/msm/dsi/phy/dsi_phy.c:350 msm_dsi_dphy_timing_calc_v3() warn: inconsistent indenting Fixes: f1fa7ff44056 ("drm/msm/dsi: implement auto PHY timing calculator for 10nm PHY") Reported-by: kernel test robot Signed-off-by: sunliming Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/494662/ Link: https://lore.kernel.org/r/20220719015622.646718-1-sunliming@kylinos.cn Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index a39de3bdc7fa..56dfa2d24be1 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -347,7 +347,7 @@ int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing, } else { timing->shared_timings.clk_pre = linear_inter(tmax, tmin, pcnt2, 0, false); - timing->shared_timings.clk_pre_inc_by_2 = 0; + timing->shared_timings.clk_pre_inc_by_2 = 0; } timing->ta_go = 3; From 9811913a6dd05c0bda3bf507006f1fef903a369e Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Fri, 15 Jul 2022 12:14:28 -0700 Subject: [PATCH 28/84] drm/msm/dpu: populate wb or intf before reset_intf_cfg dpu_encoder_helper_phys_cleanup() was not populating neither wb or intf to the intf_cfg before calling the reset_intf_cfg(). This causes the reset of the active bits of wb/intf to be skipped which is incorrect. Fix this by populating the relevant wb or intf indices correctly. Fixes: ae4d721ce100 ("drm/msm/dpu: add an API to reset the encoder related hw blocks") Signed-off-by: Abhinav Kumar Reviewed-by: Jessica Zhang Tested-by: Jessica Zhang # Trogdor (SC8170) Patchwork: https://patchwork.freedesktop.org/patch/494298/ Link: https://lore.kernel.org/r/1657912468-17254-1-git-send-email-quic_abhinavk@quicinc.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index c682d4e02d1b..52a626117f70 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2061,6 +2061,12 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); + + if (phys_enc->hw_intf) + intf_cfg.intf = phys_enc->hw_intf->idx; + if (phys_enc->hw_wb) + intf_cfg.wb = phys_enc->hw_wb->idx; + if (phys_enc->hw_pp->merge_3d) intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; From 3487896b26269f5430596711490a7c48d2941d9d Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Thu, 11 Aug 2022 15:57:50 -0700 Subject: [PATCH 29/84] drm/msm/dp: delete DP_RECOVERED_CLOCK_OUT_EN to fix tps4 Data Symbols scrambled is required for tps4 at link training 2. Therefore SCRAMBLING_DISABLE bit should not be set for tps4 to work. RECOVERED_CLOCK_OUT_EN is for enable simple EYE test for jitter measurement with minimal equipment for embedded applications purpose and is not required to be set during normal operation. Current implementation always have RECOVERED_CLOCK_OUT_EN bit set which cause SCRAMBLING_DISABLE bit wrongly set at tps4 which prevent tps4 from working. This patch delete setting RECOVERED_CLOCK_OUT_EN to fix SCRAMBLING_DISABLE be wrongly set at tps4. Changes in v2: -- fix Fixes tag Changes in v3: -- revise commit text Changes in v4: -- fix commit text newline Changes in v5: -- fix commit text line over 75 chars Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: Kuogee Hsieh Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497194/ Link: https://lore.kernel.org/r/1660258670-4200-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- 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 ab6aa13b1639..013ca02e17cb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1214,7 +1214,7 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl, if (ret) return ret; - dp_ctrl_train_pattern_set(ctrl, pattern | DP_RECOVERED_CLOCK_OUT_EN); + dp_ctrl_train_pattern_set(ctrl, pattern); for (tries = 0; tries <= maximum_retries; tries++) { drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); From b59c619aec0079621abb6e6a47607e947238909f Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:48 -0700 Subject: [PATCH 30/84] drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg 3 regulators are listed but the number 2 is specified. Fix it. Fixes: 3a3ff88a0fc1 ("drm/msm/dsi: Add 8x96 info in dsi_cfg") Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496318/ Link: https://lore.kernel.org/r/20220804073608.v4.1.I1056ee3f77f71287f333279efe4c85f88d403f65@changeid Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 2c23324a2296..02000a7b7a18 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -109,7 +109,7 @@ static const char * const dsi_8996_bus_clk_names[] = { static const struct msm_dsi_config msm8996_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, .reg_cfg = { - .num = 2, + .num = 3, .regs = { {"vdda", 18160, 1 }, /* 1.25 V */ {"vcca", 17000, 32 }, /* 0.925 V */ From 479d431519631f678151a1076cf31f00e145ce9c Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:49 -0700 Subject: [PATCH 31/84] drm/msm/dsi: Fix number of regulators for SDM660 1 regulator is listed but the number 2 is specified. This presumably means we try to get a regulator with no name. Fix it. Fixes: 462f7017a691 ("drm/msm/dsi: Fix DSI and DSI PHY regulator config from SDM660") Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Marijn Suijten Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496323/ Link: https://lore.kernel.org/r/20220804073608.v4.2.I94b3c3e412b7c208061349f05659e126483171b1@changeid Signed-off-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 02000a7b7a18..72c018e26f47 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -148,7 +148,7 @@ static const char * const dsi_sdm660_bus_clk_names[] = { static const struct msm_dsi_config sdm660_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, .reg_cfg = { - .num = 2, + .num = 1, .regs = { {"vdda", 12560, 4 }, /* 1.2 V */ }, From e93e45b1aa4909926b5c2e195eadbed1899e9e50 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 8 Jul 2022 09:26:32 -0700 Subject: [PATCH 32/84] drm/msm/gpu: Drop qos request if devm_devfreq_add_device() fails In the event that devm_devfreq_add_device() fails the device's qos freq list is left referencing df->idle_freq and df->boost_freq. Attempting to initialize devfreq again after a probe deferral will then cause invalid memory accesses in dev_pm_qos_add_request(). Fix this by dropping the requests in the error path. Fixes: 7c0ffcd40b16 ("drm/msm/gpu: Respect PM QoS constraints") Signed-off-by: Bjorn Andersson Reviewed-by: Rob Clark Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/493001/ Link: https://lore.kernel.org/r/20220708162632.3529864-1-bjorn.andersson@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu_devfreq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index d1f70426f554..85c443a37e4e 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -213,6 +213,8 @@ void msm_devfreq_init(struct msm_gpu *gpu) if (IS_ERR(df->devfreq)) { DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); + dev_pm_qos_remove_request(&df->idle_freq); + dev_pm_qos_remove_request(&df->boost_freq); df->devfreq = NULL; return; } From 323894610ba027dddc86e8a5c6e7982588d845dd Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 7 Aug 2022 09:09:01 -0700 Subject: [PATCH 33/84] drm/msm/rd: Fix FIFO-full deadlock If the previous thing cat'ing $debugfs/rd left the FIFO full, then subsequent open could deadlock in rd_write() (because open is blocked, not giving a chance for read() to consume any data in the FIFO). Also it is generally a good idea to clear out old data from the FIFO. Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/496706/ Link: https://lore.kernel.org/r/20220807160901.2353471-2-robdclark@gmail.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_rd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index a92ffde53f0b..db2f847c8535 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -196,6 +196,9 @@ static int rd_open(struct inode *inode, struct file *file) file->private_data = rd; rd->open = true; + /* Reset fifo to clear any previously unread data: */ + rd->fifo.head = rd->fifo.tail = 0; + /* the parsing tools need to know gpu-id to know which * register database to load. * From 46dd0c0658ff5783acce37dcfe437e2a79a9934e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 11 Jul 2022 13:04:31 +0300 Subject: [PATCH 34/84] drm/msm/dpu: use drm_dsc_config instead of msm_display_dsc_config There is no need to use the struct msm_display_dsc_config wrapper inside the dpu driver, use the struct drm_dsc_config directly to pass pps data. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Reviewed-by: Marijn Suijten Patchwork: https://patchwork.freedesktop.org/patch/493340/ Link: https://lore.kernel.org/r/20220711100432.455268-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 25 +++---- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 74 ++++++++++----------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 52a626117f70..7f5dba96b2ff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -162,7 +162,7 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @idle_timeout: idle timeout duration in milliseconds - * @dsc: msm_display_dsc_config pointer, for DSC-enabled encoders + * @dsc: drm_dsc_config pointer, for DSC-enabled encoders */ struct dpu_encoder_virt { struct drm_encoder base; @@ -208,7 +208,7 @@ struct dpu_encoder_virt { bool wide_bus_en; /* DSC configuration */ - struct msm_display_dsc_config *dsc; + struct drm_dsc_config *dsc; }; #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base) @@ -1791,12 +1791,12 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work) } static u32 -dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc, +dpu_encoder_dsc_initial_line_calc(struct drm_dsc_config *dsc, u32 enc_ip_width) { int ssm_delay, total_pixels, soft_slice_per_enc; - soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width; + soft_slice_per_enc = enc_ip_width / dsc->slice_width; /* * minimum number of initial line pixels is a sum of: @@ -1808,16 +1808,16 @@ dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc, * 5. 6 additional pixels as the output of the rate buffer is * 48 bits wide */ - ssm_delay = ((dsc->drm->bits_per_component < 10) ? 84 : 92); - total_pixels = ssm_delay * 3 + dsc->drm->initial_xmit_delay + 47; + ssm_delay = ((dsc->bits_per_component < 10) ? 84 : 92); + total_pixels = ssm_delay * 3 + dsc->initial_xmit_delay + 47; if (soft_slice_per_enc > 1) total_pixels += (ssm_delay * 3); - return DIV_ROUND_UP(total_pixels, dsc->drm->slice_width); + return DIV_ROUND_UP(total_pixels, dsc->slice_width); } static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc, struct dpu_hw_pingpong *hw_pp, - struct msm_display_dsc_config *dsc, + struct drm_dsc_config *dsc, u32 common_mode, u32 initial_lines) { @@ -1835,7 +1835,7 @@ static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc, } static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, - struct msm_display_dsc_config *dsc) + struct drm_dsc_config *dsc) { /* coding only for 2LM, 2enc, 1 dsc config */ struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; @@ -1858,14 +1858,15 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, } } - pic_width = dsc->drm->pic_width; + dsc_common_mode = 0; + pic_width = dsc->pic_width; dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL; if (enc_master->intf_mode == INTF_MODE_VIDEO) dsc_common_mode |= DSC_MODE_VIDEO; - this_frame_slices = pic_width / dsc->drm->slice_width; - intf_ip_w = this_frame_slices * dsc->drm->slice_width; + this_frame_slices = pic_width / dsc->slice_width; + intf_ip_w = this_frame_slices * dsc->slice_width; /* * dsc merge case: when using 2 encoders for the same stream, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index d4d1ecd416e3..9e7236ef34e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -36,7 +36,7 @@ struct msm_display_info { uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_cmd_mode; bool is_te_using_watchdog_timer; - struct msm_display_dsc_config *dsc; + struct drm_dsc_config *dsc; }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c index 411689ae6382..f2ddcfb6f7ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c @@ -37,7 +37,7 @@ static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc) } static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, - struct msm_display_dsc_config *dsc, + struct drm_dsc_config *dsc, u32 mode, u32 initial_lines) { @@ -52,89 +52,89 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, if (is_cmd_mode) initial_lines += 1; - slice_last_group_size = 3 - (dsc->drm->slice_width % 3); + slice_last_group_size = 3 - (dsc->slice_width % 3); data = (initial_lines << 20); data |= ((slice_last_group_size - 1) << 18); /* bpp is 6.4 format, 4 LSBs bits are for fractional part */ - data |= dsc->drm->bits_per_pixel << 12; - lsb = dsc->drm->bits_per_pixel % 4; - bpp = dsc->drm->bits_per_pixel / 4; + data |= dsc->bits_per_pixel << 12; + lsb = dsc->bits_per_pixel % 4; + bpp = dsc->bits_per_pixel / 4; bpp *= 4; bpp <<= 4; bpp |= lsb; data |= bpp << 8; - data |= (dsc->drm->block_pred_enable << 7); - data |= (dsc->drm->line_buf_depth << 3); - data |= (dsc->drm->simple_422 << 2); - data |= (dsc->drm->convert_rgb << 1); - data |= dsc->drm->bits_per_component; + data |= (dsc->block_pred_enable << 7); + data |= (dsc->line_buf_depth << 3); + data |= (dsc->simple_422 << 2); + data |= (dsc->convert_rgb << 1); + data |= dsc->bits_per_component; DPU_REG_WRITE(c, DSC_ENC, data); - data = dsc->drm->pic_width << 16; - data |= dsc->drm->pic_height; + data = dsc->pic_width << 16; + data |= dsc->pic_height; DPU_REG_WRITE(c, DSC_PICTURE, data); - data = dsc->drm->slice_width << 16; - data |= dsc->drm->slice_height; + data = dsc->slice_width << 16; + data |= dsc->slice_height; DPU_REG_WRITE(c, DSC_SLICE, data); - data = dsc->drm->slice_chunk_size << 16; + data = dsc->slice_chunk_size << 16; DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data); - data = dsc->drm->initial_dec_delay << 16; - data |= dsc->drm->initial_xmit_delay; + data = dsc->initial_dec_delay << 16; + data |= dsc->initial_xmit_delay; DPU_REG_WRITE(c, DSC_DELAY, data); - data = dsc->drm->initial_scale_value; + data = dsc->initial_scale_value; DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data); - data = dsc->drm->scale_decrement_interval; + data = dsc->scale_decrement_interval; DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data); - data = dsc->drm->scale_increment_interval; + data = dsc->scale_increment_interval; DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data); - data = dsc->drm->first_line_bpg_offset; + data = dsc->first_line_bpg_offset; DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data); - data = dsc->drm->nfl_bpg_offset << 16; - data |= dsc->drm->slice_bpg_offset; + data = dsc->nfl_bpg_offset << 16; + data |= dsc->slice_bpg_offset; DPU_REG_WRITE(c, DSC_BPG_OFFSET, data); - data = dsc->drm->initial_offset << 16; - data |= dsc->drm->final_offset; + data = dsc->initial_offset << 16; + data |= dsc->final_offset; DPU_REG_WRITE(c, DSC_DSC_OFFSET, data); - det_thresh_flatness = 7 + 2 * (dsc->drm->bits_per_component - 8); + det_thresh_flatness = 7 + 2 * (dsc->bits_per_component - 8); data = det_thresh_flatness << 10; - data |= dsc->drm->flatness_max_qp << 5; - data |= dsc->drm->flatness_min_qp; + data |= dsc->flatness_max_qp << 5; + data |= dsc->flatness_min_qp; DPU_REG_WRITE(c, DSC_FLATNESS, data); - data = dsc->drm->rc_model_size; + data = dsc->rc_model_size; DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data); - data = dsc->drm->rc_tgt_offset_low << 18; - data |= dsc->drm->rc_tgt_offset_high << 14; - data |= dsc->drm->rc_quant_incr_limit1 << 9; - data |= dsc->drm->rc_quant_incr_limit0 << 4; - data |= dsc->drm->rc_edge_factor; + data = dsc->rc_tgt_offset_low << 18; + data |= dsc->rc_tgt_offset_high << 14; + data |= dsc->rc_quant_incr_limit1 << 9; + data |= dsc->rc_quant_incr_limit0 << 4; + data |= dsc->rc_edge_factor; DPU_REG_WRITE(c, DSC_RC, data); } static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc, - struct msm_display_dsc_config *dsc) + struct drm_dsc_config *dsc) { - struct drm_dsc_rc_range_parameters *rc = dsc->drm->rc_range_params; + struct drm_dsc_rc_range_parameters *rc = dsc->rc_range_params; struct dpu_hw_blk_reg_map *c = &hw_dsc->hw; u32 off; int i; off = DSC_RC_BUF_THRESH; for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) { - DPU_REG_WRITE(c, off, dsc->drm->rc_buf_thresh[i]); + DPU_REG_WRITE(c, off, dsc->rc_buf_thresh[i]); off += 4; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h index 45e4118f1fa2..c0b77fe1a696 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h @@ -31,7 +31,7 @@ struct dpu_hw_dsc_ops { * @initial_lines: amount of initial lines to be used */ void (*dsc_config)(struct dpu_hw_dsc *hw_dsc, - struct msm_display_dsc_config *dsc, + struct drm_dsc_config *dsc, u32 mode, u32 initial_lines); @@ -41,7 +41,7 @@ struct dpu_hw_dsc_ops { * @dsc: panel dsc parameters */ void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc, - struct msm_display_dsc_config *dsc); + struct drm_dsc_config *dsc); }; struct dpu_hw_dsc { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 008e1420e6e5..e9d5417a719a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -585,7 +585,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, info.h_tile_instance[info.num_of_h_tiles++] = i; info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]); - info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]); + info.dsc = msm_dsi_get_dsc_config(priv->dsi[i])->drm; if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) { rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder); From 4b2b1b3674f80ed786e73d8e24c19e7129257ad8 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 11 Jul 2022 13:04:32 +0300 Subject: [PATCH 35/84] drm/msm/dsi: use drm_dsc_config instead of msm_display_dsc_config There is no need to use the struct msm_display_dsc_config wrapper inside the dsi driver, use the struct drm_dsc_config directly to pass pps data. Signed-off-by: Dmitry Baryshkov Reviewed-by: Marijn Suijten Patchwork: https://patchwork.freedesktop.org/patch/493341/ Link: https://lore.kernel.org/r/20220711100432.455268-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 157 +++++++++++------------- drivers/gpu/drm/msm/msm_drv.h | 9 +- 5 files changed, 79 insertions(+), 93 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index e9d5417a719a..008e1420e6e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -585,7 +585,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, info.h_tile_instance[info.num_of_h_tiles++] = i; info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]); - info.dsc = msm_dsi_get_dsc_config(priv->dsi[i])->drm; + info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]); if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) { rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder); diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 1625328fa430..8f1ed31b048a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -21,7 +21,7 @@ bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi) return !(host_flags & MIPI_DSI_MODE_VIDEO); } -struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) +struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) { return msm_dsi_host_get_dsc_config(msm_dsi->host); } diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 580a1e6358bf..df46cdda1b43 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -154,7 +154,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi); int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi); void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host); void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host); -struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host); +struct drm_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index a34078497af1..15e108be1901 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -33,7 +33,7 @@ #define DSI_RESET_TOGGLE_DELAY_MS 20 -static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc); +static int dsi_populate_dsc_params(struct drm_dsc_config *dsc); static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) { @@ -161,7 +161,7 @@ struct msm_dsi_host { struct regmap *sfpb; struct drm_display_mode *mode; - struct msm_display_dsc_config *dsc; + struct drm_dsc_config *dsc; /* connected device info */ struct device_node *device_node; @@ -916,7 +916,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay) { - struct msm_display_dsc_config *dsc = msm_host->dsc; + struct drm_dsc_config *dsc = msm_host->dsc; u32 reg, intf_width, reg_ctrl, reg_ctrl2; u32 slice_per_intf, total_bytes_per_intf; u32 pkt_per_line; @@ -927,24 +927,24 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod * compress mode registers */ intf_width = hdisplay; - slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width); + slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width); /* If slice_per_pkt is greater than slice_per_intf * then default to 1. This can happen during partial * update. */ - if (slice_per_intf > dsc->drm->slice_count) - dsc->drm->slice_count = 1; + if (slice_per_intf > dsc->slice_count) + dsc->slice_count = 1; - slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width); - bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * dsc->drm->bits_per_pixel, 8); + slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width); + bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 8); - dsc->drm->slice_chunk_size = bytes_in_slice; + dsc->slice_chunk_size = bytes_in_slice; total_bytes_per_intf = bytes_in_slice * slice_per_intf; eol_byte_num = total_bytes_per_intf % 3; - pkt_per_line = slice_per_intf / dsc->drm->slice_count; + pkt_per_line = slice_per_intf / dsc->slice_count; if (is_cmd_mode) /* packet data type */ reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE); @@ -1009,7 +1009,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) } if (msm_host->dsc) { - struct msm_display_dsc_config *dsc = msm_host->dsc; + struct drm_dsc_config *dsc = msm_host->dsc; /* update dsc params with timing params */ if (!dsc || !mode->hdisplay || !mode->vdisplay) { @@ -1018,9 +1018,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) return; } - dsc->drm->pic_width = mode->hdisplay; - dsc->drm->pic_height = mode->vdisplay; - DBG("Mode %dx%d\n", dsc->drm->pic_width, dsc->drm->pic_height); + dsc->pic_width = mode->hdisplay; + dsc->pic_height = mode->vdisplay; + DBG("Mode %dx%d\n", dsc->pic_width, dsc->pic_height); /* we do the calculations for dsc parameters here so that * panel can use these parameters @@ -1841,7 +1841,7 @@ static char bpg_offset[DSC_NUM_BUF_RANGES] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 }; -static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc) +static int dsi_populate_dsc_params(struct drm_dsc_config *dsc) { int mux_words_size; int groups_per_line, groups_total; @@ -1854,98 +1854,98 @@ static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc) int final_value, final_scale; int i; - dsc->drm->rc_model_size = 8192; - dsc->drm->first_line_bpg_offset = 12; - dsc->drm->rc_edge_factor = 6; - dsc->drm->rc_tgt_offset_high = 3; - dsc->drm->rc_tgt_offset_low = 3; - dsc->drm->simple_422 = 0; - dsc->drm->convert_rgb = 1; - dsc->drm->vbr_enable = 0; + dsc->rc_model_size = 8192; + dsc->first_line_bpg_offset = 12; + dsc->rc_edge_factor = 6; + dsc->rc_tgt_offset_high = 3; + dsc->rc_tgt_offset_low = 3; + dsc->simple_422 = 0; + dsc->convert_rgb = 1; + dsc->vbr_enable = 0; /* handle only bpp = bpc = 8 */ for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) - dsc->drm->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i]; + dsc->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i]; for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { - dsc->drm->rc_range_params[i].range_min_qp = min_qp[i]; - dsc->drm->rc_range_params[i].range_max_qp = max_qp[i]; - dsc->drm->rc_range_params[i].range_bpg_offset = bpg_offset[i]; + dsc->rc_range_params[i].range_min_qp = min_qp[i]; + dsc->rc_range_params[i].range_max_qp = max_qp[i]; + dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i]; } - dsc->drm->initial_offset = 6144; /* Not bpp 12 */ - if (dsc->drm->bits_per_pixel != 8) - dsc->drm->initial_offset = 2048; /* bpp = 12 */ + dsc->initial_offset = 6144; /* Not bpp 12 */ + if (dsc->bits_per_pixel != 8) + dsc->initial_offset = 2048; /* bpp = 12 */ mux_words_size = 48; /* bpc == 8/10 */ - if (dsc->drm->bits_per_component == 12) + if (dsc->bits_per_component == 12) mux_words_size = 64; - dsc->drm->initial_xmit_delay = 512; - dsc->drm->initial_scale_value = 32; - dsc->drm->first_line_bpg_offset = 12; - dsc->drm->line_buf_depth = dsc->drm->bits_per_component + 1; + dsc->initial_xmit_delay = 512; + dsc->initial_scale_value = 32; + dsc->first_line_bpg_offset = 12; + dsc->line_buf_depth = dsc->bits_per_component + 1; /* bpc 8 */ - dsc->drm->flatness_min_qp = 3; - dsc->drm->flatness_max_qp = 12; - dsc->drm->rc_quant_incr_limit0 = 11; - dsc->drm->rc_quant_incr_limit1 = 11; - dsc->drm->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; + dsc->flatness_min_qp = 3; + dsc->flatness_max_qp = 12; + dsc->rc_quant_incr_limit0 = 11; + dsc->rc_quant_incr_limit1 = 11; + dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of * params are calculated */ - groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3); - dsc->drm->slice_chunk_size = dsc->drm->slice_width * dsc->drm->bits_per_pixel / 8; - if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8) - dsc->drm->slice_chunk_size++; + groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3); + dsc->slice_chunk_size = dsc->slice_width * dsc->bits_per_pixel / 8; + if ((dsc->slice_width * dsc->bits_per_pixel) % 8) + dsc->slice_chunk_size++; /* rbs-min */ - min_rate_buffer_size = dsc->drm->rc_model_size - dsc->drm->initial_offset + - dsc->drm->initial_xmit_delay * dsc->drm->bits_per_pixel + - groups_per_line * dsc->drm->first_line_bpg_offset; + min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset + + dsc->initial_xmit_delay * dsc->bits_per_pixel + + groups_per_line * dsc->first_line_bpg_offset; - hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->drm->bits_per_pixel); + hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->bits_per_pixel); - dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay; + dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay; - dsc->drm->initial_scale_value = 8 * dsc->drm->rc_model_size / - (dsc->drm->rc_model_size - dsc->drm->initial_offset); + dsc->initial_scale_value = 8 * dsc->rc_model_size / + (dsc->rc_model_size - dsc->initial_offset); - slice_bits = 8 * dsc->drm->slice_chunk_size * dsc->drm->slice_height; + slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height; - groups_total = groups_per_line * dsc->drm->slice_height; + groups_total = groups_per_line * dsc->slice_height; - data = dsc->drm->first_line_bpg_offset * 2048; + data = dsc->first_line_bpg_offset * 2048; - dsc->drm->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->drm->slice_height - 1)); + dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1)); - pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * dsc->drm->bits_per_component + 4) - 2); + pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * dsc->bits_per_component + 4) - 2); num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size - ((slice_bits - pre_num_extra_mux_bits) % mux_words_size)); - data = 2048 * (dsc->drm->rc_model_size - dsc->drm->initial_offset + num_extra_mux_bits); - dsc->drm->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); + data = 2048 * (dsc->rc_model_size - dsc->initial_offset + num_extra_mux_bits); + dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); /* bpp * 16 + 0.5 */ - data = dsc->drm->bits_per_pixel * 16; + data = dsc->bits_per_pixel * 16; data *= 2; data++; data /= 2; target_bpp_x16 = data; - data = (dsc->drm->initial_xmit_delay * target_bpp_x16) / 16; - final_value = dsc->drm->rc_model_size - data + num_extra_mux_bits; - dsc->drm->final_offset = final_value; + data = (dsc->initial_xmit_delay * target_bpp_x16) / 16; + final_value = dsc->rc_model_size - data + num_extra_mux_bits; + dsc->final_offset = final_value; - final_scale = 8 * dsc->drm->rc_model_size / (dsc->drm->rc_model_size - final_value); + final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - final_value); - data = (final_scale - 9) * (dsc->drm->nfl_bpg_offset + dsc->drm->slice_bpg_offset); - dsc->drm->scale_increment_interval = (2048 * dsc->drm->final_offset) / data; + data = (final_scale - 9) * (dsc->nfl_bpg_offset + dsc->slice_bpg_offset); + dsc->scale_increment_interval = (2048 * dsc->final_offset) / data; - dsc->drm->scale_decrement_interval = groups_per_line / (dsc->drm->initial_scale_value - 8); + dsc->scale_decrement_interval = groups_per_line / (dsc->initial_scale_value - 8); return 0; } @@ -2165,17 +2165,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, msm_host->dev = dev; panel = msm_dsi_host_get_panel(&msm_host->base); - if (!IS_ERR(panel) && panel->dsc) { - struct msm_display_dsc_config *dsc = msm_host->dsc; - - if (!dsc) { - dsc = devm_kzalloc(&msm_host->pdev->dev, sizeof(*dsc), GFP_KERNEL); - if (!dsc) - return -ENOMEM; - dsc->drm = panel->dsc; - msm_host->dsc = dsc; - } - } + if (!IS_ERR(panel) && panel->dsc) + msm_host->dsc = panel->dsc; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { @@ -2659,22 +2650,22 @@ enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, const struct drm_display_mode *mode) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - struct msm_display_dsc_config *dsc = msm_host->dsc; + struct drm_dsc_config *dsc = msm_host->dsc; int pic_width = mode->hdisplay; int pic_height = mode->vdisplay; if (!msm_host->dsc) return MODE_OK; - if (pic_width % dsc->drm->slice_width) { + if (pic_width % dsc->slice_width) { pr_err("DSI: pic_width %d has to be multiple of slice %d\n", - pic_width, dsc->drm->slice_width); + pic_width, dsc->slice_width); return MODE_H_ILLEGAL; } - if (pic_height % dsc->drm->slice_height) { + if (pic_height % dsc->slice_height) { pr_err("DSI: pic_height %d has to be multiple of slice %d\n", - pic_height, dsc->drm->slice_height); + pic_height, dsc->slice_height); return MODE_V_ILLEGAL; } @@ -2771,7 +2762,7 @@ void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host) DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER); } -struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host) +struct drm_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 09c4585a8064..4229a7222088 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -103,11 +103,6 @@ struct msm_drm_thread { struct kthread_worker *worker; }; -/* DSC config */ -struct msm_display_dsc_config { - struct drm_dsc_config *drm; -}; - struct msm_drm_private { struct drm_device *dev; @@ -329,7 +324,7 @@ void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi); bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi); bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi); -struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi); +struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi); #else static inline void __init msm_dsi_register(void) { @@ -359,7 +354,7 @@ static inline bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi) return false; } -static inline struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) +static inline struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) { return NULL; } From a5e96a572d59ce45da51a27310f8a376bc69a868 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 6 Jul 2022 17:52:19 +0300 Subject: [PATCH 36/84] dt-bindings: display/msm/gpu: allow specifying several IOMMU nodes Different platforms require different amounts of IOMMUs. The APQ8064 uses 64 IOMMU instances for GPU, adjust the schema accordingly. Signed-off-by: Dmitry Baryshkov Acked-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/492536/ Link: https://lore.kernel.org/r/20220706145222.1565238-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/gpu.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml index 3397bc31d087..346aabdccf7b 100644 --- a/Documentation/devicetree/bindings/display/msm/gpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml @@ -58,7 +58,8 @@ properties: - const: ocmem iommus: - maxItems: 1 + minItems: 1 + maxItems: 64 sram: $ref: /schemas/types.yaml#/definitions/phandle-array From 47531e478514caea0940e641c22ce9f6dab3401f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 6 Jul 2022 17:52:21 +0300 Subject: [PATCH 37/84] dt-bindings: display/msm/gmu: account for different GMU variants Make display/msm/gmu.yaml describe all existing GMU variants rather than just the 630.2 (SDM845) version of it. Signed-off-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/492539/ Link: https://lore.kernel.org/r/20220706145222.1565238-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../devicetree/bindings/display/msm/gmu.yaml | 166 +++++++++++++++--- 1 file changed, 146 insertions(+), 20 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml index fe55611d2603..67fdeeabae0c 100644 --- a/Documentation/devicetree/bindings/display/msm/gmu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml @@ -20,35 +20,24 @@ description: | properties: compatible: items: - - enum: - - qcom,adreno-gmu-630.2 + - pattern: '^qcom,adreno-gmu-6[0-9][0-9]\.[0-9]$' - const: qcom,adreno-gmu reg: - items: - - description: Core GMU registers - - description: GMU PDC registers - - description: GMU PDC sequence registers + minItems: 3 + maxItems: 4 reg-names: - items: - - const: gmu - - const: gmu_pdc - - const: gmu_pdc_seq + minItems: 3 + maxItems: 4 clocks: - items: - - description: GMU clock - - description: GPU CX clock - - description: GPU AXI clock - - description: GPU MEMNOC clock + minItems: 4 + maxItems: 7 clock-names: - items: - - const: gmu - - const: cxo - - const: axi - - const: memnoc + minItems: 4 + maxItems: 7 interrupts: items: @@ -76,6 +65,9 @@ properties: operating-points-v2: true + opp-table: + type: object + required: - compatible - reg @@ -91,6 +83,140 @@ required: additionalProperties: false +allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,adreno-gmu-618.0 + - qcom,adreno-gmu-630.2 + then: + properties: + reg: + items: + - description: Core GMU registers + - description: GMU PDC registers + - description: GMU PDC sequence registers + reg-names: + items: + - const: gmu + - const: gmu_pdc + - const: gmu_pdc_seq + clocks: + items: + - description: GMU clock + - description: GPU CX clock + - description: GPU AXI clock + - description: GPU MEMNOC clock + clock-names: + items: + - const: gmu + - const: cxo + - const: axi + - const: memnoc + + - if: + properties: + compatible: + contains: + enum: + - qcom,adreno-gmu-635.0 + then: + properties: + reg: + items: + - description: Core GMU registers + - description: Resource controller registers + - description: GMU PDC registers + reg-names: + items: + - const: gmu + - const: rscc + - const: gmu_pdc + clocks: + items: + - description: GMU clock + - description: GPU CX clock + - description: GPU AXI clock + - description: GPU MEMNOC clock + - description: GPU AHB clock + - description: GPU HUB CX clock + - description: GPU SMMU vote clock + clock-names: + items: + - const: gmu + - const: cxo + - const: axi + - const: memnoc + - const: ahb + - const: hub + - const: smmu_vote + + - if: + properties: + compatible: + contains: + enum: + - qcom,adreno-gmu-640.1 + then: + properties: + reg: + items: + - description: Core GMU registers + - description: GMU PDC registers + - description: GMU PDC sequence registers + reg-names: + items: + - const: gmu + - const: gmu_pdc + - const: gmu_pdc_seq + + - if: + properties: + compatible: + contains: + enum: + - qcom,adreno-gmu-650.2 + then: + properties: + reg: + items: + - description: Core GMU registers + - description: Resource controller registers + - description: GMU PDC registers + - description: GMU PDC sequence registers + reg-names: + items: + - const: gmu + - const: rscc + - const: gmu_pdc + - const: gmu_pdc_seq + + - if: + properties: + compatible: + contains: + enum: + - qcom,adreno-gmu-640.1 + - qcom,adreno-gmu-650.2 + then: + properties: + clocks: + items: + - description: GPU AHB clock + - description: GMU clock + - description: GPU CX clock + - description: GPU AXI clock + - description: GPU MEMNOC clock + clock-names: + items: + - const: ahb + - const: gmu + - const: cxo + - const: axi + - const: memnoc + examples: - | #include From 4dd1be2f8fc2305f0821643324f3e06ddf08fde5 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 6 Jul 2022 17:52:22 +0300 Subject: [PATCH 38/84] dt-bindings: display/msm/mdp4: require 4 IOMMUs APQ8064, the only supported mdp4 platform, uses 4 IOMMUs for the MDP4 device. Update schema accordingly. When we have other MDP4 platforms, this spec can be updated accordingly. Signed-off-by: Dmitry Baryshkov Acked-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/492541/ Link: https://lore.kernel.org/r/20220706145222.1565238-5-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/mdp4.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/mdp4.yaml b/Documentation/devicetree/bindings/display/msm/mdp4.yaml index f63f60fea27c..58c13f5277b6 100644 --- a/Documentation/devicetree/bindings/display/msm/mdp4.yaml +++ b/Documentation/devicetree/bindings/display/msm/mdp4.yaml @@ -36,7 +36,7 @@ properties: maxItems: 1 iommus: - maxItems: 1 + maxItems: 4 ports: $ref: /schemas/graph.yaml#/properties/ports From fc951a415e57dc7332099c2436bbc45067d2e679 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Aug 2022 09:20:55 +0300 Subject: [PATCH 39/84] dt-bindings: display/msm: dpu-msm8998: add missing DPU opp-table The 'display-controller' child (DPU) of Display SubSystem (MDSS) uses opp-table, so reference it which allows restricting DPU schema to fixed list of properties. Fixes: 6e986a8f1cf1 ("dt-bindings: display: msm: Add binding for msm8998 dpu") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497896/ Link: https://lore.kernel.org/r/20220817062059.18640-2-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../devicetree/bindings/display/msm/dpu-msm8998.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml index 2df64afb76e6..253665c693e6 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml @@ -62,6 +62,7 @@ patternProperties: "^display-controller@[0-9a-f]+$": type: object description: Node containing the properties of DPU. + additionalProperties: false properties: compatible: @@ -105,6 +106,9 @@ patternProperties: maxItems: 1 operating-points-v2: true + opp-table: + type: object + ports: $ref: /schemas/graph.yaml#/properties/ports description: | From 1c1385b33217e24201778c7f454d640db1bb4e21 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Aug 2022 09:20:56 +0300 Subject: [PATCH 40/84] dt-bindings: display/msm: dpu-qcm2290: add missing DPU opp-table The 'display-controller' child (DPU) of Display SubSystem (MDSS) uses opp-table, so reference it which allows restricting DPU schema to fixed list of properties. Fixes: 164f69d9d45a ("dt-bindings: msm: disp: add yaml schemas for QCM2290 DPU bindings") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497893/ Link: https://lore.kernel.org/r/20220817062059.18640-3-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml index 734d14de966d..c5824e1d2382 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml @@ -74,6 +74,7 @@ patternProperties: "^display-controller@[0-9a-f]+$": type: object description: Node containing the properties of DPU. + additionalProperties: false properties: compatible: @@ -113,6 +114,8 @@ patternProperties: maxItems: 1 operating-points-v2: true + opp-table: + type: object ports: $ref: /schemas/graph.yaml#/properties/ports From 5621478dbc0a537a81d887cdbc86d4d12d51bd8f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Aug 2022 09:20:57 +0300 Subject: [PATCH 41/84] dt-bindings: display/msm: dpu-sc7180: add missing DPU opp-table The 'display-controller' child (DPU) of Display SubSystem (MDSS) uses opp-table, so reference it which allows restricting DPU schema to fixed list of properties. Fixes: 3d7a0dd8f39b ("dt-bindings: msm: disp: add yaml schemas for DPU bindings") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497894/ Link: https://lore.kernel.org/r/20220817062059.18640-4-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml index d3c3e4b07897..4890bc25f3fd 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml @@ -73,6 +73,7 @@ patternProperties: "^display-controller@[0-9a-f]+$": type: object description: Node containing the properties of DPU. + additionalProperties: false properties: compatible: @@ -114,6 +115,8 @@ patternProperties: maxItems: 1 operating-points-v2: true + opp-table: + type: object ports: $ref: /schemas/graph.yaml#/properties/ports From c5a7f04c0257659e1df1d4a166cfcc17c70c7fdc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Aug 2022 09:20:58 +0300 Subject: [PATCH 42/84] dt-bindings: display/msm: dpu-sc7280: add missing DPU opp-table The 'display-controller' child (DPU) of Display SubSystem (MDSS) uses opp-table, so reference it which allows restricting DPU schema to fixed list of properties. Fixes: 57fd4f34ddac ("dt-bindings: msm: add DT bindings for sc7280") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497898/ Link: https://lore.kernel.org/r/20220817062059.18640-5-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml index f427eec3d3a4..584d646021d5 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml @@ -72,6 +72,7 @@ patternProperties: "^display-controller@[0-9a-f]+$": type: object description: Node containing the properties of DPU. + additionalProperties: false properties: compatible: @@ -112,6 +113,8 @@ patternProperties: maxItems: 1 operating-points-v2: true + opp-table: + type: object ports: $ref: /schemas/graph.yaml#/properties/ports From feda34d14adf295a6311ffe00e9b89104bcda61b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Aug 2022 09:20:59 +0300 Subject: [PATCH 43/84] dt-bindings: display/msm: dpu-sdm845: add missing DPU opp-table The 'display-controller' child (DPU) of Display SubSystem (MDSS) uses opp-table, so reference it which allows restricting DPU schema to fixed list of properties. Fixes: 3d7a0dd8f39b ("dt-bindings: msm: disp: add yaml schemas for DPU bindings") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/499212/ Link: https://lore.kernel.org/r/20220817062059.18640-6-krzysztof.kozlowski@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml index 2bb8896beffc..7d1037373175 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml @@ -65,6 +65,7 @@ patternProperties: "^display-controller@[0-9a-f]+$": type: object description: Node containing the properties of DPU. + additionalProperties: false properties: compatible: @@ -102,6 +103,9 @@ patternProperties: maxItems: 1 operating-points-v2: true + opp-table: + type: object + ports: $ref: /schemas/graph.yaml#/properties/ports description: | From 5ccdcecaf8f732f593e359ebfb65de96b11bae66 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 5 Aug 2022 14:56:30 +0300 Subject: [PATCH 44/84] drm/msm: lookup the ICC paths in both mdp5/dpu and mdss devices The commit 6874f48bb8b0 ("drm/msm: make mdp5/dpu devices master components") changed the MDP5 driver to look for the interconnect paths in the MDSS device rather than in the MDP5 device itself. This was left unnoticed since on my testing devices the interconnects probably didn't reach the sync state. Rather than just using the MDP5 device for ICC path lookups for the MDP5 devices, introduce an additional helper to check both MDP5/DPU and MDSS nodes. This will be helpful for the MDP5->DPU conversion, since the driver will have to check both nodes. Fixes: 6874f48bb8b0 ("drm/msm: make mdp5/dpu devices master components") Reported-by: Marijn Suijten Reported-by: Yassine Oudjana Signed-off-by: Dmitry Baryshkov Tested-by: Marijn Suijten # On sdm630 Tested-by: Yassine Oudjana # msm8996 Patchwork: https://patchwork.freedesktop.org/patch/496488/ Link: https://lore.kernel.org/r/20220805115630.506391-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 ++----- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 9 +++------ drivers/gpu/drm/msm/msm_drv.h | 2 ++ drivers/gpu/drm/msm/msm_io_utils.c | 22 ++++++++++++++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 008e1420e6e5..8646fd0603cb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -384,12 +384,9 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) struct icc_path *path1; struct drm_device *dev = dpu_kms->dev; struct device *dpu_dev = dev->dev; - struct device *mdss_dev = dpu_dev->parent; - /* Interconnects are a part of MDSS device tree binding, not the - * MDP/DPU device. */ - path0 = of_icc_get(mdss_dev, "mdp0-mem"); - path1 = of_icc_get(mdss_dev, "mdp1-mem"); + path0 = msm_icc_get(dpu_dev, "mdp0-mem"); + path1 = msm_icc_get(dpu_dev, "mdp1-mem"); if (IS_ERR_OR_NULL(path0)) return PTR_ERR_OR_ZERO(path0); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index d2a48caf9d27..b0d21838a134 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -902,12 +902,9 @@ fail: static int mdp5_setup_interconnect(struct platform_device *pdev) { - /* Interconnects are a part of MDSS device tree binding, not the - * MDP5 device. */ - struct device *mdss_dev = pdev->dev.parent; - struct icc_path *path0 = of_icc_get(mdss_dev, "mdp0-mem"); - struct icc_path *path1 = of_icc_get(mdss_dev, "mdp1-mem"); - struct icc_path *path_rot = of_icc_get(mdss_dev, "rotator-mem"); + struct icc_path *path0 = msm_icc_get(&pdev->dev, "mdp0-mem"); + struct icc_path *path1 = msm_icc_get(&pdev->dev, "mdp1-mem"); + struct icc_path *path_rot = msm_icc_get(&pdev->dev, "rotator-mem"); if (IS_ERR(path0)) return PTR_ERR(path0); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 4229a7222088..f6670f82e350 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -467,6 +467,8 @@ 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); +struct icc_path *msm_icc_get(struct device *dev, const char *name); + #define msm_writel(data, addr) writel((data), (addr)) #define msm_readl(addr) readl((addr)) diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c index 7b504617833a..d02cd29ce829 100644 --- a/drivers/gpu/drm/msm/msm_io_utils.c +++ b/drivers/gpu/drm/msm/msm_io_utils.c @@ -5,6 +5,8 @@ * Author: Rob Clark */ +#include + #include "msm_drv.h" /* @@ -124,3 +126,23 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, work->worker = worker; kthread_init_work(&work->work, fn); } + +struct icc_path *msm_icc_get(struct device *dev, const char *name) +{ + struct device *mdss_dev = dev->parent; + struct icc_path *path; + + path = of_icc_get(dev, name); + if (path) + return path; + + /* + * If there are no interconnects attached to the corresponding device + * node, of_icc_get() will return NULL. + * + * If the MDP5/DPU device node doesn't have interconnects, lookup the + * path in the parent (MDSS) device. + */ + return of_icc_get(mdss_dev, name); + +} From 7538f80ae0d98bf51eb89eee5344aec219902d42 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 15 Jun 2022 15:57:01 +0300 Subject: [PATCH 45/84] drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx Remove loops over hw_vbif. Instead always VBIF's idx as an index in the array. This fixes an error in dpu_kms_hw_init(), where we fill dpu_kms->hw_vbif[i], but check for an error pointer at dpu_kms->hw_vbif[vbif_idx]. Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/489569/ Link: https://lore.kernel.org/r/20220615125703.24647-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 ++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 29 +++++++++++------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 8646fd0603cb..c99c7a218ddb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -823,12 +823,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) _dpu_kms_mmu_destroy(dpu_kms); if (dpu_kms->catalog) { - for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { - u32 vbif_idx = dpu_kms->catalog->vbif[i].id; - - if ((vbif_idx < VBIF_MAX) && dpu_kms->hw_vbif[vbif_idx]) { - dpu_hw_vbif_destroy(dpu_kms->hw_vbif[vbif_idx]); - dpu_kms->hw_vbif[vbif_idx] = NULL; + for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { + if (dpu_kms->hw_vbif[i]) { + dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]); + dpu_kms->hw_vbif[i] = NULL; } } } @@ -1110,7 +1108,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { u32 vbif_idx = dpu_kms->catalog->vbif[i].id; - dpu_kms->hw_vbif[i] = dpu_hw_vbif_init(vbif_idx, + dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, dpu_kms->vbif[vbif_idx], dpu_kms->catalog); if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) { rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index 21d20373eb8b..a18fb649301c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -11,6 +11,14 @@ #include "dpu_hw_vbif.h" #include "dpu_trace.h" +static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif vbif_idx) +{ + if (vbif_idx < ARRAY_SIZE(dpu_kms->hw_vbif)) + return dpu_kms->hw_vbif[vbif_idx]; + + return NULL; +} + /** * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt * @vbif: Pointer to hardware vbif driver @@ -148,20 +156,15 @@ exit: void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, struct dpu_vbif_set_ot_params *params) { - struct dpu_hw_vbif *vbif = NULL; + struct dpu_hw_vbif *vbif; struct dpu_hw_mdp *mdp; bool forced_on = false; u32 ot_lim; - int ret, i; + int ret; mdp = dpu_kms->hw_mdp; - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i] && - dpu_kms->hw_vbif[i]->idx == params->vbif_idx) - vbif = dpu_kms->hw_vbif[i]; - } - + vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); if (!vbif || !mdp) { DRM_DEBUG_ATOMIC("invalid arguments vbif %d mdp %d\n", vbif != NULL, mdp != NULL); @@ -204,7 +207,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, struct dpu_vbif_set_qos_params *params) { - struct dpu_hw_vbif *vbif = NULL; + struct dpu_hw_vbif *vbif; struct dpu_hw_mdp *mdp; bool forced_on = false; const struct dpu_vbif_qos_tbl *qos_tbl; @@ -216,13 +219,7 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, } mdp = dpu_kms->hw_mdp; - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i] && - dpu_kms->hw_vbif[i]->idx == params->vbif_idx) { - vbif = dpu_kms->hw_vbif[i]; - break; - } - } + vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); if (!vbif || !vbif->cap) { DPU_ERROR("invalid vbif %d\n", params->vbif_idx); From bc778bb9841a6527d7fdd23062515e6d4a1b2874 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 15 Jun 2022 15:57:02 +0300 Subject: [PATCH 46/84] drm/msm/dpu: fix error handling around dpu_hw_vbif_init Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If the value is NULL, then the function will return 0 instead of a proper return code. Moreover dpu_hw_vbif_init() function can not return NULL. So, replace corresponding IS_ERR_OR_NULL() call with IS_ERR(). Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/489570/ Link: https://lore.kernel.org/r/20220615125703.24647-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c99c7a218ddb..ffdb4fcd3bcc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1110,10 +1110,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, dpu_kms->vbif[vbif_idx], dpu_kms->catalog); - if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) { + if (IS_ERR(dpu_kms->hw_vbif[vbif_idx])) { rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); - if (!dpu_kms->hw_vbif[vbif_idx]) - rc = -EINVAL; DPU_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc); dpu_kms->hw_vbif[vbif_idx] = NULL; goto power_error; From 606f015bdb8d0d172143f589320302d2d922f2f6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 15 Jun 2022 15:57:03 +0300 Subject: [PATCH 47/84] drm/msm/dpu: drop VBIF indices We do not expect to have other VBIFs. Drop VBIF_n indices and always use VBIF_RT and VBIF_NRT. Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/489571/ Link: https://lore.kernel.org/r/20220615125703.24647-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 6 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 36 ++++++++++++------- 3 files changed, 28 insertions(+), 18 deletions(-) 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 0239a811d5ec..76b35410be71 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1333,7 +1333,7 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = { static const struct dpu_vbif_cfg msm8998_vbif[] = { { - .name = "vbif_0", .id = VBIF_0, + .name = "vbif_rt", .id = VBIF_RT, .base = 0, .len = 0x1040, .default_ot_rd_limit = 32, .default_ot_wr_limit = 32, @@ -1363,7 +1363,7 @@ static const struct dpu_vbif_cfg msm8998_vbif[] = { static const struct dpu_vbif_cfg sdm845_vbif[] = { { - .name = "vbif_0", .id = VBIF_0, + .name = "vbif_rt", .id = VBIF_RT, .base = 0, .len = 0x1040, .features = BIT(DPU_VBIF_QOS_REMAP), .xin_halt_timeout = 0x4000, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 9f402be55fbf..d3b0ed0a9c6c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -273,11 +273,9 @@ enum dpu_wd_timer { }; enum dpu_vbif { - VBIF_0, - VBIF_1, + VBIF_RT, + VBIF_NRT, VBIF_MAX, - VBIF_RT = VBIF_0, - VBIF_NRT = VBIF_1 }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index a18fb649301c..1305e250b71e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -19,6 +19,18 @@ static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif v return NULL; } +static const char *dpu_vbif_name(enum dpu_vbif idx) +{ + switch (idx) { + case VBIF_RT: + return "VBIF_RT"; + case VBIF_NRT: + return "VBIF_NRT"; + default: + return "??"; + } +} + /** * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt * @vbif: Pointer to hardware vbif driver @@ -50,12 +62,12 @@ static int _dpu_vbif_wait_for_xin_halt(struct dpu_hw_vbif *vbif, u32 xin_id) if (!status) { rc = -ETIMEDOUT; - DPU_ERROR("VBIF %d client %d not halting. TIMEDOUT.\n", - vbif->idx - VBIF_0, xin_id); + DPU_ERROR("%s client %d not halting. TIMEDOUT.\n", + dpu_vbif_name(vbif->idx), xin_id); } else { rc = 0; - DRM_DEBUG_ATOMIC("VBIF %d client %d is halted\n", - vbif->idx - VBIF_0, xin_id); + DRM_DEBUG_ATOMIC("%s client %d is halted\n", + dpu_vbif_name(vbif->idx), xin_id); } return rc; @@ -95,8 +107,8 @@ static void _dpu_vbif_apply_dynamic_ot_limit(struct dpu_hw_vbif *vbif, } } - DRM_DEBUG_ATOMIC("vbif:%d xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n", - vbif->idx - VBIF_0, params->xin_id, + DRM_DEBUG_ATOMIC("%s xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n", + dpu_vbif_name(vbif->idx), params->xin_id, params->width, params->height, params->frame_rate, pps, *ot_lim); } @@ -141,8 +153,8 @@ static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif, } exit: - DRM_DEBUG_ATOMIC("vbif:%d xin:%d ot_lim:%d\n", - vbif->idx - VBIF_0, params->xin_id, ot_lim); + DRM_DEBUG_ATOMIC("%s xin:%d ot_lim:%d\n", + dpu_vbif_name(vbif->idx), params->xin_id, ot_lim); return ot_lim; } @@ -242,8 +254,8 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true); for (i = 0; i < qos_tbl->npriority_lvl; i++) { - DRM_DEBUG_ATOMIC("vbif:%d xin:%d lvl:%d/%d\n", - params->vbif_idx, params->xin_id, i, + DRM_DEBUG_ATOMIC("%s xin:%d lvl:%d/%d\n", + dpu_vbif_name(params->vbif_idx), params->xin_id, i, qos_tbl->priority_lvl[i]); vbif->ops.set_qos_remap(vbif, params->xin_id, i, qos_tbl->priority_lvl[i]); @@ -263,8 +275,8 @@ void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms) if (vbif && vbif->ops.clear_errors) { vbif->ops.clear_errors(vbif, &pnd, &src); if (pnd || src) { - DRM_DEBUG_KMS("VBIF %d: pnd 0x%X, src 0x%X\n", - vbif->idx - VBIF_0, pnd, src); + DRM_DEBUG_KMS("%s: pnd 0x%X, src 0x%X\n", + dpu_vbif_name(vbif->idx), pnd, src); } } } From 1364a4ee9a99f10ebf490aa9be2bb2920989e886 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 20:24:55 +0300 Subject: [PATCH 48/84] drm/msm/dpu: drop unused memory allocation Drop the dpu_cfg variable and corresponding kzalloc, which became unused after changing hw catalog to static configuration. Fixes: de7d480f5e8c ("drm/msm/dpu: make dpu hardware catalog static const") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/498738/ Link: https://lore.kernel.org/r/20220822172455.282923-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 ----- 1 file changed, 5 deletions(-) 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 76b35410be71..27f029fdc682 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1939,11 +1939,6 @@ static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { const struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev) { int i; - struct dpu_mdss_cfg *dpu_cfg; - - dpu_cfg = kzalloc(sizeof(*dpu_cfg), GFP_KERNEL); - if (!dpu_cfg) - return ERR_PTR(-ENOMEM); for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) { if (cfg_handler[i].hw_rev == hw_rev) From fa91ed0c555b0789c24dfa26c169d3f965db656e Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 25 Jul 2022 04:42:42 +0800 Subject: [PATCH 49/84] drm/msm/dpu: Fix comment typo The double `be' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/497853/ Link: https://lore.kernel.org/r/20220724204242.4107-1-wangborong@cdjrlc.com Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 71fe4c505f5b..38aa38ab1568 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -76,7 +76,7 @@ enum { /** * MDP TOP BLOCK features - * @DPU_MDP_PANIC_PER_PIPE Panic configuration needs to be be done per pipe + * @DPU_MDP_PANIC_PER_PIPE Panic configuration needs to be done per pipe * @DPU_MDP_10BIT_SUPPORT, Chipset supports 10 bit pixel formats * @DPU_MDP_BWC, MDSS HW supports Bandwidth compression. * @DPU_MDP_UBWC_1_0, This chipsets supports Universal Bandwidth From 89d529e393199502a951819a51454ddd64e62681 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 16 Aug 2022 15:46:12 +0200 Subject: [PATCH 50/84] drm/msm: Make .remove and .shutdown HW shutdown consistent Drivers' .remove and .shutdown callbacks are executed on different code paths. The former is called when a device is removed from the bus, while the latter is called at system shutdown time to quiesce the device. This means that some overlap exists between the two, because both have to take care of properly shutting down the hardware. But currently the logic used in these two callbacks isn't consistent in msm drivers, which could lead to kernel panic. For example, on .remove the component is deleted and its .unbind callback leads to the hardware being shutdown but only if the DRM device has been marked as registered. That check doesn't exist in the .shutdown logic and this can lead to the driver calling drm_atomic_helper_shutdown() for a DRM device that hasn't been properly initialized. A situation like this can happen if drivers for expected sub-devices fail to probe, since the .bind callback will never be executed. If that is the case, drm_atomic_helper_shutdown() will attempt to take mutexes that are only initialized if drm_mode_config_init() is called during a device bind. This bug was attempted to be fixed in commit 623f279c7781 ("drm/msm: fix shutdown hook in case GPU components failed to bind"), but unfortunately it still happens in some cases as the one mentioned above, i.e: systemd-shutdown[1]: Powering off. kvm: exiting hardware virtualization platform wifi-firmware.0: Removing from iommu group 12 platform video-firmware.0: Removing from iommu group 10 ------------[ cut here ]------------ WARNING: CPU: 6 PID: 1 at drivers/gpu/drm/drm_modeset_lock.c:317 drm_modeset_lock_all_ctx+0x3c4/0x3d0 ... Hardware name: Google CoachZ (rev3+) (DT) pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : drm_modeset_lock_all_ctx+0x3c4/0x3d0 lr : drm_modeset_lock_all_ctx+0x48/0x3d0 sp : ffff80000805bb80 x29: ffff80000805bb80 x28: ffff327c00128000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000001 x24: ffffc95d820ec030 x23: ffff327c00bbd090 x22: ffffc95d8215eca0 x21: ffff327c039c5800 x20: ffff327c039c5988 x19: ffff80000805bbe8 x18: 0000000000000034 x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 x2 : ffff327c00128000 x1 : 0000000000000000 x0 : ffff327c039c59b0 Call trace: drm_modeset_lock_all_ctx+0x3c4/0x3d0 drm_atomic_helper_shutdown+0x70/0x134 msm_drv_shutdown+0x30/0x40 platform_shutdown+0x28/0x40 device_shutdown+0x148/0x350 kernel_power_off+0x38/0x80 __do_sys_reboot+0x288/0x2c0 __arm64_sys_reboot+0x28/0x34 invoke_syscall+0x48/0x114 el0_svc_common.constprop.0+0x44/0xec do_el0_svc+0x2c/0xc0 el0_svc+0x2c/0x84 el0t_64_sync_handler+0x11c/0x150 el0t_64_sync+0x18c/0x190 ---[ end trace 0000000000000000 ]--- Unable to handle kernel NULL pointer dereference at virtual address 0000000000000018 Mem abort info: ESR = 0x0000000096000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x00000004 CM = 0, WnR = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=000000010eab1000 [0000000000000018] pgd=0000000000000000, p4d=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP ... Hardware name: Google CoachZ (rev3+) (DT) pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : ww_mutex_lock+0x28/0x32c lr : drm_modeset_lock_all_ctx+0x1b0/0x3d0 sp : ffff80000805bb50 x29: ffff80000805bb50 x28: ffff327c00128000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000001 x24: 0000000000000018 x23: ffff80000805bc10 x22: ffff327c039c5ad8 x21: ffff327c039c5800 x20: ffff80000805bbe8 x19: 0000000000000018 x18: 0000000000000034 x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 x2 : ffff327c00128000 x1 : 0000000000000000 x0 : 0000000000000018 Call trace: ww_mutex_lock+0x28/0x32c drm_modeset_lock_all_ctx+0x1b0/0x3d0 drm_atomic_helper_shutdown+0x70/0x134 msm_drv_shutdown+0x30/0x40 platform_shutdown+0x28/0x40 device_shutdown+0x148/0x350 kernel_power_off+0x38/0x80 __do_sys_reboot+0x288/0x2c0 __arm64_sys_reboot+0x28/0x34 invoke_syscall+0x48/0x114 el0_svc_common.constprop.0+0x44/0xec do_el0_svc+0x2c/0xc0 el0_svc+0x2c/0x84 el0t_64_sync_handler+0x11c/0x150 el0t_64_sync+0x18c/0x190 Code: aa0103f4 d503201f d2800001 aa0103e3 (c8e37c02) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b Kernel Offset: 0x495d77c00000 from 0xffff800008000000 PHYS_OFFSET: 0xffffcd8500000000 CPU features: 0x800,00c2a015,19801c82 Memory Limit: none ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- Fixes: 9d5cbf5fe46e ("drm/msm: add shutdown support for display platform_driver") Signed-off-by: Javier Martinez Canillas Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/497842/ Link: https://lore.kernel.org/r/20220816134612.916527-1-javierm@redhat.com Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 3403d7da6cae..07f66412533b 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1263,10 +1263,15 @@ void msm_drv_shutdown(struct platform_device *pdev) struct msm_drm_private *priv = platform_get_drvdata(pdev); struct drm_device *drm = priv ? priv->dev : NULL; - if (!priv || !priv->kms) - return; - - drm_atomic_helper_shutdown(drm); + /* + * Shutdown the hw if we're far enough along where things might be on. + * If we run this too early, we'll end up panicking in any variety of + * places. Since we don't register the drm device until late in + * msm_drm_init, drm_dev->registered is used as an indicator that the + * shutdown will be successful. + */ + if (drm && drm->registered) + drm_atomic_helper_shutdown(drm); } static struct platform_driver msm_platform_driver = { From 4bca876458caf7c105ab2ae9d80ff2cc9c60388d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 20:22:04 +0300 Subject: [PATCH 51/84] drm/msm/dpu: drop unused variable from dpu_kms_mdp_snapshot() Follow up the merge of address fields and drop the variable that became unused after the commit 9403f9a42c88 ("drm/msm/dpu: merge base_off with blk_off in struct dpu_hw_blk_reg_map"). Fixes: 9403f9a42c88 ("drm/msm/dpu: merge base_off with blk_off in struct dpu_hw_blk_reg_map") Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/498736/ Link: https://lore.kernel.org/r/20220822172204.281045-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ffdb4fcd3bcc..fd13157568d0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -897,12 +897,10 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k int i; struct dpu_kms *dpu_kms; const struct dpu_mdss_cfg *cat; - struct dpu_hw_mdp *top; dpu_kms = to_dpu_kms(kms); cat = dpu_kms->catalog; - top = dpu_kms->hw_mdp; pm_runtime_get_sync(&dpu_kms->pdev->dev); From aabf9220dfefdffb1f8d9126606f6a525405ba7b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 9 Feb 2022 20:24:56 +0300 Subject: [PATCH 52/84] drm/msm/dpu: rip out master planes support Master/virtual planes were used for multirect support. In preparation to reworking DPU planes, drop support for master planes (which was not used anyway). Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/473146/ Link: https://lore.kernel.org/r/20220209172520.3719906-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 72 ++++----------------- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 13 +--- 6 files changed, 18 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 781dcd3fb283..0dc2d44fe5a9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1235,17 +1235,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, } for (i = 1; i < SSPP_MAX; i++) { - if (pipe_staged[i]) { + if (pipe_staged[i]) dpu_plane_clear_multirect(pipe_staged[i]); - - if (is_dpu_plane_virtual(pipe_staged[i]->plane)) { - DPU_ERROR( - "r1 only virt plane:%d not supported\n", - pipe_staged[i]->plane->base.id); - rc = -EINVAL; - goto end; - } - } } z_pos = -1; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 102c21bb4192..691c471b08c2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -780,8 +780,7 @@ static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp, } struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx, - void __iomem *addr, const struct dpu_mdss_cfg *catalog, - bool is_virtual_pipe) + void __iomem *addr, const struct dpu_mdss_cfg *catalog) { struct dpu_hw_pipe *hw_pipe; const struct dpu_sspp_cfg *cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 78b1bc9e004f..0c95b7e64f6c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -377,11 +377,9 @@ struct dpu_kms; * @idx: Pipe index for which driver object is required * @addr: Mapped register io address of MDP * @catalog : Pointer to mdss catalog data - * @is_virtual_pipe: is this pipe virtual pipe */ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx, - void __iomem *addr, const struct dpu_mdss_cfg *catalog, - bool is_virtual_pipe); + void __iomem *addr, const struct dpu_mdss_cfg *catalog); /** * dpu_hw_sspp_destroy(): Destroys SSPP driver context diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index fd13157568d0..5e6e2626151e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -779,7 +779,7 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)); plane = dpu_plane_init(dev, catalog->sspp[i].id, type, - (1UL << max_crtc_count) - 1, 0); + (1UL << max_crtc_count) - 1); if (IS_ERR(plane)) { DPU_ERROR("dpu_plane_init failed\n"); ret = PTR_ERR(plane); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index a617a3d8b1bc..c7c1360462a7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -91,7 +91,7 @@ enum dpu_plane_qos { /* * struct dpu_plane - local dpu plane structure * @aspace: address space pointer - * @mplane_list: List of multirect planes of the same pipe + * @csc_ptr: Points to dpu_csc_cfg structure to use for current * @catalog: Points to dpu catalog structure * @revalidate: force revalidation of all the plane properties */ @@ -106,8 +106,6 @@ struct dpu_plane { uint32_t color_fill; bool is_error; bool is_rt_pipe; - bool is_virtual; - struct list_head mplane_list; const struct dpu_mdss_cfg *catalog; }; @@ -225,7 +223,7 @@ static void _dpu_plane_calc_clk(struct drm_plane *plane, struct dpu_hw_pipe_cfg static int _dpu_plane_calc_fill_level(struct drm_plane *plane, const struct dpu_format *fmt, u32 src_width) { - struct dpu_plane *pdpu, *tmp; + struct dpu_plane *pdpu; struct dpu_plane_state *pstate; u32 fixed_buff_size; u32 total_fl; @@ -239,19 +237,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, pstate = to_dpu_plane_state(plane->state); fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; - list_for_each_entry(tmp, &pdpu->mplane_list, mplane_list) { - u32 tmp_width; - - if (!tmp->base.state->visible) - continue; - tmp_width = drm_rect_width(&tmp->base.state->src) >> 16; - DPU_DEBUG("plane%d/%d src_width:%d/%d\n", - pdpu->base.base.id, tmp->base.base.id, - src_width, - tmp_width); - src_width = max_t(u32, src_width, - tmp_width); - } + /* FIXME: in multirect case account for the src_width of all the planes */ if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { if (fmt->chroma_sample == DPU_CHROMA_420) { @@ -854,13 +840,8 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane) } done: - if (dpu_plane[R0]->is_virtual) { - pstate[R0]->multirect_index = DPU_SSPP_RECT_1; - pstate[R1]->multirect_index = DPU_SSPP_RECT_0; - } else { - pstate[R0]->multirect_index = DPU_SSPP_RECT_0; - pstate[R1]->multirect_index = DPU_SSPP_RECT_1; - } + pstate[R0]->multirect_index = DPU_SSPP_RECT_0; + pstate[R1]->multirect_index = DPU_SSPP_RECT_1; DPU_DEBUG_PLANE(dpu_plane[R0], "R0: %d - %d\n", pstate[R0]->multirect_mode, pstate[R0]->multirect_index); @@ -1266,19 +1247,13 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) static void _dpu_plane_atomic_disable(struct drm_plane *plane) { - struct dpu_plane *pdpu = to_dpu_plane(plane); struct drm_plane_state *state = plane->state; struct dpu_plane_state *pstate = to_dpu_plane_state(state); - trace_dpu_plane_disable(DRMID(plane), is_dpu_plane_virtual(plane), + trace_dpu_plane_disable(DRMID(plane), false, pstate->multirect_mode); pstate->pending = true; - - if (is_dpu_plane_virtual(plane) && - pdpu->pipe_hw && pdpu->pipe_hw->ops.setup_multirect) - pdpu->pipe_hw->ops.setup_multirect(pdpu->pipe_hw, - DPU_SSPP_RECT_SOLO, DPU_SSPP_MULTIRECT_NONE); } static void dpu_plane_atomic_update(struct drm_plane *plane, @@ -1493,17 +1468,12 @@ enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane) return plane ? to_dpu_plane(plane)->pipe : SSPP_NONE; } -bool is_dpu_plane_virtual(struct drm_plane *plane) -{ - return plane ? to_dpu_plane(plane)->is_virtual : false; -} - /* initialize plane */ struct drm_plane *dpu_plane_init(struct drm_device *dev, uint32_t pipe, enum drm_plane_type type, - unsigned long possible_crtcs, u32 master_plane_id) + unsigned long possible_crtcs) { - struct drm_plane *plane = NULL, *master_plane = NULL; + struct drm_plane *plane = NULL; const uint32_t *format_list; struct dpu_plane *pdpu; struct msm_drm_private *priv = dev->dev_private; @@ -1524,18 +1494,9 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, /* cache local stuff for later */ plane = &pdpu->base; pdpu->pipe = pipe; - pdpu->is_virtual = (master_plane_id != 0); - INIT_LIST_HEAD(&pdpu->mplane_list); - master_plane = drm_plane_find(dev, NULL, master_plane_id); - if (master_plane) { - struct dpu_plane *mpdpu = to_dpu_plane(master_plane); - - list_add_tail(&pdpu->mplane_list, &mpdpu->mplane_list); - } /* initialize underlying h/w driver */ - pdpu->pipe_hw = dpu_hw_sspp_init(pipe, kms->mmio, kms->catalog, - master_plane_id != 0); + pdpu->pipe_hw = dpu_hw_sspp_init(pipe, kms->mmio, kms->catalog); if (IS_ERR(pdpu->pipe_hw)) { DPU_ERROR("[%u]SSPP init failed\n", pipe); ret = PTR_ERR(pdpu->pipe_hw); @@ -1545,14 +1506,8 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, goto clean_sspp; } - if (pdpu->is_virtual) { - format_list = pdpu->pipe_hw->cap->sblk->virt_format_list; - num_formats = pdpu->pipe_hw->cap->sblk->virt_num_formats; - } - else { - format_list = pdpu->pipe_hw->cap->sblk->format_list; - num_formats = pdpu->pipe_hw->cap->sblk->num_formats; - } + format_list = pdpu->pipe_hw->cap->sblk->format_list; + num_formats = pdpu->pipe_hw->cap->sblk->num_formats; ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, format_list, num_formats, @@ -1594,15 +1549,14 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, mutex_init(&pdpu->lock); - DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", plane->name, - pipe, plane->base.id, master_plane_id); + DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, + pipe, plane->base.id); return plane; clean_sspp: if (pdpu && pdpu->pipe_hw) dpu_hw_sspp_destroy(pdpu->pipe_hw); clean_plane: - list_del(&pdpu->mplane_list); kfree(pdpu); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index e1463107a6fc..50e474ddf98a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -64,14 +64,6 @@ struct dpu_multirect_plane_states { */ enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane); -/** - * is_dpu_plane_virtual - check for virtual plane - * @plane: Pointer to DRM plane object - * returns: true - if the plane is virtual - * false - if the plane is primary - */ -bool is_dpu_plane_virtual(struct drm_plane *plane); - /** * dpu_plane_get_ctl_flush - get control flush mask * @plane: Pointer to DRM plane object @@ -99,14 +91,11 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error); * @pipe: dpu hardware pipe identifier * @type: Plane type - PRIMARY/OVERLAY/CURSOR * @possible_crtcs: bitmask of crtc that can be attached to the given pipe - * @master_plane_id: primary plane id of a multirect pipe. 0 value passed for - * a regular plane initialization. A non-zero primary plane - * id will be passed for a virtual pipe initialization. * */ struct drm_plane *dpu_plane_init(struct drm_device *dev, uint32_t pipe, enum drm_plane_type type, - unsigned long possible_crtcs, u32 master_plane_id); + unsigned long possible_crtcs); /** * dpu_plane_validate_multirecti_v2 - validate the multirect planes From e64ad2d224a805d0448c027fcfded00cb0a6f056 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 9 Feb 2022 20:24:57 +0300 Subject: [PATCH 53/84] drm/msm/dpu: do not limit the zpos property Stop limiting zpos property values, we use normalized_zpos anyway. And nothing stops userspace from assigning several planes to a single zpos (it is a userspace bug, but the kernel is forgiving about it). Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/473147/ Link: https://lore.kernel.org/r/20220209172520.3719906-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c7c1360462a7..5135200ce132 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1478,7 +1478,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, struct dpu_plane *pdpu; struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *kms = to_dpu_kms(priv->kms); - int zpos_max = DPU_ZPOS_MAX; uint32_t num_formats; uint32_t supported_rotations; int ret = -EINVAL; @@ -1517,14 +1516,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, pdpu->catalog = kms->catalog; - if (kms->catalog->mixer_count && - kms->catalog->mixer[0].sblk->maxblendstages) { - zpos_max = kms->catalog->mixer[0].sblk->maxblendstages - 1; - if (zpos_max > DPU_STAGE_MAX - DPU_STAGE_0 - 1) - zpos_max = DPU_STAGE_MAX - DPU_STAGE_0 - 1; - } - - ret = drm_plane_create_zpos_property(plane, 0, 0, zpos_max); + ret = drm_plane_create_zpos_property(plane, 0, 0, DPU_ZPOS_MAX); if (ret) DPU_ERROR("failed to install zpos property, rc = %d\n", ret); From 30da01af0d9a7f602925c1dac9414b630ae41f71 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 9 Feb 2022 20:25:01 +0300 Subject: [PATCH 54/84] drm/msm/dpu: inline dpu_plane_get_ctl_flush There is no need to keep a separate function for calling into the ctl if we already know all the details. Inline this function in the dpu_crtc.c Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/473152/ Link: https://lore.kernel.org/r/20220209172520.3719906-7-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 ++++++++------- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 12 ------------ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 9 --------- 3 files changed, 8 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 0dc2d44fe5a9..2d3863514cb5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -412,7 +412,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; - u32 flush_mask; uint32_t stage_idx, lm_idx; int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 }; bool bg_alpha_enable = false; @@ -420,6 +419,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, memset(fetch_active, 0, sizeof(fetch_active)); drm_atomic_crtc_for_each_plane(plane, crtc) { + enum dpu_sspp sspp_idx; + state = plane->state; if (!state) continue; @@ -430,14 +431,14 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, pstate = to_dpu_plane_state(state); fb = state->fb; - dpu_plane_get_ctl_flush(plane, ctl, &flush_mask); - set_bit(dpu_plane_pipe(plane), fetch_active); + sspp_idx = dpu_plane_pipe(plane); + set_bit(sspp_idx, fetch_active); DRM_DEBUG_ATOMIC("crtc %d stage:%d - plane %d sspp %d fb %d\n", crtc->base.id, pstate->stage, plane->base.id, - dpu_plane_pipe(plane) - SSPP_VIG0, + sspp_idx - SSPP_VIG0, state->fb ? state->fb->base.id : -1); format = to_dpu_format(msm_framebuffer_format(pstate->base.fb)); @@ -447,13 +448,13 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, stage_idx = zpos_cnt[pstate->stage]++; stage_cfg->stage[pstate->stage][stage_idx] = - dpu_plane_pipe(plane); + sspp_idx; stage_cfg->multirect_index[pstate->stage][stage_idx] = pstate->multirect_index; trace_dpu_crtc_setup_mixer(DRMID(crtc), DRMID(plane), state, pstate, stage_idx, - dpu_plane_pipe(plane) - SSPP_VIG0, + sspp_idx - SSPP_VIG0, format->base.pixel_format, fb ? fb->modifier : 0); @@ -462,7 +463,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); - mixer[lm_idx].flush_mask |= flush_mask; + mixer[lm_idx].flush_mask |= ctl->ops.get_bitmask_sspp(ctl, sspp_idx); if (bg_alpha_enable && !format->alpha_enable) mixer[lm_idx].mixer_op_mode = 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 5135200ce132..658005f609f4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -850,18 +850,6 @@ done: return 0; } -/** - * dpu_plane_get_ctl_flush - get control flush for the given plane - * @plane: Pointer to drm plane structure - * @ctl: Pointer to hardware control driver - * @flush_sspp: Pointer to sspp flush control word - */ -void dpu_plane_get_ctl_flush(struct drm_plane *plane, struct dpu_hw_ctl *ctl, - u32 *flush_sspp) -{ - *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, dpu_plane_pipe(plane)); -} - static int dpu_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 50e474ddf98a..b7b1b05199c2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -64,15 +64,6 @@ struct dpu_multirect_plane_states { */ enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane); -/** - * dpu_plane_get_ctl_flush - get control flush mask - * @plane: Pointer to DRM plane object - * @ctl: Pointer to control hardware - * @flush_sspp: Pointer to sspp flush control word - */ -void dpu_plane_get_ctl_flush(struct drm_plane *plane, struct dpu_hw_ctl *ctl, - u32 *flush_sspp); - /** * dpu_plane_flush - final plane operations before commit flush * @plane: Pointer to drm plane structure From 3cde792a5583fbb4592f21f9447669aa099d1103 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 9 Feb 2022 20:25:03 +0300 Subject: [PATCH 55/84] drm/msm/dpu: get rid of cached flush_mask Instead of querying the CTL for the flush mask (for SSPP, LM or DSPP), storing the mask in the mixer configuration and then pushing the mask to the CTL, tell CTL to cache the flush in place. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/473159/ Link: https://lore.kernel.org/r/20220209172520.3719906-9-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 26 +++---- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 78 +++++++++------------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 35 ++++++--- 5 files changed, 69 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 2d3863514cb5..13ce321283ff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -463,7 +463,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); - mixer[lm_idx].flush_mask |= ctl->ops.get_bitmask_sspp(ctl, sspp_idx); + mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl, + sspp_idx); if (bg_alpha_enable && !format->alpha_enable) mixer[lm_idx].mixer_op_mode = 0; @@ -497,7 +498,6 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) for (i = 0; i < cstate->num_mixers; i++) { mixer[i].mixer_op_mode = 0; - mixer[i].flush_mask = 0; if (mixer[i].lm_ctl->ops.clear_all_blendstages) mixer[i].lm_ctl->ops.clear_all_blendstages( mixer[i].lm_ctl); @@ -514,17 +514,14 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode); - mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl, + /* stage config flush mask */ + ctl->ops.update_pending_flush_mixer(ctl, mixer[i].hw_lm->idx); - /* stage config flush mask */ - ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask); - - DRM_DEBUG_ATOMIC("lm %d, op_mode 0x%X, ctl %d, flush mask 0x%x\n", + DRM_DEBUG_ATOMIC("lm %d, op_mode 0x%X, ctl %d\n", mixer[i].hw_lm->idx - LM_0, mixer[i].mixer_op_mode, - ctl->idx - CTL_0, - mixer[i].flush_mask); + ctl->idx - CTL_0); ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, &stage_cfg); @@ -768,16 +765,9 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) dspp->ops.setup_pcc(dspp, &cfg); } - mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl, - mixer[i].hw_dspp->idx); - /* stage config flush mask */ - ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask); - - DRM_DEBUG_ATOMIC("lm %d, ctl %d, flush mask 0x%x\n", - mixer[i].hw_lm->idx - DSPP_0, - ctl->idx - CTL_0, - mixer[i].flush_mask); + ctl->ops.update_pending_flush_dspp(ctl, + mixer[i].hw_dspp->idx); } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 9b67645c2574..539b68b1626a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -97,7 +97,6 @@ struct dpu_crtc_mixer { struct dpu_hw_ctl *lm_ctl; struct dpu_hw_dspp *hw_dspp; u32 mixer_op_mode; - u32 flush_mask; }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 7f5dba96b2ff..9c6817b5a194 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1981,7 +1981,6 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc) { struct dpu_hw_mixer_cfg mixer; int i, num_lm; - u32 flush_mask = 0; struct dpu_global_state *global_state; struct dpu_hw_blk *hw_lm[2]; struct dpu_hw_mixer *hw_mixer[2]; @@ -2000,9 +1999,8 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc) for (i = 0; i < num_lm; i++) { hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]); - flush_mask = phys_enc->hw_ctl->ops.get_bitmask_mixer(ctl, hw_mixer[i]->idx); - if (phys_enc->hw_ctl->ops.update_pending_flush) - phys_enc->hw_ctl->ops.update_pending_flush(ctl, flush_mask); + if (phys_enc->hw_ctl->ops.update_pending_flush_mixer) + phys_enc->hw_ctl->ops.update_pending_flush_mixer(ctl, hw_mixer[i]->idx); /* clear all blendstages */ if (phys_enc->hw_ctl->ops.setup_blendstage) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index e12b7fa48a7b..a35ecb6676c8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -150,92 +150,84 @@ static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx) DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask); } -static uint32_t dpu_hw_ctl_get_bitmask_sspp(struct dpu_hw_ctl *ctx, +static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx, enum dpu_sspp sspp) { - uint32_t flushbits = 0; - switch (sspp) { case SSPP_VIG0: - flushbits = BIT(0); + ctx->pending_flush_mask |= BIT(0); break; case SSPP_VIG1: - flushbits = BIT(1); + ctx->pending_flush_mask |= BIT(1); break; case SSPP_VIG2: - flushbits = BIT(2); + ctx->pending_flush_mask |= BIT(2); break; case SSPP_VIG3: - flushbits = BIT(18); + ctx->pending_flush_mask |= BIT(18); break; case SSPP_RGB0: - flushbits = BIT(3); + ctx->pending_flush_mask |= BIT(3); break; case SSPP_RGB1: - flushbits = BIT(4); + ctx->pending_flush_mask |= BIT(4); break; case SSPP_RGB2: - flushbits = BIT(5); + ctx->pending_flush_mask |= BIT(5); break; case SSPP_RGB3: - flushbits = BIT(19); + ctx->pending_flush_mask |= BIT(19); break; case SSPP_DMA0: - flushbits = BIT(11); + ctx->pending_flush_mask |= BIT(11); break; case SSPP_DMA1: - flushbits = BIT(12); + ctx->pending_flush_mask |= BIT(12); break; case SSPP_DMA2: - flushbits = BIT(24); + ctx->pending_flush_mask |= BIT(24); break; case SSPP_DMA3: - flushbits = BIT(25); + ctx->pending_flush_mask |= BIT(25); break; case SSPP_CURSOR0: - flushbits = BIT(22); + ctx->pending_flush_mask |= BIT(22); break; case SSPP_CURSOR1: - flushbits = BIT(23); + ctx->pending_flush_mask |= BIT(23); break; default: break; } - - return flushbits; } -static uint32_t dpu_hw_ctl_get_bitmask_mixer(struct dpu_hw_ctl *ctx, +static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx, enum dpu_lm lm) { - uint32_t flushbits = 0; - switch (lm) { case LM_0: - flushbits = BIT(6); + ctx->pending_flush_mask |= BIT(6); break; case LM_1: - flushbits = BIT(7); + ctx->pending_flush_mask |= BIT(7); break; case LM_2: - flushbits = BIT(8); + ctx->pending_flush_mask |= BIT(8); break; case LM_3: - flushbits = BIT(9); + ctx->pending_flush_mask |= BIT(9); break; case LM_4: - flushbits = BIT(10); + ctx->pending_flush_mask |= BIT(10); break; case LM_5: - flushbits = BIT(20); + ctx->pending_flush_mask |= BIT(20); break; default: - return -EINVAL; + break; } - flushbits |= CTL_FLUSH_MASK_CTL; - - return flushbits; + ctx->pending_flush_mask |= CTL_FLUSH_MASK_CTL; } static void dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx, @@ -294,29 +286,25 @@ static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx, ctx->pending_flush_mask |= BIT(MERGE_3D_IDX); } -static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx, +static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx, enum dpu_dspp dspp) { - uint32_t flushbits = 0; - switch (dspp) { case DSPP_0: - flushbits = BIT(13); + ctx->pending_flush_mask |= BIT(13); break; case DSPP_1: - flushbits = BIT(14); + ctx->pending_flush_mask |= BIT(14); break; case DSPP_2: - flushbits = BIT(15); + ctx->pending_flush_mask |= BIT(15); break; case DSPP_3: - flushbits = BIT(21); + ctx->pending_flush_mask |= BIT(21); break; default: - return 0; + break; } - - return flushbits; } static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us) @@ -685,9 +673,9 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->wait_reset_status = dpu_hw_ctl_wait_reset_status; ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages; ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; - ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp; - ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer; - ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp; + ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp; + ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer; + ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp; if (cap & BIT(DPU_CTL_FETCH_ACTIVE)) ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 7d9ad6a3f9f6..96c012ec8467 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -129,6 +129,32 @@ struct dpu_hw_ctl_ops { void (*update_pending_flush_merge_3d)(struct dpu_hw_ctl *ctx, enum dpu_merge_3d blk); + /** + * OR in the given flushbits to the cached pending_flush_mask + * No effect on hardware + * @ctx : ctl path ctx pointer + * @blk : SSPP block index + */ + void (*update_pending_flush_sspp)(struct dpu_hw_ctl *ctx, + enum dpu_sspp blk); + + /** + * OR in the given flushbits to the cached pending_flush_mask + * No effect on hardware + * @ctx : ctl path ctx pointer + * @blk : LM block index + */ + void (*update_pending_flush_mixer)(struct dpu_hw_ctl *ctx, + enum dpu_lm blk); + + /** + * OR in the given flushbits to the cached pending_flush_mask + * No effect on hardware + * @ctx : ctl path ctx pointer + * @blk : DSPP block index + */ + void (*update_pending_flush_dspp)(struct dpu_hw_ctl *ctx, + enum dpu_dspp blk); /** * Write the value of the pending_flush_mask to hardware * @ctx : ctl path ctx pointer @@ -171,15 +197,6 @@ struct dpu_hw_ctl_ops { */ int (*wait_reset_status)(struct dpu_hw_ctl *ctx); - uint32_t (*get_bitmask_sspp)(struct dpu_hw_ctl *ctx, - enum dpu_sspp blk); - - uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx, - enum dpu_lm blk); - - uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx, - enum dpu_dspp blk); - /** * Set all blend stages to disabled * @ctx : ctl path ctx pointer From c24df3fa039fabfafe251cbdd446e0f0e88d2512 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 22 Jun 2022 17:25:38 -0700 Subject: [PATCH 56/84] drm/msm/dp: Reorganize code to avoid forward declaration Let's move these functions around to avoid having to forward declare dp_ctrl_on_stream_phy_test_report(). Also remove dp_ctrl_reinitialize_mainlink() forward declaration because we're doing that sort of task. Reviewed-by: Kuogee Hsieh Reviewed-by: Dmitry Baryshkov Signed-off-by: Stephen Boyd Patchwork: https://patchwork.freedesktop.org/patch/490771/ Link: https://lore.kernel.org/r/20220623002540.871994-2-swboyd@chromium.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 104 +++++++++++++++---------------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 013ca02e17cb..7c8e74cd01f6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1238,8 +1238,6 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl, return -ETIMEDOUT; } -static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl); - static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, int *training_step) { @@ -1535,38 +1533,6 @@ end: return ret; } -static int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl); - -static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - - if (!ctrl->link->phy_params.phy_test_pattern_sel) { - drm_dbg_dp(ctrl->drm_dev, - "no test pattern selected by sink\n"); - return ret; - } - - /* - * The global reset will need DP link related clocks to be - * 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; - } - - ret = dp_ctrl_on_link(&ctrl->dp_ctrl); - if (!ret) - ret = dp_ctrl_on_stream_phy_test_report(&ctrl->dp_ctrl); - else - DRM_ERROR("failed to enable DP link controller\n"); - - return ret; -} - static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) { bool success = false; @@ -1619,6 +1585,56 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) return success; } +static int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl) +{ + int ret; + struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + + ret = dp_ctrl_enable_stream_clocks(ctrl); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + return ret; + } + + dp_ctrl_send_phy_test_pattern(ctrl); + + return 0; +} + +static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + if (!ctrl->link->phy_params.phy_test_pattern_sel) { + drm_dbg_dp(ctrl->drm_dev, + "no test pattern selected by sink\n"); + return ret; + } + + /* + * The global reset will need DP link related clocks to be + * 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; + } + + ret = dp_ctrl_on_link(&ctrl->dp_ctrl); + if (!ret) + ret = dp_ctrl_on_stream_phy_test_report(&ctrl->dp_ctrl); + else + DRM_ERROR("failed to enable DP link controller\n"); + + return ret; +} + void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; @@ -1816,26 +1832,6 @@ static int dp_ctrl_link_retrain(struct dp_ctrl_private *ctrl) return dp_ctrl_setup_main_link(ctrl, &training_step); } -static int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl) -{ - int ret; - struct dp_ctrl_private *ctrl; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - - ret = dp_ctrl_enable_stream_clocks(ctrl); - if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); - return ret; - } - - dp_ctrl_send_phy_test_pattern(ctrl); - - return 0; -} - int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) { int ret = 0; From 64d6058233b7e4234fd543639f9d006740531a54 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 22 Jun 2022 17:25:39 -0700 Subject: [PATCH 57/84] drm/msm/dp: Remove pixel_rate from struct dp_ctrl This struct member is stored to in the function that calls the function which uses it. That's possible with a function argument instead of storing to a struct member. Pass the pixel_rate as an argument instead to simplify the code. Note that dp_ctrl_link_maintenance() was storing the pixel_rate but never using it so we just remove the assignment from there. Cc: Kuogee Hsieh Signed-off-by: Stephen Boyd Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/490772/ Link: https://lore.kernel.org/r/20220623002540.871994-3-swboyd@chromium.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 60 ++++++++++++-------------------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 - 2 files changed, 22 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 7c8e74cd01f6..22b239bf2c0f 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1356,25 +1356,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) if (ret) DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); - drm_dbg_dp(ctrl->drm_dev, "link rate=%d pixel_clk=%d\n", - ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate); - - return ret; -} - -static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - - dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", - ctrl->dp_ctrl.pixel_rate * 1000); - - ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); - if (ret) - DRM_ERROR("Unabled to start pixel clocks. ret=%d\n", ret); - - drm_dbg_dp(ctrl->drm_dev, "link rate=%d pixel_clk=%d\n", - ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate); + drm_dbg_dp(ctrl->drm_dev, "link rate=%d\n", ctrl->link->link_params.rate); return ret; } @@ -1518,8 +1500,6 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl) ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; - ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - ret = dp_ctrl_setup_main_link(ctrl, &training_step); if (ret) goto end; @@ -1589,14 +1569,16 @@ static int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl) { int ret; struct dp_ctrl_private *ctrl; + unsigned long pixel_rate; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + 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_enable_stream_clocks(ctrl); + ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + DRM_ERROR("Unable to start pixel clocks. ret=%d\n", ret); return ret; } @@ -1705,11 +1687,12 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) { int rc = 0; struct dp_ctrl_private *ctrl; - u32 rate = 0; + u32 rate; int link_train_max_retries = 5; u32 const phy_cts_pixel_clk_khz = 148500; u8 link_status[DP_LINK_STATUS_SIZE]; unsigned int training_step; + unsigned long pixel_rate; if (!dp_ctrl) return -EINVAL; @@ -1717,25 +1700,24 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, 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); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { drm_dbg_dp(ctrl->drm_dev, "using phy test link parameters\n"); - if (!ctrl->panel->dp_mode.drm_mode.clock) - ctrl->dp_ctrl.pixel_rate = phy_cts_pixel_clk_khz; + if (!pixel_rate) + pixel_rate = phy_cts_pixel_clk_khz; } else { ctrl->link->link_params.rate = rate; ctrl->link->link_params.num_lanes = ctrl->panel->link_info.num_lanes; - ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; } - drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%d\n", + drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n", ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, - ctrl->dp_ctrl.pixel_rate); - + pixel_rate); rc = dp_ctrl_enable_mainlink_clocks(ctrl); if (rc) @@ -1837,6 +1819,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) int ret = 0; bool mainlink_ready = false; struct dp_ctrl_private *ctrl; + unsigned long pixel_rate; unsigned long pixel_rate_orig; if (!dp_ctrl) @@ -1844,15 +1827,14 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock; - pixel_rate_orig = ctrl->dp_ctrl.pixel_rate; if (dp_ctrl->wide_bus_en) - ctrl->dp_ctrl.pixel_rate >>= 1; + pixel_rate >>= 1; - drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%d\n", + drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n", ctrl->link->link_params.rate, - ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate); + ctrl->link->link_params.num_lanes, pixel_rate); if (!dp_power_clk_status(ctrl->power, DP_CTRL_PM)) { /* link clk is off */ ret = dp_ctrl_enable_mainlink_clocks(ctrl); @@ -1862,9 +1844,11 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train) } } - ret = dp_ctrl_enable_stream_clocks(ctrl); + 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); if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + DRM_ERROR("Unable to start pixel clocks. ret=%d\n", ret); goto end; } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index b563e2e3bfe5..9f29734af81c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -16,7 +16,6 @@ struct dp_ctrl { bool orientation; atomic_t aborted; - u32 pixel_rate; bool wide_bus_en; }; From 62b060e06e2af9c00fe59445fdf78b3fc7525650 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 22 Jun 2022 17:25:40 -0700 Subject: [PATCH 58/84] drm/msm/dp: Get rid of dp_ctrl_on_stream_phy_test_report() This API isn't really more than a couple lines now that we don't store the pixel_rate to the struct member. Inline it into the caller. Cc: Kuogee Hsieh Signed-off-by: Stephen Boyd Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/490775/ Link: https://lore.kernel.org/r/20220623002540.871994-4-swboyd@chromium.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 46 +++++++++++++------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 22b239bf2c0f..3854c9f1f7e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1565,36 +1565,15 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) return success; } -static int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl) -{ - int ret; - struct dp_ctrl_private *ctrl; - unsigned long pixel_rate; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_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); - if (ret) { - DRM_ERROR("Unable to start pixel clocks. ret=%d\n", ret); - return ret; - } - - dp_ctrl_send_phy_test_pattern(ctrl); - - return 0; -} - static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) { - int ret = 0; + int ret; + unsigned long pixel_rate; if (!ctrl->link->phy_params.phy_test_pattern_sel) { drm_dbg_dp(ctrl->drm_dev, "no test pattern selected by sink\n"); - return ret; + return 0; } /* @@ -1609,12 +1588,23 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) } ret = dp_ctrl_on_link(&ctrl->dp_ctrl); - if (!ret) - ret = dp_ctrl_on_stream_phy_test_report(&ctrl->dp_ctrl); - else + if (ret) { DRM_ERROR("failed to enable DP link controller\n"); + return ret; + } - return ret; + 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); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + return ret; + } + + dp_ctrl_send_phy_test_pattern(ctrl); + + return 0; } void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl) From fd713be04095dec8c13acd41c70e640571015bba Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 21:48:58 +0300 Subject: [PATCH 59/84] dt-bindings: msm/dp: mark vdda supplies as deprecated The commit 85936d4f3815 ("phy: qcom-qmp: add regulator_set_load to dp phy") moved setting regulator load to the DP PHY driver (QMP). Then, the commit 7516351bebc1 ("drm/msm/dp: delete vdda regulator related functions from eDP/DP controller") removed support for VDDA supplies from the DP controller driver. Mark these properties as deprecated and drop them from the example. Acked-by: Rob Herring Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Patchwork: https://patchwork.freedesktop.org/patch/498748/ Link: https://lore.kernel.org/r/20220822184900.307160-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../devicetree/bindings/display/msm/dp-controller.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 94bc6e1b6451..391910d91e43 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -76,8 +76,10 @@ properties: "#sound-dai-cells": const: 0 - vdda-0p9-supply: true - vdda-1p2-supply: true + vdda-0p9-supply: + deprecated: true + vdda-1p2-supply: + deprecated: true ports: $ref: /schemas/graph.yaml#/properties/ports @@ -140,9 +142,6 @@ examples: power-domains = <&rpmhpd SC7180_CX>; - vdda-0p9-supply = <&vdda_usb_ss_dp_core>; - vdda-1p2-supply = <&vdda_usb_ss_dp_1p2>; - ports { #address-cells = <1>; #size-cells = <0>; From 33468f4d64bcba854b554ea4628c618aa28b7335 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 21:48:59 +0300 Subject: [PATCH 60/84] dt-bindings: msm/dp: add missing properties Document missing definitions for opp-table (DP controller OPPs), aux-bus (DP AUX BUS) and data-lanes (DP/eDP lanes mapping) properties. Reviewed-by: Stephen Boyd Acked-by: Krzysztof Kozlowski Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/498750/ Link: https://lore.kernel.org/r/20220822184900.307160-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../bindings/display/msm/dp-controller.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 391910d91e43..52cbf00df0ba 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -70,9 +70,21 @@ properties: operating-points-v2: maxItems: 1 + opp-table: true + power-domains: maxItems: 1 + aux-bus: + $ref: /schemas/display/dp-aux-bus.yaml# + + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 4 + items: + maximum: 3 + "#sound-dai-cells": const: 0 From 122b17f32e35b9e7cae8feca258658d6ed5de4c3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 21:49:00 +0300 Subject: [PATCH 61/84] dt-bindings: msm/dp: handle DP vs eDP difference The #sound-dai-cells property should be used only for DP controllers. It doesn't make sense for eDP, there is no support for audio output. The aux-bus should not be used for DP controllers. Also p1 MMIO region should be used only for DP controllers. Take care of these differences. Reviewed-by: Rob Herring Signed-off-by: Dmitry Baryshkov Reviewed-by: Stephen Boyd Patchwork: https://patchwork.freedesktop.org/patch/498751/ Link: https://lore.kernel.org/r/20220822184900.307160-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../bindings/display/msm/dp-controller.yaml | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 52cbf00df0ba..f2515af8256f 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -24,6 +24,7 @@ properties: - qcom,sm8350-dp reg: + minItems: 4 items: - description: ahb register block - description: aux register block @@ -112,10 +113,33 @@ required: - clock-names - phys - phy-names - - "#sound-dai-cells" - power-domains - ports +allOf: + # AUX BUS does not exist on DP controllers + # Audio output also is present only on DP output + # p1 regions is present on DP, but not on eDP + - if: + properties: + compatible: + contains: + enum: + - qcom,sc7280-edp + - qcom,sc8180x-edp + then: + properties: + "#sound-dai-cells": false + reg: + maxItems: 4 + else: + properties: + aux-bus: false + reg: + minItems: 5 + required: + - "#sound-dai-cells" + additionalProperties: false examples: From e40261156829d66ec4644243bc31e1831733638f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 23 Aug 2022 14:23:02 -0700 Subject: [PATCH 62/84] drm/msm/dp: Silence inconsistent indent warning Build robots complain smatch warnings: drivers/gpu/drm/msm/dp/dp_link.c:969 dp_link_process_link_status_update() warn: inconsistent indenting Fix it along with a trailing space from the same commit. Cc: Kuogee Hsieh Fixes: ea530388e64b ("drm/msm/dp: skip checking LINK_STATUS_UPDATED bit") Reported-by: kernel test robot Signed-off-by: Stephen Boyd Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/498954/ Link: https://lore.kernel.org/r/20220823212302.1744145-1-swboyd@chromium.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_link.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 36f0af02749f..36bb6191d2f0 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -786,7 +786,7 @@ static int dp_link_process_link_training_request(struct dp_link_private *link) link->request.test_lane_count); link->dp_link.link_params.num_lanes = link->request.test_lane_count; - link->dp_link.link_params.rate = + link->dp_link.link_params.rate = drm_dp_bw_code_to_link_rate(link->request.test_link_rate); return 0; @@ -965,8 +965,7 @@ static int dp_link_process_link_status_update(struct dp_link_private *link) if (channel_eq_done && clock_recovery_done) return -EINVAL; - - return 0; + return 0; } /** From aa0bff10af1c4b92e6b56e3e1b7f81c660d3ba78 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 24 Aug 2022 13:15:50 -0700 Subject: [PATCH 63/84] drm/msm/dp: correct 1.62G link rate at dp_catalog_ctrl_config_msa() At current implementation there is an extra 0 at 1.62G link rate which cause no correct pixel_div selected for 1.62G link rate to calculate mvid and nvid. This patch delete the extra 0 to have mvid and nvid be calculated correctly. Changes in v2: -- fix Fixes tag's text Changes in v3: -- fix misspelling of "Reviewed-by" Fixes: 937f941ca06f ("drm/msm/dp: Use qmp phy for DP PLL and PHY") Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/499328/ Link: https://lore.kernel.org/r/1661372150-3764-1-git-send-email-quic_khsieh@quicinc.com [DB: rewrapped commit message] Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 7257515871a9..676279d0ca8d 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -431,7 +431,7 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, if (rate == link_rate_hbr3) pixel_div = 6; - else if (rate == 1620000 || rate == 270000) + else if (rate == 162000 || rate == 270000) pixel_div = 2; else if (rate == link_rate_hbr2) pixel_div = 4; From dcfde8f6b16535124f48f3ee60cb9714401d7c5b Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:24 +0200 Subject: [PATCH 64/84] drm/msm/dsi/phy: Reindent and reflow multiline function calls The commit 613cbd1da3c9 ("drm/msm/dsi: use devm_clk_*register to registe DSI PHY clocks") introduced the devm_ prefix to clk_hw registration calls, without updating the indentation of the arguments on the following lines. Similarly commit e55b3fbbbbc8 ("drm/msm/dsi: drop PLL accessor functions") moved from pll_write to dsi_phy_write without updating the indentation of followup arguments either. Preparing for a series that heavily touches the clk calls, reflow and reindent function calls that are adhering to an 80-char column limit by spanning multiple lines. Where function names are very long the arguments are indented with a fixed number of two tab characters instead of aligning with the opening parenthesis of the function call. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491931/ Link: https://lore.kernel.org/r/20220629225331.357308-5-marijn.suijten@somainline.org [DB: adjusted commit message to make checkpatch happy] Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 96 +++++++++---------- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 9 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 73 +++++++------- .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 63 ++++++------ drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 84 ++++++++-------- 5 files changed, 161 insertions(+), 164 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 08b015ea1b1e..56892036e419 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -188,19 +188,19 @@ static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll, struct dsi_pll_config * pr_debug("SSC is enabled\n"); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_LOW_1, - config->ssc_stepsize & 0xff); + config->ssc_stepsize & 0xff); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_STEPSIZE_HIGH_1, - config->ssc_stepsize >> 8); + config->ssc_stepsize >> 8); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_LOW_1, - config->ssc_div_per & 0xff); + config->ssc_div_per & 0xff); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_PER_HIGH_1, - config->ssc_div_per >> 8); + config->ssc_div_per >> 8); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_LOW_1, - config->ssc_adj_per & 0xff); + config->ssc_adj_per & 0xff); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_DIV_ADJPER_HIGH_1, - config->ssc_adj_per >> 8); + config->ssc_adj_per >> 8); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_SSC_CONTROL, - SSC_EN | (config->ssc_center ? SSC_CENTER : 0)); + SSC_EN | (config->ssc_center ? SSC_CENTER : 0)); } } @@ -215,16 +215,19 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll) dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, - 0xba); - dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c); + 0xba); + dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, + 0x0c); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_OUTDIV, 0x00); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CORE_OVERRIDE, 0x00); - dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08); + dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, + 0x08); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x08); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_BAND_SET_RATE_1, 0xc0); - dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa); + dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, + 0xfa); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, - 0x4c); + 0x4c); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PFILT, 0x29); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_IFILT, 0x3f); @@ -236,18 +239,18 @@ static void dsi_pll_commit(struct dsi_pll_10nm *pll, struct dsi_pll_config *conf dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_DECIMAL_DIV_START_1, - config->decimal_div_start); + config->decimal_div_start); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_LOW_1, - config->frac_div_start & 0xff); + config->frac_div_start & 0xff); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_MID_1, - (config->frac_div_start & 0xff00) >> 8); + (config->frac_div_start & 0xff00) >> 8); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_FRAC_DIV_START_HIGH_1, - (config->frac_div_start & 0x30000) >> 16); + (config->frac_div_start & 0x30000) >> 16); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCKDET_RATE_1, 64); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_PLL_LOCK_DELAY, 0x06); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CMODE, 0x10); dsi_phy_write(base + REG_DSI_10nm_PHY_PLL_CLOCK_INVERTERS, - config->pll_clock_inverters); + config->pll_clock_inverters); } static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, @@ -306,7 +309,7 @@ static void dsi_pll_disable_pll_bias(struct dsi_pll_10nm *pll) dsi_phy_write(pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0); dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0, - data & ~BIT(5)); + data & ~BIT(5)); ndelay(250); } @@ -315,7 +318,7 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_10nm *pll) u32 data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0); dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CTRL_0, - data | BIT(5)); + data | BIT(5)); dsi_phy_write(pll->phy->pll_base + REG_DSI_10nm_PHY_PLL_SYSTEM_MUXES, 0xc0); ndelay(250); } @@ -326,7 +329,7 @@ static void dsi_pll_disable_global_clk(struct dsi_pll_10nm *pll) data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1); dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, - data & ~BIT(5)); + data & ~BIT(5)); } static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll) @@ -335,7 +338,7 @@ static void dsi_pll_enable_global_clk(struct dsi_pll_10nm *pll) data = dsi_phy_read(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1); dsi_phy_write(pll->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, - data | BIT(5)); + data | BIT(5)); } static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw) @@ -356,7 +359,7 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw) /* Start PLL */ dsi_phy_write(pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, - 0x01); + 0x01); /* * ensure all PLL configurations are written prior to checking @@ -378,10 +381,10 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw) dsi_pll_enable_global_clk(pll_10nm->slave); dsi_phy_write(pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, - 0x01); + 0x01); if (pll_10nm->slave) dsi_phy_write(pll_10nm->slave->phy->base + - REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01); + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x01); error: return rc; @@ -486,7 +489,7 @@ static void dsi_10nm_pll_save_state(struct msm_dsi_phy *phy) u32 cmn_clk_cfg0, cmn_clk_cfg1; cached->pll_out_div = dsi_phy_read(pll_10nm->phy->pll_base + - REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE); + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE); cached->pll_out_div &= 0x3; cmn_clk_cfg0 = dsi_phy_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0); @@ -515,7 +518,7 @@ static int dsi_10nm_pll_restore_state(struct msm_dsi_phy *phy) dsi_phy_write(pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, val); dsi_phy_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, - cached->bit_clk_div | (cached->pix_clk_div << 4)); + cached->bit_clk_div | (cached->pix_clk_div << 4)); val = dsi_phy_read(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1); val &= ~0x3; @@ -598,11 +601,10 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, - parent, CLK_SET_RATE_PARENT, - pll_10nm->phy->pll_base + - REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, - 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); + hw = devm_clk_hw_register_divider(dev, clk_name, parent, + CLK_SET_RATE_PARENT, pll_10nm->phy->pll_base + + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, + 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -613,11 +615,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov /* BIT CLK: DIV_CTRL_3_0 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, - pll_10nm->phy->base + - REG_DSI_10nm_PHY_CMN_CLK_CFG0, - 0, 4, CLK_DIVIDER_ONE_BASED, - &pll_10nm->postdiv_lock); + CLK_SET_RATE_PARENT, + pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, + 0, 4, CLK_DIVIDER_ONE_BASED, &pll_10nm->postdiv_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -628,7 +628,7 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, 8); + CLK_SET_RATE_PARENT, 1, 8); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -640,7 +640,7 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 2); + 0, 1, 2); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -650,7 +650,7 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 4); + 0, 1, 4); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -663,11 +663,11 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, - ((const char *[]){ - parent, parent2, parent3, parent4 - }), 4, 0, pll_10nm->phy->base + - REG_DSI_10nm_PHY_CMN_CLK_CFG1, - 0, 2, 0, NULL); + ((const char *[]){ + parent, parent2, parent3, parent4, + }), 4, 0, pll_10nm->phy->base + + REG_DSI_10nm_PHY_CMN_CLK_CFG1, + 0, 2, 0, NULL); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -677,11 +677,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - 0, pll_10nm->phy->base + - REG_DSI_10nm_PHY_CMN_CLK_CFG0, - 4, 4, CLK_DIVIDER_ONE_BASED, - &pll_10nm->postdiv_lock); + hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, + pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, + 4, 4, CLK_DIVIDER_ONE_BASED, &pll_10nm->postdiv_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 8199c53567f4..055b48cf8008 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -711,7 +711,7 @@ static int dsi_14nm_pll_restore_state(struct msm_dsi_phy *phy) cached_state->vco_rate, 0); if (ret) { DRM_DEV_ERROR(&pll_14nm->phy->pdev->dev, - "restore vco rate failed. ret=%d\n", ret); + "restore vco rate failed. ret=%d\n", ret); return ret; } @@ -837,7 +837,7 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov /* DSI Byte clock = VCO_CLK / N1 / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, 8); + CLK_SET_RATE_PARENT, 1, 8); if (IS_ERR(hw)) return PTR_ERR(hw); @@ -952,7 +952,8 @@ static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy, if (msm_dsi_dphy_timing_calc_v2(timing, clk_req)) { DRM_DEV_ERROR(&phy->pdev->dev, - "%s: D-PHY timing calculation failed\n", __func__); + "%s: D-PHY timing calculation failed\n", + __func__); return -EINVAL; } @@ -1005,7 +1006,7 @@ static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy, ret = dsi_14nm_set_usecase(phy); if (ret) { DRM_DEV_ERROR(&phy->pdev->dev, "%s: set pll usecase failed, %d\n", - __func__, ret); + __func__, ret); return ret; } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 48eab80b548e..ef04bb630c5d 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -104,7 +104,7 @@ static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm) * reset bit off and back on. */ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, - DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1); + DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1); dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1); } @@ -201,9 +201,9 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate, dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2, - DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2)); + DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2)); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3, - DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3)); + DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3)); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00); /* Add hardware recommended delay for correct PLL configuration */ @@ -316,12 +316,12 @@ static int _dsi_pll_28nm_vco_prepare_hpm(struct dsi_pll_28nm *pll_28nm) for (i = 0; i < 2; i++) { /* DSI Uniphy lock detect setting */ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, - 0x0c, 100); + 0x0c, 100); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d); /* poll for PLL ready status */ - locked = pll_28nm_poll_for_ready(pll_28nm, - max_reads, timeout_us); + locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, + timeout_us); if (locked) break; @@ -508,11 +508,11 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy) } dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, - cached_state->postdiv3); + cached_state->postdiv3); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, - cached_state->postdiv1); + cached_state->postdiv1); dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG, - cached_state->byte_mux); + cached_state->byte_mux); return 0; } @@ -547,28 +547,26 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->phy->id); snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, - parent1, CLK_SET_RATE_PARENT, - pll_28nm->phy->pll_base + - REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, + hw = devm_clk_hw_register_divider(dev, clk_name, parent1, + CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base + + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, 0, 4, 0, NULL); if (IS_ERR(hw)) return PTR_ERR(hw); snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, - parent1, CLK_SET_RATE_PARENT, - 1, 2); + hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, + CLK_SET_RATE_PARENT, 1, 2); if (IS_ERR(hw)) return PTR_ERR(hw); snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id); snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, - parent1, 0, pll_28nm->phy->pll_base + + hw = devm_clk_hw_register_divider(dev, clk_name, parent1, 0, + pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, - 0, 8, 0, NULL); + 0, 8, 0, NULL); if (IS_ERR(hw)) return PTR_ERR(hw); provided_clocks[DSI_PIXEL_PLL_CLK] = hw; @@ -578,16 +576,16 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, ((const char *[]){ - parent1, parent2 + parent1, parent2, }), 2, CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base + - REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL); + REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL); if (IS_ERR(hw)) return PTR_ERR(hw); snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id); snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, - parent1, CLK_SET_RATE_PARENT, 1, 4); + hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, + CLK_SET_RATE_PARENT, 1, 4); if (IS_ERR(hw)) return PTR_ERR(hw); provided_clocks[DSI_BYTE_PLL_CLK] = hw; @@ -627,31 +625,31 @@ static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy, void __iomem *base = phy->base; dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_0, - DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); + DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_1, - DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); + DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_2, - DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); + DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); if (timing->clk_zero & BIT(8)) dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_3, - DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8); + DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_4, - DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); + DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_5, - DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); + DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_6, - DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); + DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_7, - DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); + DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_8, - DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); + DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_9, - DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | - DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); + DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | + DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_10, - DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); + DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_11, - DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); + DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); } static void dsi_28nm_phy_regulator_enable_dcdc(struct msm_dsi_phy *phy) @@ -713,7 +711,8 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, if (msm_dsi_dphy_timing_calc(timing, clk_req)) { DRM_DEV_ERROR(&phy->pdev->dev, - "%s: D-PHY timing calculation failed\n", __func__); + "%s: D-PHY timing calculation failed\n", + __func__); return -EINVAL; } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index fc56cdcc9ad6..af630b8eb9f3 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -104,29 +104,29 @@ static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate, fb_divider = (temp * VCO_PREF_DIV_RATIO) / val; fb_divider = fb_divider / 2 - 1; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1, - fb_divider & 0xff); + fb_divider & 0xff); val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2); val |= (fb_divider >> 8) & 0x07; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2, - val); + val); val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3); val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3, - val); + val); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6, - 0xf); + 0xf); val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8); val |= 0x7 << 4; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, - val); + val); return 0; } @@ -206,7 +206,7 @@ static int dsi_pll_28nm_vco_prepare(struct clk_hw *hw) /* enable the PLL */ dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, - DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE); + DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE); locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us); @@ -367,16 +367,16 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy) cached_state->vco_rate, 0); if (ret) { DRM_DEV_ERROR(&pll_28nm->phy->pdev->dev, - "restore vco rate failed. ret=%d\n", ret); + "restore vco rate failed. ret=%d\n", ret); return ret; } dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10, - cached_state->postdiv3); + cached_state->postdiv3); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9, - cached_state->postdiv2); + cached_state->postdiv2); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, - cached_state->postdiv1); + cached_state->postdiv1); return 0; } @@ -446,10 +446,10 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1); /* DIV3 */ - hw = devm_clk_hw_register_divider(dev, clk_name, - parent_name, 0, pll_28nm->phy->pll_base + + hw = devm_clk_hw_register_divider(dev, clk_name, parent_name, 0, + pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10, - 0, 8, 0, NULL); + 0, 8, 0, NULL); if (IS_ERR(hw)) return PTR_ERR(hw); provided_clocks[DSI_PIXEL_PLL_CLK] = hw; @@ -489,29 +489,29 @@ static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy, void __iomem *base = phy->base; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0, - DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); + DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1, - DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); + DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2, - DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); + DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3, 0x0); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4, - DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); + DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5, - DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); + DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6, - DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); + DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7, - DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); + DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8, - DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); + DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9, - DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | - DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); + DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | + DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10, - DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); + DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11, - DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); + DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); } static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy) @@ -523,7 +523,7 @@ static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy) dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 1); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4, - 0x100); + 0x100); } static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy) @@ -544,7 +544,7 @@ static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy) int i = 5000; dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG, - 0x3); + 0x3); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2, 0x0); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1, 0x5a); @@ -577,11 +577,11 @@ static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy) dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i), 0x45); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i), 0x00); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i), - 0x00); + 0x00); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i), - 0x01); + 0x01); dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i), - 0x66); + 0x66); } dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0, 0x40); @@ -602,7 +602,8 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, if (msm_dsi_dphy_timing_calc(timing, clk_req)) { DRM_DEV_ERROR(&phy->pdev->dev, - "%s: D-PHY timing calculation failed\n", __func__); + "%s: D-PHY timing calculation failed\n", + __func__); return -EINVAL; } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 66ed1919a1db..36f1e6a40d9c 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -176,19 +176,19 @@ static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *c pr_debug("SSC is enabled\n"); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1, - config->ssc_stepsize & 0xff); + config->ssc_stepsize & 0xff); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1, - config->ssc_stepsize >> 8); + config->ssc_stepsize >> 8); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1, - config->ssc_div_per & 0xff); + config->ssc_div_per & 0xff); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1, - config->ssc_div_per >> 8); + config->ssc_div_per >> 8); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1, - config->ssc_adj_per & 0xff); + config->ssc_adj_per & 0xff); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1, - config->ssc_adj_per >> 8); + config->ssc_adj_per >> 8); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL, - SSC_EN | (config->ssc_center ? SSC_CENTER : 0)); + SSC_EN | (config->ssc_center ? SSC_CENTER : 0)); } } @@ -208,7 +208,7 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) } dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1, - analog_controls_five_1); + analog_controls_five_1); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03); @@ -245,17 +245,20 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi void __iomem *base = pll->phy->pll_base; dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12); - dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, config->decimal_div_start); + dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, + config->decimal_div_start); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, - config->frac_div_start & 0xff); + config->frac_div_start & 0xff); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, - (config->frac_div_start & 0xff00) >> 8); + (config->frac_div_start & 0xff00) >> 8); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, - (config->frac_div_start & 0x30000) >> 16); + (config->frac_div_start & 0x30000) >> 16); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06); - dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, pll->phy->cphy_mode ? 0x00 : 0x10); - dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, config->pll_clock_inverters); + dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, + pll->phy->cphy_mode ? 0x00 : 0x10); + dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, + config->pll_clock_inverters); } static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, @@ -341,7 +344,7 @@ static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll) data = dsi_phy_read(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); dsi_phy_write(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, - data | BIT(5) | BIT(4)); + data | BIT(5) | BIT(4)); } static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll) @@ -500,7 +503,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy) u32 cmn_clk_cfg0, cmn_clk_cfg1; cached->pll_out_div = dsi_phy_read(pll_7nm->phy->pll_base + - REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); cached->pll_out_div &= 0x3; cmn_clk_cfg0 = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0); @@ -529,7 +532,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy) dsi_phy_write(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val); dsi_phy_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, - cached->bit_clk_div | (cached->pix_clk_div << 4)); + cached->bit_clk_div | (cached->pix_clk_div << 4)); val = dsi_phy_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); val &= ~0x3; @@ -612,11 +615,10 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id); snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, - parent, CLK_SET_RATE_PARENT, - pll_7nm->phy->pll_base + - REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, - 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); + hw = devm_clk_hw_register_divider(dev, clk_name, parent, + CLK_SET_RATE_PARENT, pll_7nm->phy->pll_base + + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, + 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -627,11 +629,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide /* BIT CLK: DIV_CTRL_3_0 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, - pll_7nm->phy->base + - REG_DSI_7nm_PHY_CMN_CLK_CFG0, - 0, 4, CLK_DIVIDER_ONE_BASED, - &pll_7nm->postdiv_lock); + CLK_SET_RATE_PARENT, + pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, + 0, 4, CLK_DIVIDER_ONE_BASED, &pll_7nm->postdiv_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -642,8 +642,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, - pll_7nm->phy->cphy_mode ? 7 : 8); + CLK_SET_RATE_PARENT, 1, + pll_7nm->phy->cphy_mode ? 7 : 8); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -655,7 +655,7 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 2); + 0, 1, 2); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -689,11 +689,11 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, - ((const char *[]){ + ((const char *[]){ parent, parent2, - }), 2, 0, pll_7nm->phy->base + + }), 2, 0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, - 0, 1, 0, NULL); + 0, 1, 0, NULL); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -705,11 +705,9 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - 0, pll_7nm->phy->base + - REG_DSI_7nm_PHY_CMN_CLK_CFG0, - 4, 4, CLK_DIVIDER_ONE_BASED, - &pll_7nm->postdiv_lock); + hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, + pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, + 4, 4, CLK_DIVIDER_ONE_BASED, &pll_7nm->postdiv_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -841,7 +839,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, ret = msm_dsi_dphy_timing_calc_v4(timing, clk_req); if (ret) { DRM_DEV_ERROR(&phy->pdev->dev, - "%s: PHY timing calculation failed\n", __func__); + "%s: PHY timing calculation failed\n", __func__); return -EINVAL; } @@ -960,10 +958,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, - timing->shared_timings.clk_pre); + timing->shared_timings.clk_pre); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->clk_prepare); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, - timing->shared_timings.clk_post); + timing->shared_timings.clk_post); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04); @@ -982,9 +980,9 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12, - timing->shared_timings.clk_pre); + timing->shared_timings.clk_pre); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13, - timing->shared_timings.clk_post); + timing->shared_timings.clk_post); } /* DSI lane settings */ From 158ce9cb945b34c78ebd49dbb2c7401ca728c809 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:25 +0200 Subject: [PATCH 65/84] drm/msm/dsi_phy_28nm_8960: Use stack memory for temporary clock names The clock names formatted into the hw_clk's init structure are only used for the duration of the registration function where they are kstrdup'ed, making it unnecessary to keep the allocations alive for the duration of the device (through devm). Just like the other DSI PHY PLL clock trees, use a stack-local char array and save on memory outside of the pll_28nm_register function. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491917/ Link: https://lore.kernel.org/r/20220629225331.357308-6-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index af630b8eb9f3..24bac401b210 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -383,7 +383,7 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy) static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks) { - char *clk_name, *parent_name, *vco_name; + char clk_name[32], parent_name[32], vco_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", @@ -404,18 +404,6 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov if (!bytediv) return -ENOMEM; - vco_name = devm_kzalloc(dev, 32, GFP_KERNEL); - if (!vco_name) - return -ENOMEM; - - parent_name = devm_kzalloc(dev, 32, GFP_KERNEL); - if (!parent_name) - return -ENOMEM; - - clk_name = devm_kzalloc(dev, 32, GFP_KERNEL); - if (!clk_name) - return -ENOMEM; - snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); vco_init.name = vco_name; From e139dfa008365ec6255cd8ae56e1e5d7511f92f7 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:26 +0200 Subject: [PATCH 66/84] drm/msm/dsi/phy: Replace hardcoded char-array length with sizeof() Now that the last DSI PHY PLL driver (dsi_phy_28nm_8960) has been converted to use a simple stack-local char-array instead of a devm_kzalloc heap allocation we can safely call sizeof() on every string variable (that's now a sized array instead of a pointer) passed into snprintf instead of hardcoding the size. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491920/ Link: https://lore.kernel.org/r/20220629225331.357308-7-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 36 +++++++++---------- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 18 +++++----- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 24 ++++++------- .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 8 ++--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 34 +++++++++--------- 5 files changed, 60 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 56892036e419..8bd7b97b1b9b 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -591,15 +591,15 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov DBG("DSI%d", pll_10nm->phy->id); - snprintf(vco_name, 32, "dsi%dvco_clk", pll_10nm->phy->id); + snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_10nm->phy->id); pll_10nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_10nm->clk_hw); if (ret) return ret; - snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_divider(dev, clk_name, parent, CLK_SET_RATE_PARENT, pll_10nm->phy->pll_base + @@ -610,8 +610,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov goto fail; } - snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_bit_clk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); /* BIT CLK: DIV_CTRL_3_0 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent, @@ -623,8 +623,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov goto fail; } - snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_byteclk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, @@ -636,8 +636,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov provided_clocks[DSI_BYTE_PLL_CLK] = hw; - snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2); @@ -646,8 +646,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov goto fail; } - snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 4); @@ -656,11 +656,11 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov goto fail; } - snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->phy->id); - snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); - snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_10nm->phy->id); - snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); + snprintf(parent2, sizeof(parent2), "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); + snprintf(parent3, sizeof(parent3), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); + snprintf(parent4, sizeof(parent4), "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, ((const char *[]){ @@ -673,8 +673,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov goto fail; } - snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->phy->id); - snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_dsiclk", pll_10nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pclk_mux", pll_10nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 055b48cf8008..e10ba1b09b2f 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -816,15 +816,15 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov DBG("DSI%d", pll_14nm->phy->id); - snprintf(vco_name, 32, "dsi%dvco_clk", pll_14nm->phy->id); + snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_14nm->phy->id); pll_14nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_14nm->clk_hw); if (ret) return ret; - snprintf(clk_name, 32, "dsi%dn1_postdiv_clk", pll_14nm->phy->id); - snprintf(parent, 32, "dsi%dvco_clk", pll_14nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_14nm->phy->id); /* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */ hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, @@ -832,8 +832,8 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov if (IS_ERR(hw)) return PTR_ERR(hw); - snprintf(clk_name, 32, "dsi%dpllbyte", pll_14nm->phy->id); - snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_14nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); /* DSI Byte clock = VCO_CLK / N1 / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, @@ -843,8 +843,8 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov provided_clocks[DSI_BYTE_PLL_CLK] = hw; - snprintf(clk_name, 32, "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); - snprintf(parent, 32, "dsi%dn1_postdiv_clk", pll_14nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); /* * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider @@ -854,8 +854,8 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov if (IS_ERR(hw)) return PTR_ERR(hw); - snprintf(clk_name, 32, "dsi%dpll", pll_14nm->phy->id); - snprintf(parent, 32, "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_14nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); /* DSI pixel clock = VCO_CLK / N1 / 2 / N2 * This is the output of N2 post-divider, bits 4-7 in diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index ef04bb630c5d..7d3cabeca743 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -539,14 +539,14 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov else vco_init.ops = &clk_ops_dsi_pll_28nm_vco_hpm; - snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_28nm->phy->id); pll_28nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_28nm->clk_hw); if (ret) return ret; - snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->phy->id); - snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%danalog_postdiv_clk", pll_28nm->phy->id); + snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); hw = devm_clk_hw_register_divider(dev, clk_name, parent1, CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, @@ -554,15 +554,15 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov if (IS_ERR(hw)) return PTR_ERR(hw); - snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); - snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); + snprintf(parent1, sizeof(parent1), "dsi%danalog_postdiv_clk", pll_28nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, CLK_SET_RATE_PARENT, 1, 2); if (IS_ERR(hw)) return PTR_ERR(hw); - snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id); - snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id); + snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); hw = devm_clk_hw_register_divider(dev, clk_name, parent1, 0, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, @@ -571,9 +571,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov return PTR_ERR(hw); provided_clocks[DSI_PIXEL_PLL_CLK] = hw; - snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->phy->id); - snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->phy->id); - snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dbyte_mux", pll_28nm->phy->id); + snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(parent2, sizeof(parent2), "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, ((const char *[]){ parent1, parent2, @@ -582,8 +582,8 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov if (IS_ERR(hw)) return PTR_ERR(hw); - snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id); - snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id); + snprintf(parent1, sizeof(parent1), "dsi%dbyte_mux", pll_28nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, CLK_SET_RATE_PARENT, 1, 4); if (IS_ERR(hw)) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index 24bac401b210..3deb306f4cc4 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -404,7 +404,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov if (!bytediv) return -ENOMEM; - snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_28nm->phy->id); vco_init.name = vco_name; pll_28nm->clk_hw.init = &vco_init; @@ -417,8 +417,8 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov bytediv->hw.init = &bytediv_init; bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9; - snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); - snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id + 1); + snprintf(parent_name, sizeof(parent_name), "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id + 1); bytediv_init.name = clk_name; bytediv_init.ops = &clk_bytediv_ops; @@ -432,7 +432,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov return ret; provided_clocks[DSI_BYTE_PLL_CLK] = &bytediv->hw; - snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1); + snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id + 1); /* DIV3 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent_name, 0, pll_28nm->phy->pll_base + diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 36f1e6a40d9c..6a58dd62bac5 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -605,15 +605,15 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide DBG("DSI%d", pll_7nm->phy->id); - snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->phy->id); + snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_7nm->phy->id); pll_7nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_7nm->clk_hw); if (ret) return ret; - snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_7nm->phy->id); hw = devm_clk_hw_register_divider(dev, clk_name, parent, CLK_SET_RATE_PARENT, pll_7nm->phy->pll_base + @@ -624,8 +624,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide goto fail; } - snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_bit_clk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); /* BIT CLK: DIV_CTRL_3_0 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent, @@ -637,8 +637,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide goto fail; } - snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_byteclk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, @@ -651,8 +651,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide provided_clocks[DSI_BYTE_PLL_CLK] = hw; - snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2); @@ -661,8 +661,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide goto fail; } - snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); if (pll_7nm->phy->cphy_mode) hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 2, 7); @@ -682,11 +682,11 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide data = dsi_phy_read(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data | 3); - snprintf(parent, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); } else { - snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id); - snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id); - snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); + snprintf(parent2, sizeof(parent2), "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); hw = devm_clk_hw_register_mux(dev, clk_name, ((const char *[]){ @@ -699,10 +699,10 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide goto fail; } - snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id); + snprintf(parent, sizeof(parent), "dsi%d_pclk_mux", pll_7nm->phy->id); } - snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, From 2db57ba10656b1eb97104da9fd48d9fd7a387d62 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:27 +0200 Subject: [PATCH 67/84] drm/msm/dsi_phy_28nm_8960: Replace parent names with clk_hw pointers parent_hw pointers are easier to manage and cheaper to use than repeatedly formatting the parent name and subsequently leaving the clk framework to perform lookups based on that name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491929/ Link: https://lore.kernel.org/r/20220629225331.357308-8-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index 3deb306f4cc4..69c1b2d8333c 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -383,7 +383,7 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy) static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks) { - char clk_name[32], parent_name[32], vco_name[32]; + char clk_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", @@ -404,8 +404,8 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov if (!bytediv) return -ENOMEM; - snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_28nm->phy->id); - vco_init.name = vco_name; + snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_28nm->phy->id); + vco_init.name = clk_name; pll_28nm->clk_hw.init = &vco_init; @@ -417,13 +417,14 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov bytediv->hw.init = &bytediv_init; bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9; - snprintf(parent_name, sizeof(parent_name), "dsi%dvco_clk", pll_28nm->phy->id); snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id + 1); bytediv_init.name = clk_name; bytediv_init.ops = &clk_bytediv_ops; bytediv_init.flags = CLK_SET_RATE_PARENT; - bytediv_init.parent_names = (const char * const *) &parent_name; + bytediv_init.parent_hws = (const struct clk_hw*[]){ + &pll_28nm->clk_hw, + }; bytediv_init.num_parents = 1; /* DIV2 */ @@ -434,8 +435,8 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id + 1); /* DIV3 */ - hw = devm_clk_hw_register_divider(dev, clk_name, parent_name, 0, - pll_28nm->phy->pll_base + + hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + &pll_28nm->clk_hw, 0, pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10, 0, 8, 0, NULL); if (IS_ERR(hw)) From 09186dd9da124b09cfe6573cd808c91d2865f65c Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:28 +0200 Subject: [PATCH 68/84] drm/msm/dsi_phy_28nm: Replace parent names with clk_hw pointers parent_hw pointers are easier to manage and cheaper to use than repeatedly formatting the parent name and subsequently leaving the clk framework to perform lookups based on that name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491925/ Link: https://lore.kernel.org/r/20220629225331.357308-9-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 50 ++++++++++------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 7d3cabeca743..04411fefb808 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -519,17 +519,17 @@ static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy) static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks) { - char clk_name[32], parent1[32], parent2[32], vco_name[32]; + char clk_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", .name = "xo", }, .num_parents = 1, - .name = vco_name, + .name = clk_name, .flags = CLK_IGNORE_UNUSED, }; struct device *dev = &pll_28nm->phy->pdev->dev; - struct clk_hw *hw; + struct clk_hw *hw, *analog_postdiv, *indirect_path_div2, *byte_mux; int ret; DBG("%d", pll_28nm->phy->id); @@ -539,32 +539,30 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov else vco_init.ops = &clk_ops_dsi_pll_28nm_vco_hpm; - snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_28nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_28nm->phy->id); pll_28nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_28nm->clk_hw); if (ret) return ret; snprintf(clk_name, sizeof(clk_name), "dsi%danalog_postdiv_clk", pll_28nm->phy->id); - snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, parent1, - CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base + + analog_postdiv = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + &pll_28nm->clk_hw, CLK_SET_RATE_PARENT, + pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, 0, 4, 0, NULL); - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(analog_postdiv)) + return PTR_ERR(analog_postdiv); snprintf(clk_name, sizeof(clk_name), "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); - snprintf(parent1, sizeof(parent1), "dsi%danalog_postdiv_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, - CLK_SET_RATE_PARENT, 1, 2); - if (IS_ERR(hw)) - return PTR_ERR(hw); + indirect_path_div2 = devm_clk_hw_register_fixed_factor_parent_hw(dev, + clk_name, analog_postdiv, CLK_SET_RATE_PARENT, 1, 2); + if (IS_ERR(indirect_path_div2)) + return PTR_ERR(indirect_path_div2); snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id); - snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, parent1, 0, - pll_28nm->phy->pll_base + + hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + &pll_28nm->clk_hw, 0, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, 0, 8, 0, NULL); if (IS_ERR(hw)) @@ -572,20 +570,18 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov provided_clocks[DSI_PIXEL_PLL_CLK] = hw; snprintf(clk_name, sizeof(clk_name), "dsi%dbyte_mux", pll_28nm->phy->id); - snprintf(parent1, sizeof(parent1), "dsi%dvco_clk", pll_28nm->phy->id); - snprintf(parent2, sizeof(parent2), "dsi%dindirect_path_div2_clk", pll_28nm->phy->id); - hw = devm_clk_hw_register_mux(dev, clk_name, - ((const char *[]){ - parent1, parent2, + byte_mux = devm_clk_hw_register_mux_parent_hws(dev, clk_name, + ((const struct clk_hw *[]){ + &pll_28nm->clk_hw, + indirect_path_div2, }), 2, CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL); - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(byte_mux)) + return PTR_ERR(byte_mux); snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id); - snprintf(parent1, sizeof(parent1), "dsi%dbyte_mux", pll_28nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent1, - CLK_SET_RATE_PARENT, 1, 4); + hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name, + byte_mux, CLK_SET_RATE_PARENT, 1, 4); if (IS_ERR(hw)) return PTR_ERR(hw); provided_clocks[DSI_BYTE_PLL_CLK] = hw; From 9fcb91201a23f8b8c861d9a29c8487dddddef234 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:29 +0200 Subject: [PATCH 69/84] drm/msm/dsi_phy_14nm: Replace parent names with clk_hw pointers parent_hw pointers are easier to manage and cheaper to use than repeatedly formatting the parent name and subsequently leaving the clk framework to perform lookups based on that name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491921/ Link: https://lore.kernel.org/r/20220629225331.357308-10-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 40 ++++++++++------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index e10ba1b09b2f..1a855351654c 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -764,14 +764,14 @@ static int dsi_14nm_set_usecase(struct msm_dsi_phy *phy) static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm *pll_14nm, const char *name, - const char *parent_name, + const struct clk_hw *parent_hw, unsigned long flags, u8 shift) { struct dsi_pll_14nm_postdiv *pll_postdiv; struct device *dev = &pll_14nm->phy->pdev->dev; struct clk_init_data postdiv_init = { - .parent_names = (const char *[]) { parent_name }, + .parent_hws = (const struct clk_hw *[]) { parent_hw }, .num_parents = 1, .name = name, .flags = flags, @@ -800,23 +800,23 @@ static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm *pll_14nm, static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **provided_clocks) { - char clk_name[32], parent[32], vco_name[32]; + char clk_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", }, .num_parents = 1, - .name = vco_name, + .name = clk_name, .flags = CLK_IGNORE_UNUSED, .ops = &clk_ops_dsi_pll_14nm_vco, }; struct device *dev = &pll_14nm->phy->pdev->dev; - struct clk_hw *hw; + struct clk_hw *hw, *n1_postdiv, *n1_postdivby2; int ret; DBG("DSI%d", pll_14nm->phy->id); - snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_14nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_14nm->phy->id); pll_14nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_14nm->clk_hw); @@ -824,48 +824,46 @@ static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **prov return ret; snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_14nm->phy->id); /* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */ - hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, - CLK_SET_RATE_PARENT, 0); - if (IS_ERR(hw)) - return PTR_ERR(hw); + n1_postdiv = pll_14nm_postdiv_register(pll_14nm, clk_name, + &pll_14nm->clk_hw, CLK_SET_RATE_PARENT, 0); + if (IS_ERR(n1_postdiv)) + return PTR_ERR(n1_postdiv); snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_14nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); /* DSI Byte clock = VCO_CLK / N1 / 8 */ - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, 8); + hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name, + n1_postdiv, CLK_SET_RATE_PARENT, 1, 8); if (IS_ERR(hw)) return PTR_ERR(hw); provided_clocks[DSI_BYTE_PLL_CLK] = hw; snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dn1_postdiv_clk", pll_14nm->phy->id); /* * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider * on the way. Don't let it set parent. */ - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 2); - if (IS_ERR(hw)) - return PTR_ERR(hw); + n1_postdivby2 = devm_clk_hw_register_fixed_factor_parent_hw(dev, + clk_name, n1_postdiv, 0, 1, 2); + if (IS_ERR(n1_postdivby2)) + return PTR_ERR(n1_postdivby2); snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_14nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dn1_postdivby2_clk", pll_14nm->phy->id); /* DSI pixel clock = VCO_CLK / N1 / 2 / N2 * This is the output of N2 post-divider, bits 4-7 in * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent. */ - hw = pll_14nm_postdiv_register(pll_14nm, clk_name, parent, 0, 4); + hw = pll_14nm_postdiv_register(pll_14nm, clk_name, n1_postdivby2, + 0, 4); if (IS_ERR(hw)) return PTR_ERR(hw); - provided_clocks[DSI_PIXEL_PLL_CLK] = hw; + provided_clocks[DSI_PIXEL_PLL_CLK] = hw; return 0; } From 12fc7b1a758b3f7a640b225ce80545ff8cbb3e4b Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:30 +0200 Subject: [PATCH 70/84] drm/msm/dsi_phy_10nm: Replace parent names with clk_hw pointers parent_hw pointers are easier to manage and cheaper to use than repeatedly formatting the parent name and subsequently leaving the clk framework to perform lookups based on that name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491923/ Link: https://lore.kernel.org/r/20220629225331.357308-11-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 77 ++++++++++------------ 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index 8bd7b97b1b9b..ae57f95edf63 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -574,24 +574,24 @@ static int dsi_10nm_set_usecase(struct msm_dsi_phy *phy) */ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **provided_clocks) { - char clk_name[32], parent[32], vco_name[32]; - char parent2[32], parent3[32], parent4[32]; + char clk_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", }, .num_parents = 1, - .name = vco_name, + .name = clk_name, .flags = CLK_IGNORE_UNUSED, .ops = &clk_ops_dsi_pll_10nm_vco, }; struct device *dev = &pll_10nm->phy->pdev->dev; - struct clk_hw *hw; + struct clk_hw *hw, *pll_out_div, *pll_bit, *pll_by_2_bit; + struct clk_hw *pll_post_out_div, *pclk_mux; int ret; DBG("DSI%d", pll_10nm->phy->id); - snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_10nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_10nm->phy->id); pll_10nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_10nm->clk_hw); @@ -599,36 +599,34 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov return ret; snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_10nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, pll_10nm->phy->pll_base + + pll_out_div = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + &pll_10nm->clk_hw, CLK_SET_RATE_PARENT, + pll_10nm->phy->pll_base + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + if (IS_ERR(pll_out_div)) { + ret = PTR_ERR(pll_out_div); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_bit_clk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); /* BIT CLK: DIV_CTRL_3_0 */ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, + pll_bit = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + pll_out_div, CLK_SET_RATE_PARENT, pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, 0, 4, CLK_DIVIDER_ONE_BASED, &pll_10nm->postdiv_lock); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + if (IS_ERR(pll_bit)) { + ret = PTR_ERR(pll_bit); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_byteclk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, 8); + hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name, + pll_bit, CLK_SET_RATE_PARENT, 1, 8); if (IS_ERR(hw)) { ret = PTR_ERR(hw); goto fail; @@ -637,48 +635,43 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm, struct clk_hw **prov provided_clocks[DSI_BYTE_PLL_CLK] = hw; snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 2); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + pll_by_2_bit = devm_clk_hw_register_fixed_factor_parent_hw(dev, + clk_name, pll_bit, 0, 1, 2); + if (IS_ERR(pll_by_2_bit)) { + ret = PTR_ERR(pll_by_2_bit); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 4); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + pll_post_out_div = devm_clk_hw_register_fixed_factor_parent_hw(dev, + clk_name, pll_out_div, 0, 1, 4); + if (IS_ERR(pll_post_out_div)) { + ret = PTR_ERR(pll_post_out_div); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_10nm->phy->id); - snprintf(parent2, sizeof(parent2), "dsi%d_pll_by_2_bit_clk", pll_10nm->phy->id); - snprintf(parent3, sizeof(parent3), "dsi%d_pll_out_div_clk", pll_10nm->phy->id); - snprintf(parent4, sizeof(parent4), "dsi%d_pll_post_out_div_clk", pll_10nm->phy->id); - hw = devm_clk_hw_register_mux(dev, clk_name, - ((const char *[]){ - parent, parent2, parent3, parent4, + pclk_mux = devm_clk_hw_register_mux_parent_hws(dev, clk_name, + ((const struct clk_hw *[]){ + pll_bit, + pll_by_2_bit, + pll_out_div, + pll_post_out_div, }), 4, 0, pll_10nm->phy->base + - REG_DSI_10nm_PHY_CMN_CLK_CFG1, - 0, 2, 0, NULL); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + REG_DSI_10nm_PHY_CMN_CLK_CFG1, 0, 2, 0, NULL); + if (IS_ERR(pclk_mux)) { + ret = PTR_ERR(pclk_mux); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_dsiclk", pll_10nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pclk_mux", pll_10nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, - pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, + hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name, pclk_mux, + 0, pll_10nm->phy->base + REG_DSI_10nm_PHY_CMN_CLK_CFG0, 4, 4, CLK_DIVIDER_ONE_BASED, &pll_10nm->postdiv_lock); if (IS_ERR(hw)) { ret = PTR_ERR(hw); From fa374ddba2997f4a0506612d9e18fea3c0d009b3 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:31 +0200 Subject: [PATCH 71/84] drm/msm/dsi_phy_7nm: Replace parent names with clk_hw pointers parent_hw pointers are easier to manage and cheaper to use than repeatedly formatting the parent name and subsequently leaving the clk framework to perform lookups based on that name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/491927/ Link: https://lore.kernel.org/r/20220629225331.357308-12-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 70 +++++++++++------------ 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 6a58dd62bac5..c1710a8824e7 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -588,24 +588,24 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy) */ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provided_clocks) { - char clk_name[32], parent[32], vco_name[32]; - char parent2[32]; + char clk_name[32]; struct clk_init_data vco_init = { .parent_data = &(const struct clk_parent_data) { .fw_name = "ref", }, .num_parents = 1, - .name = vco_name, + .name = clk_name, .flags = CLK_IGNORE_UNUSED, .ops = &clk_ops_dsi_pll_7nm_vco, }; struct device *dev = &pll_7nm->phy->pdev->dev; - struct clk_hw *hw; + struct clk_hw *hw, *pll_out_div, *pll_bit, *pll_by_2_bit; + struct clk_hw *pll_post_out_div, *phy_pll_out_dsi_parent; int ret; DBG("DSI%d", pll_7nm->phy->id); - snprintf(vco_name, sizeof(vco_name), "dsi%dvco_clk", pll_7nm->phy->id); + snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_7nm->phy->id); pll_7nm->clk_hw.init = &vco_init; ret = devm_clk_hw_register(dev, &pll_7nm->clk_hw); @@ -613,36 +613,34 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide return ret; snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%dvco_clk", pll_7nm->phy->id); - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, pll_7nm->phy->pll_base + + pll_out_div = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + &pll_7nm->clk_hw, CLK_SET_RATE_PARENT, + pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + if (IS_ERR(pll_out_div)) { + ret = PTR_ERR(pll_out_div); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_bit_clk", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); /* BIT CLK: DIV_CTRL_3_0 */ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, - CLK_SET_RATE_PARENT, + pll_bit = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + pll_out_div, CLK_SET_RATE_PARENT, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, 0, 4, CLK_DIVIDER_ONE_BASED, &pll_7nm->postdiv_lock); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + if (IS_ERR(pll_bit)) { + ret = PTR_ERR(pll_bit); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_byteclk", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - CLK_SET_RATE_PARENT, 1, + hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name, + pll_bit, CLK_SET_RATE_PARENT, 1, pll_7nm->phy->cphy_mode ? 7 : 8); if (IS_ERR(hw)) { ret = PTR_ERR(hw); @@ -652,24 +650,24 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide provided_clocks[DSI_BYTE_PLL_CLK] = hw; snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, - 0, 1, 2); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + pll_by_2_bit = devm_clk_hw_register_fixed_factor_parent_hw(dev, + clk_name, pll_bit, 0, 1, 2); + if (IS_ERR(pll_by_2_bit)) { + ret = PTR_ERR(pll_by_2_bit); goto fail; } snprintf(clk_name, sizeof(clk_name), "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_out_div_clk", pll_7nm->phy->id); if (pll_7nm->phy->cphy_mode) - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 2, 7); + pll_post_out_div = devm_clk_hw_register_fixed_factor_parent_hw( + dev, clk_name, pll_out_div, 0, 2, 7); else - hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 4); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); + pll_post_out_div = devm_clk_hw_register_fixed_factor_parent_hw( + dev, clk_name, pll_out_div, 0, 1, 4); + if (IS_ERR(pll_post_out_div)) { + ret = PTR_ERR(pll_post_out_div); goto fail; } @@ -682,15 +680,14 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide data = dsi_phy_read(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data | 3); - snprintf(parent, sizeof(parent), "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id); + phy_pll_out_dsi_parent = pll_post_out_div; } else { snprintf(clk_name, sizeof(clk_name), "dsi%d_pclk_mux", pll_7nm->phy->id); - snprintf(parent, sizeof(parent), "dsi%d_pll_bit_clk", pll_7nm->phy->id); - snprintf(parent2, sizeof(parent2), "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id); - hw = devm_clk_hw_register_mux(dev, clk_name, - ((const char *[]){ - parent, parent2, + hw = devm_clk_hw_register_mux_parent_hws(dev, clk_name, + ((const struct clk_hw *[]){ + pll_bit, + pll_by_2_bit, }), 2, 0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, 0, 1, 0, NULL); @@ -699,13 +696,14 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide goto fail; } - snprintf(parent, sizeof(parent), "dsi%d_pclk_mux", pll_7nm->phy->id); + phy_pll_out_dsi_parent = hw; } snprintf(clk_name, sizeof(clk_name), "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id); /* PIX CLK DIV : DIV_CTRL_7_4*/ - hw = devm_clk_hw_register_divider(dev, clk_name, parent, 0, + hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name, + phy_pll_out_dsi_parent, 0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, 4, 4, CLK_DIVIDER_ONE_BASED, &pll_7nm->postdiv_lock); if (IS_ERR(hw)) { From 0587e9aa0493980dd39602ac78ee9b25406f06e7 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:50 -0700 Subject: [PATCH 72/84] drm/msm/dsi: Don't set a load before disabling a regulator As of commit 5451781dadf8 ("regulator: core: Only count load for enabled consumers"), a load isn't counted for a disabled regulator. That means all the code in the DSI driver to specify and set loads before disabling a regulator is not actually doing anything useful. Let's remove it. It should be noted that all of the loads set that were being specified were pointless noise anyway. The only use for this number is to pick between low power and high power modes of regulators. Regulators appear to do this changeover at loads on the order of 10000 uA. You would need a lot of clients of the same rail for that 100 uA number to count for anything. Note that now that we get rid of the setting of the load at disable time, we can just set the load once when we first get the regulator and then forget it. It should also be noted that the regulator functions regulator_bulk_enable() and regulator_set_load() already print error messages when they encounter problems so while moving things around we get rid of some extra error prints. Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496320/ Link: https://lore.kernel.org/r/20220804073608.v4.3.If1f94fbbdb7c1d0fb3961de61483a851ad1971a7@changeid Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 1 - drivers/gpu/drm/msm/dsi/dsi_cfg.c | 52 +++++++------- drivers/gpu/drm/msm/dsi/dsi_host.c | 71 ++++--------------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 52 ++------------ drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 4 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 6 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 4 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 6 +- .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 2 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 6 +- 10 files changed, 60 insertions(+), 144 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index df46cdda1b43..56996ac9e58a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -37,7 +37,6 @@ enum msm_dsi_phy_usecase { struct dsi_reg_entry { char name[32]; int enable_load; - int disable_load; }; struct dsi_reg_config { diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 72c018e26f47..901d6fd53800 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -14,9 +14,9 @@ static const struct msm_dsi_config apq8064_dsi_cfg = { .reg_cfg = { .num = 3, .regs = { - {"vdda", 100000, 100}, /* 1.2 V */ - {"avdd", 10000, 100}, /* 3.0 V */ - {"vddio", 100000, 100}, /* 1.8 V */ + {"vdda", 100000}, /* 1.2 V */ + {"avdd", 10000}, /* 3.0 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .bus_clk_names = dsi_v2_bus_clk_names, @@ -34,9 +34,9 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = { .reg_cfg = { .num = 3, .regs = { - {"vdd", 150000, 100}, /* 3.0 V */ - {"vdda", 100000, 100}, /* 1.2 V */ - {"vddio", 100000, 100}, /* 1.8 V */ + {"vdd", 150000}, /* 3.0 V */ + {"vdda", 100000}, /* 1.2 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .bus_clk_names = dsi_6g_bus_clk_names, @@ -54,8 +54,8 @@ static const struct msm_dsi_config msm8916_dsi_cfg = { .reg_cfg = { .num = 2, .regs = { - {"vdda", 100000, 100}, /* 1.2 V */ - {"vddio", 100000, 100}, /* 1.8 V */ + {"vdda", 100000}, /* 1.2 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .bus_clk_names = dsi_8916_bus_clk_names, @@ -73,8 +73,8 @@ static const struct msm_dsi_config msm8976_dsi_cfg = { .reg_cfg = { .num = 2, .regs = { - {"vdda", 100000, 100}, /* 1.2 V */ - {"vddio", 100000, 100}, /* 1.8 V */ + {"vdda", 100000}, /* 1.2 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .bus_clk_names = dsi_8976_bus_clk_names, @@ -88,12 +88,12 @@ static const struct msm_dsi_config msm8994_dsi_cfg = { .reg_cfg = { .num = 6, .regs = { - {"vdda", 100000, 100}, /* 1.25 V */ - {"vddio", 100000, 100}, /* 1.8 V */ - {"vcca", 10000, 100}, /* 1.0 V */ - {"vdd", 100000, 100}, /* 1.8 V */ - {"lab_reg", -1, -1}, - {"ibb_reg", -1, -1}, + {"vdda", 100000}, /* 1.25 V */ + {"vddio", 100000}, /* 1.8 V */ + {"vcca", 10000}, /* 1.0 V */ + {"vdd", 100000}, /* 1.8 V */ + {"lab_reg", -1}, + {"ibb_reg", -1}, }, }, .bus_clk_names = dsi_6g_bus_clk_names, @@ -111,9 +111,9 @@ static const struct msm_dsi_config msm8996_dsi_cfg = { .reg_cfg = { .num = 3, .regs = { - {"vdda", 18160, 1 }, /* 1.25 V */ - {"vcca", 17000, 32 }, /* 0.925 V */ - {"vddio", 100000, 100 },/* 1.8 V */ + {"vdda", 18160}, /* 1.25 V */ + {"vcca", 17000}, /* 0.925 V */ + {"vddio", 100000},/* 1.8 V */ }, }, .bus_clk_names = dsi_8996_bus_clk_names, @@ -131,8 +131,8 @@ static const struct msm_dsi_config msm8998_dsi_cfg = { .reg_cfg = { .num = 2, .regs = { - {"vdd", 367000, 16 }, /* 0.9 V */ - {"vdda", 62800, 2 }, /* 1.2 V */ + {"vdd", 367000}, /* 0.9 V */ + {"vdda", 62800}, /* 1.2 V */ }, }, .bus_clk_names = dsi_msm8998_bus_clk_names, @@ -150,7 +150,7 @@ static const struct msm_dsi_config sdm660_dsi_cfg = { .reg_cfg = { .num = 1, .regs = { - {"vdda", 12560, 4 }, /* 1.2 V */ + {"vdda", 12560}, /* 1.2 V */ }, }, .bus_clk_names = dsi_sdm660_bus_clk_names, @@ -172,7 +172,7 @@ static const struct msm_dsi_config sdm845_dsi_cfg = { .reg_cfg = { .num = 1, .regs = { - {"vdda", 21800, 4 }, /* 1.2 V */ + {"vdda", 21800}, /* 1.2 V */ }, }, .bus_clk_names = dsi_sdm845_bus_clk_names, @@ -186,7 +186,7 @@ static const struct msm_dsi_config sc7180_dsi_cfg = { .reg_cfg = { .num = 1, .regs = { - {"vdda", 21800, 4 }, /* 1.2 V */ + {"vdda", 21800}, /* 1.2 V */ }, }, .bus_clk_names = dsi_sc7180_bus_clk_names, @@ -204,7 +204,7 @@ static const struct msm_dsi_config sc7280_dsi_cfg = { .reg_cfg = { .num = 1, .regs = { - {"vdda", 8350, 0 }, /* 1.2 V */ + {"vdda", 8350}, /* 1.2 V */ }, }, .bus_clk_names = dsi_sc7280_bus_clk_names, @@ -222,7 +222,7 @@ static const struct msm_dsi_config qcm2290_dsi_cfg = { .reg_cfg = { .num = 1, .regs = { - {"vdda", 21800, 4 }, /* 1.2 V */ + {"vdda", 21800}, /* 1.2 V */ }, }, .bus_clk_names = dsi_qcm2290_bus_clk_names, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 15e108be1901..99e21d38c7da 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -205,9 +205,6 @@ static inline void dsi_write(struct msm_dsi_host *msm_host, u32 reg, u32 data) msm_writel(data, msm_host->ctrl_base + reg); } -static int dsi_host_regulator_enable(struct msm_dsi_host *msm_host); -static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host); - static const struct msm_dsi_cfg_handler *dsi_get_config( struct msm_dsi_host *msm_host) { @@ -258,56 +255,6 @@ static inline struct msm_dsi_host *to_msm_dsi_host(struct mipi_dsi_host *host) return container_of(host, struct msm_dsi_host, base); } -static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host) -{ - struct regulator_bulk_data *s = msm_host->supplies; - const struct dsi_reg_entry *regs = msm_host->cfg_hnd->cfg->reg_cfg.regs; - int num = msm_host->cfg_hnd->cfg->reg_cfg.num; - int i; - - DBG(""); - for (i = num - 1; i >= 0; i--) - if (regs[i].disable_load >= 0) - regulator_set_load(s[i].consumer, - regs[i].disable_load); - - regulator_bulk_disable(num, s); -} - -static int dsi_host_regulator_enable(struct msm_dsi_host *msm_host) -{ - struct regulator_bulk_data *s = msm_host->supplies; - const struct dsi_reg_entry *regs = msm_host->cfg_hnd->cfg->reg_cfg.regs; - int num = msm_host->cfg_hnd->cfg->reg_cfg.num; - int ret, i; - - DBG(""); - for (i = 0; i < num; i++) { - if (regs[i].enable_load >= 0) { - ret = regulator_set_load(s[i].consumer, - regs[i].enable_load); - if (ret < 0) { - pr_err("regulator %d set op mode failed, %d\n", - i, ret); - goto fail; - } - } - } - - ret = regulator_bulk_enable(num, s); - if (ret < 0) { - pr_err("regulator enable failed, %d\n", ret); - goto fail; - } - - return 0; - -fail: - for (i--; i >= 0; i--) - regulator_set_load(s[i].consumer, regs[i].disable_load); - return ret; -} - static int dsi_regulator_init(struct msm_dsi_host *msm_host) { struct regulator_bulk_data *s = msm_host->supplies; @@ -325,6 +272,15 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host) return ret; } + for (i = 0; i < num; i++) { + if (regs[i].enable_load >= 0) { + ret = regulator_set_load(s[i].consumer, + regs[i].enable_load); + if (ret < 0) + return ret; + } + } + return 0; } @@ -2547,7 +2503,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, msm_dsi_sfpb_config(msm_host, true); - ret = dsi_host_regulator_enable(msm_host); + ret = regulator_bulk_enable(msm_host->cfg_hnd->cfg->reg_cfg.num, + msm_host->supplies); if (ret) { pr_err("%s:Failed to enable vregs.ret=%d\n", __func__, ret); @@ -2587,7 +2544,8 @@ fail_disable_clk: cfg_hnd->ops->link_clk_disable(msm_host); pm_runtime_put(&msm_host->pdev->dev); fail_disable_reg: - dsi_host_regulator_disable(msm_host); + regulator_bulk_disable(msm_host->cfg_hnd->cfg->reg_cfg.num, + msm_host->supplies); unlock_ret: mutex_unlock(&msm_host->dev_mutex); return ret; @@ -2614,7 +2572,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) cfg_hnd->ops->link_clk_disable(msm_host); pm_runtime_put(&msm_host->pdev->dev); - dsi_host_regulator_disable(msm_host); + regulator_bulk_disable(msm_host->cfg_hnd->cfg->reg_cfg.num, + msm_host->supplies); msm_dsi_sfpb_config(msm_host, false); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 56dfa2d24be1..c341d6ab5d9e 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -529,58 +529,16 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy) return ret; } - return 0; -} - -static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy) -{ - struct regulator_bulk_data *s = phy->supplies; - const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; - int num = phy->cfg->reg_cfg.num; - int i; - - DBG(""); - for (i = num - 1; i >= 0; i--) - if (regs[i].disable_load >= 0) - regulator_set_load(s[i].consumer, regs[i].disable_load); - - regulator_bulk_disable(num, s); -} - -static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy) -{ - struct regulator_bulk_data *s = phy->supplies; - const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; - struct device *dev = &phy->pdev->dev; - int num = phy->cfg->reg_cfg.num; - int ret, i; - - DBG(""); for (i = 0; i < num; i++) { if (regs[i].enable_load >= 0) { ret = regulator_set_load(s[i].consumer, regs[i].enable_load); - if (ret < 0) { - DRM_DEV_ERROR(dev, - "regulator %d set op mode failed, %d\n", - i, ret); - goto fail; - } + if (ret < 0) + return ret; } } - ret = regulator_bulk_enable(num, s); - if (ret < 0) { - DRM_DEV_ERROR(dev, "regulator enable failed, %d\n", ret); - goto fail; - } - return 0; - -fail: - for (i--; i >= 0; i--) - regulator_set_load(s[i].consumer, regs[i].disable_load); - return ret; } static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) @@ -829,7 +787,7 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, goto res_en_fail; } - ret = dsi_phy_regulator_enable(phy); + ret = regulator_bulk_enable(phy->cfg->reg_cfg.num, phy->supplies); if (ret) { DRM_DEV_ERROR(dev, "%s: regulator enable failed, %d\n", __func__, ret); @@ -866,7 +824,7 @@ pll_restor_fail: if (phy->cfg->ops.disable) phy->cfg->ops.disable(phy); phy_en_fail: - dsi_phy_regulator_disable(phy); + regulator_bulk_disable(phy->cfg->reg_cfg.num, phy->supplies); reg_en_fail: dsi_phy_disable_resource(phy); res_en_fail: @@ -880,7 +838,7 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy) phy->cfg->ops.disable(phy); - dsi_phy_regulator_disable(phy); + regulator_bulk_disable(phy->cfg->reg_cfg.num, phy->supplies); dsi_phy_disable_resource(phy); } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index ae57f95edf63..d1a943e2c66a 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -1024,7 +1024,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vdds", 36000, 32}, + {"vdds", 36000}, }, }, .ops = { @@ -1046,7 +1046,7 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vdds", 36000, 32}, + {"vdds", 36000}, }, }, .ops = { diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 1a855351654c..7ca30d9b54f5 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -1028,7 +1028,7 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vcca", 17000, 32}, + {"vcca", 17000}, }, }, .ops = { @@ -1049,7 +1049,7 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vcca", 73400, 32}, + {"vcca", 73400}, }, }, .ops = { @@ -1070,7 +1070,7 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vcca", 17000, 32}, + {"vcca", 17000}, }, }, .ops = { diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c index ee7c418a1c29..b7c621d94981 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c @@ -134,8 +134,8 @@ const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { .reg_cfg = { .num = 2, .regs = { - {"vddio", 100000, 100}, /* 1.8 V */ - {"vcca", 10000, 100}, /* 1.0 V */ + {"vddio", 100000}, /* 1.8 V */ + {"vcca", 10000}, /* 1.0 V */ }, }, .ops = { diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 04411fefb808..8535659520f9 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -769,7 +769,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vddio", 100000, 100}, + {"vddio", 100000}, }, }, .ops = { @@ -790,7 +790,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vddio", 100000, 100}, + {"vddio", 100000}, }, }, .ops = { @@ -811,7 +811,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vddio", 100000, 100}, /* 1.8 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .ops = { diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index 69c1b2d8333c..e96f5adca275 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -643,7 +643,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vddio", 100000, 100}, /* 1.8 V */ + {"vddio", 100000}, /* 1.8 V */ }, }, .ops = { diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index c1710a8824e7..7897c9ddb0bb 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -1037,7 +1037,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vdds", 36000, 32}, + {"vdds", 36000}, }, }, .ops = { @@ -1064,7 +1064,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vdds", 36000, 32}, + {"vdds", 36000}, }, }, .ops = { @@ -1086,7 +1086,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = { .reg_cfg = { .num = 1, .regs = { - {"vdds", 37550, 0}, + {"vdds", 37550}, }, }, .ops = { From 15cde7ea0778fe1f92fbb00be4564ec239d84d3c Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:51 -0700 Subject: [PATCH 73/84] drm/msm/dsi: Use the new regulator bulk feature to specify the load As of commit 6eabfc018e8d ("regulator: core: Allow specifying an initial load w/ the bulk API") we can now specify the initial load in the bulk data rather than having to manually call regulator_set_load() on each regulator. Let's use it. Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496319/ Link: https://lore.kernel.org/r/20220804073608.v4.4.I7b3c72949883846badb073cfeae985c55239da1d@changeid Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_host.c | 13 +++---------- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 13 +++---------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 99e21d38c7da..00476c127e53 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -262,8 +262,10 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host) int num = msm_host->cfg_hnd->cfg->reg_cfg.num; int i, ret; - for (i = 0; i < num; i++) + for (i = 0; i < num; i++) { s[i].supply = regs[i].name; + s[i].init_load_uA = regs[i].enable_load; + } ret = devm_regulator_bulk_get(&msm_host->pdev->dev, num, s); if (ret < 0) { @@ -272,15 +274,6 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host) return ret; } - for (i = 0; i < num; i++) { - if (regs[i].enable_load >= 0) { - ret = regulator_set_load(s[i].consumer, - regs[i].enable_load); - if (ret < 0) - return ret; - } - } - return 0; } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index c341d6ab5d9e..11d0c60bc78f 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -515,8 +515,10 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy) int num = phy->cfg->reg_cfg.num; int i, ret; - for (i = 0; i < num; i++) + for (i = 0; i < num; i++) { s[i].supply = regs[i].name; + s[i].init_load_uA = regs[i].enable_load; + } ret = devm_regulator_bulk_get(dev, num, s); if (ret < 0) { @@ -529,15 +531,6 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy) return ret; } - for (i = 0; i < num; i++) { - if (regs[i].enable_load >= 0) { - ret = regulator_set_load(s[i].consumer, - regs[i].enable_load); - if (ret < 0) - return ret; - } - } - return 0; } From d8810a66924482fc3977cebe3404629ad2647743 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:52 -0700 Subject: [PATCH 74/84] drm/msm/dsi: Take advantage of devm_regulator_bulk_get_const() As of the commit 1de452a0edda ("regulator: core: Allow drivers to define their init data as const") we no longer need to do copying of regulator bulk data from initdata to something dynamic. Let's take advantage of that. In addition to saving some code, this also moves us to using ARRAY_SIZE() to specify how many regulators we have which is less error prone. This gets rid of some layers of wrappers which makes it obvious that we can get rid of an extra error print. devm_regulator_bulk_get_const() prints errors for you so you don't need an extra layer of printing. In all cases here I have preserved the old settings without any investigation about whether the loads being set are sensible. In the cases of some of the PHYs if several PHYs in the same file used exactly the same settings I had them point to the same data structure. NOTE: Though I haven't done the math, this is likely an overall savings in terms of "static const" data. We previously always allocated space for 8 supplies. Each of these supplies took up 36 bytes of data (32 for name, 4 for an int). Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496325/ Link: https://lore.kernel.org/r/20220804073608.v4.5.I55a9e65cb1c22221316629e98768ff473f47a067@changeid Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 12 -- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 172 +++++++++--------- drivers/gpu/drm/msm/dsi/dsi_cfg.h | 3 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 42 ++--- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 37 +--- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 5 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c | 20 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 32 ++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 14 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 28 +-- .../gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 12 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 32 ++-- 12 files changed, 167 insertions(+), 242 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 56996ac9e58a..805883187462 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -30,20 +30,8 @@ enum msm_dsi_phy_usecase { MSM_DSI_PHY_SLAVE, }; -#define DSI_DEV_REGULATOR_MAX 8 #define DSI_BUS_CLK_MAX 4 -/* Regulators for DSI devices */ -struct dsi_reg_entry { - char name[32]; - int enable_load; -}; - -struct dsi_reg_config { - int num; - struct dsi_reg_entry regs[DSI_DEV_REGULATOR_MAX]; -}; - struct msm_dsi { struct drm_device *dev; struct platform_device *pdev; diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 901d6fd53800..7e97c239ed48 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -9,16 +9,16 @@ static const char * const dsi_v2_bus_clk_names[] = { "core_mmss", "iface", "bus", }; +static const struct regulator_bulk_data apq8064_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 100000 }, /* 1.2 V */ + { .supply = "avdd", .init_load_uA = 10000 }, /* 3.0 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + static const struct msm_dsi_config apq8064_dsi_cfg = { .io_offset = 0, - .reg_cfg = { - .num = 3, - .regs = { - {"vdda", 100000}, /* 1.2 V */ - {"avdd", 10000}, /* 3.0 V */ - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = apq8064_dsi_regulators, + .num_regulators = ARRAY_SIZE(apq8064_dsi_regulators), .bus_clk_names = dsi_v2_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names), .io_start = { 0x4700000, 0x5800000 }, @@ -29,16 +29,16 @@ static const char * const dsi_6g_bus_clk_names[] = { "mdp_core", "iface", "bus", "core_mmss", }; +static const struct regulator_bulk_data msm8974_apq8084_regulators[] = { + { .supply = "vdd", .init_load_uA = 150000 }, /* 3.0 V */ + { .supply = "vdda", .init_load_uA = 100000 }, /* 1.2 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 3, - .regs = { - {"vdd", 150000}, /* 3.0 V */ - {"vdda", 100000}, /* 1.2 V */ - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = msm8974_apq8084_regulators, + .num_regulators = ARRAY_SIZE(msm8974_apq8084_regulators), .bus_clk_names = dsi_6g_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names), .io_start = { 0xfd922800, 0xfd922b00 }, @@ -49,15 +49,15 @@ static const char * const dsi_8916_bus_clk_names[] = { "mdp_core", "iface", "bus", }; +static const struct regulator_bulk_data msm8916_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 100000 }, /* 1.2 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + static const struct msm_dsi_config msm8916_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 2, - .regs = { - {"vdda", 100000}, /* 1.2 V */ - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = msm8916_dsi_regulators, + .num_regulators = ARRAY_SIZE(msm8916_dsi_regulators), .bus_clk_names = dsi_8916_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names), .io_start = { 0x1a98000 }, @@ -68,34 +68,34 @@ static const char * const dsi_8976_bus_clk_names[] = { "mdp_core", "iface", "bus", }; +static const struct regulator_bulk_data msm8976_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 100000 }, /* 1.2 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + static const struct msm_dsi_config msm8976_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 2, - .regs = { - {"vdda", 100000}, /* 1.2 V */ - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = msm8976_dsi_regulators, + .num_regulators = ARRAY_SIZE(msm8976_dsi_regulators), .bus_clk_names = dsi_8976_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_8976_bus_clk_names), .io_start = { 0x1a94000, 0x1a96000 }, .num_dsi = 2, }; +static const struct regulator_bulk_data msm8994_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 100000 }, /* 1.25 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ + { .supply = "vcca", .init_load_uA = 10000 }, /* 1.0 V */ + { .supply = "vdd", .init_load_uA = 100000 }, /* 1.8 V */ + { .supply = "lab_reg", .init_load_uA = -1 }, + { .supply = "ibb_reg", .init_load_uA = -1 }, +}; + static const struct msm_dsi_config msm8994_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 6, - .regs = { - {"vdda", 100000}, /* 1.25 V */ - {"vddio", 100000}, /* 1.8 V */ - {"vcca", 10000}, /* 1.0 V */ - {"vdd", 100000}, /* 1.8 V */ - {"lab_reg", -1}, - {"ibb_reg", -1}, - }, - }, + .regulator_data = msm8994_dsi_regulators, + .num_regulators = ARRAY_SIZE(msm8994_dsi_regulators), .bus_clk_names = dsi_6g_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names), .io_start = { 0xfd998000, 0xfd9a0000 }, @@ -106,16 +106,16 @@ static const char * const dsi_8996_bus_clk_names[] = { "mdp_core", "iface", "bus", "core_mmss", }; +static const struct regulator_bulk_data msm8996_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 18160 }, /* 1.25 V */ + { .supply = "vcca", .init_load_uA = 17000 }, /* 0.925 V */ + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + static const struct msm_dsi_config msm8996_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 3, - .regs = { - {"vdda", 18160}, /* 1.25 V */ - {"vcca", 17000}, /* 0.925 V */ - {"vddio", 100000},/* 1.8 V */ - }, - }, + .regulator_data = msm8996_dsi_regulators, + .num_regulators = ARRAY_SIZE(msm8996_dsi_regulators), .bus_clk_names = dsi_8996_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_8996_bus_clk_names), .io_start = { 0x994000, 0x996000 }, @@ -126,15 +126,15 @@ static const char * const dsi_msm8998_bus_clk_names[] = { "iface", "bus", "core", }; +static const struct regulator_bulk_data msm8998_dsi_regulators[] = { + { .supply = "vdd", .init_load_uA = 367000 }, /* 0.9 V */ + { .supply = "vdda", .init_load_uA = 62800 }, /* 1.2 V */ +}; + static const struct msm_dsi_config msm8998_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 2, - .regs = { - {"vdd", 367000}, /* 0.9 V */ - {"vdda", 62800}, /* 1.2 V */ - }, - }, + .regulator_data = msm8998_dsi_regulators, + .num_regulators = ARRAY_SIZE(msm8998_dsi_regulators), .bus_clk_names = dsi_msm8998_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_msm8998_bus_clk_names), .io_start = { 0xc994000, 0xc996000 }, @@ -145,14 +145,14 @@ static const char * const dsi_sdm660_bus_clk_names[] = { "iface", "bus", "core", "core_mmss", }; +static const struct regulator_bulk_data sdm660_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 12560 }, /* 1.2 V */ +}; + static const struct msm_dsi_config sdm660_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 1, - .regs = { - {"vdda", 12560}, /* 1.2 V */ - }, - }, + .regulator_data = sdm660_dsi_regulators, + .num_regulators = ARRAY_SIZE(sdm660_dsi_regulators), .bus_clk_names = dsi_sdm660_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_sdm660_bus_clk_names), .io_start = { 0xc994000, 0xc996000 }, @@ -167,28 +167,28 @@ static const char * const dsi_sc7180_bus_clk_names[] = { "iface", "bus", }; +static const struct regulator_bulk_data sdm845_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 21800 }, /* 1.2 V */ +}; + static const struct msm_dsi_config sdm845_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 1, - .regs = { - {"vdda", 21800}, /* 1.2 V */ - }, - }, + .regulator_data = sdm845_dsi_regulators, + .num_regulators = ARRAY_SIZE(sdm845_dsi_regulators), .bus_clk_names = dsi_sdm845_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_sdm845_bus_clk_names), .io_start = { 0xae94000, 0xae96000 }, .num_dsi = 2, }; +static const struct regulator_bulk_data sc7180_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 21800 }, /* 1.2 V */ +}; + static const struct msm_dsi_config sc7180_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 1, - .regs = { - {"vdda", 21800}, /* 1.2 V */ - }, - }, + .regulator_data = sc7180_dsi_regulators, + .num_regulators = ARRAY_SIZE(sc7180_dsi_regulators), .bus_clk_names = dsi_sc7180_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_sc7180_bus_clk_names), .io_start = { 0xae94000 }, @@ -199,14 +199,14 @@ static const char * const dsi_sc7280_bus_clk_names[] = { "iface", "bus", }; +static const struct regulator_bulk_data sc7280_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 8350 }, /* 1.2 V */ +}; + static const struct msm_dsi_config sc7280_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 1, - .regs = { - {"vdda", 8350}, /* 1.2 V */ - }, - }, + .regulator_data = sc7280_dsi_regulators, + .num_regulators = ARRAY_SIZE(sc7280_dsi_regulators), .bus_clk_names = dsi_sc7280_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_sc7280_bus_clk_names), .io_start = { 0xae94000 }, @@ -217,14 +217,14 @@ static const char * const dsi_qcm2290_bus_clk_names[] = { "iface", "bus", }; +static const struct regulator_bulk_data qcm2290_dsi_cfg_regulators[] = { + { .supply = "vdda", .init_load_uA = 21800 }, /* 1.2 V */ +}; + static const struct msm_dsi_config qcm2290_dsi_cfg = { .io_offset = DSI_6G_REG_SHIFT, - .reg_cfg = { - .num = 1, - .regs = { - {"vdda", 21800}, /* 1.2 V */ - }, - }, + .regulator_data = qcm2290_dsi_cfg_regulators, + .num_regulators = ARRAY_SIZE(qcm2290_dsi_cfg_regulators), .bus_clk_names = dsi_qcm2290_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_qcm2290_bus_clk_names), .io_start = { 0x5e94000 }, diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index fe54a999968b..8f04e685a74e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -32,7 +32,8 @@ struct msm_dsi_config { u32 io_offset; - struct dsi_reg_config reg_cfg; + const struct regulator_bulk_data *regulator_data; + int num_regulators; const char * const *bus_clk_names; const int num_bus_clks; const resource_size_t io_start[DSI_MAX]; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 00476c127e53..40f27ed57340 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -108,7 +108,7 @@ struct msm_dsi_host { void __iomem *ctrl_base; phys_addr_t ctrl_size; - struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX]; + struct regulator_bulk_data *supplies; int num_bus_clks; struct clk_bulk_data bus_clks[DSI_BUS_CLK_MAX]; @@ -255,28 +255,6 @@ static inline struct msm_dsi_host *to_msm_dsi_host(struct mipi_dsi_host *host) return container_of(host, struct msm_dsi_host, base); } -static int dsi_regulator_init(struct msm_dsi_host *msm_host) -{ - struct regulator_bulk_data *s = msm_host->supplies; - const struct dsi_reg_entry *regs = msm_host->cfg_hnd->cfg->reg_cfg.regs; - int num = msm_host->cfg_hnd->cfg->reg_cfg.num; - int i, ret; - - for (i = 0; i < num; i++) { - s[i].supply = regs[i].name; - s[i].init_load_uA = regs[i].enable_load; - } - - ret = devm_regulator_bulk_get(&msm_host->pdev->dev, num, s); - if (ret < 0) { - pr_err("%s: failed to init regulator, ret=%d\n", - __func__, ret); - return ret; - } - - return 0; -} - int dsi_clk_init_v2(struct msm_dsi_host *msm_host) { struct platform_device *pdev = msm_host->pdev; @@ -1977,6 +1955,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) { struct msm_dsi_host *msm_host = NULL; struct platform_device *pdev = msm_dsi->pdev; + const struct msm_dsi_config *cfg; int ret; msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); @@ -2009,6 +1988,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) pr_err("%s: get config failed\n", __func__); goto fail; } + cfg = msm_host->cfg_hnd->cfg; msm_host->id = dsi_host_get_id(msm_host); if (msm_host->id < 0) { @@ -2018,13 +1998,13 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) } /* fixup base address by io offset */ - msm_host->ctrl_base += msm_host->cfg_hnd->cfg->io_offset; + msm_host->ctrl_base += cfg->io_offset; - ret = dsi_regulator_init(msm_host); - if (ret) { - pr_err("%s: regulator init failed\n", __func__); + ret = devm_regulator_bulk_get_const(&pdev->dev, cfg->num_regulators, + cfg->regulator_data, + &msm_host->supplies); + if (ret) goto fail; - } ret = dsi_clk_init(msm_host); if (ret) { @@ -2496,7 +2476,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, msm_dsi_sfpb_config(msm_host, true); - ret = regulator_bulk_enable(msm_host->cfg_hnd->cfg->reg_cfg.num, + ret = regulator_bulk_enable(msm_host->cfg_hnd->cfg->num_regulators, msm_host->supplies); if (ret) { pr_err("%s:Failed to enable vregs.ret=%d\n", @@ -2537,7 +2517,7 @@ fail_disable_clk: cfg_hnd->ops->link_clk_disable(msm_host); pm_runtime_put(&msm_host->pdev->dev); fail_disable_reg: - regulator_bulk_disable(msm_host->cfg_hnd->cfg->reg_cfg.num, + regulator_bulk_disable(msm_host->cfg_hnd->cfg->num_regulators, msm_host->supplies); unlock_ret: mutex_unlock(&msm_host->dev_mutex); @@ -2565,7 +2545,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) cfg_hnd->ops->link_clk_disable(msm_host); pm_runtime_put(&msm_host->pdev->dev); - regulator_bulk_disable(msm_host->cfg_hnd->cfg->reg_cfg.num, + regulator_bulk_disable(msm_host->cfg_hnd->cfg->num_regulators, msm_host->supplies); msm_dsi_sfpb_config(msm_host, false); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 11d0c60bc78f..5880b33e4b5e 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -507,33 +507,6 @@ int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing, return 0; } -static int dsi_phy_regulator_init(struct msm_dsi_phy *phy) -{ - struct regulator_bulk_data *s = phy->supplies; - const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs; - struct device *dev = &phy->pdev->dev; - int num = phy->cfg->reg_cfg.num; - int i, ret; - - for (i = 0; i < num; i++) { - s[i].supply = regs[i].name; - s[i].init_load_uA = regs[i].enable_load; - } - - ret = devm_regulator_bulk_get(dev, num, s); - if (ret < 0) { - if (ret != -EPROBE_DEFER) { - DRM_DEV_ERROR(dev, - "%s: failed to init regulator, ret=%d\n", - __func__, ret); - } - - return ret; - } - - return 0; -} - static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) { struct device *dev = &phy->pdev->dev; @@ -698,7 +671,9 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail; } - ret = dsi_phy_regulator_init(phy); + ret = devm_regulator_bulk_get_const(dev, phy->cfg->num_regulators, + phy->cfg->regulator_data, + &phy->supplies); if (ret) goto fail; @@ -780,7 +755,7 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, goto res_en_fail; } - ret = regulator_bulk_enable(phy->cfg->reg_cfg.num, phy->supplies); + ret = regulator_bulk_enable(phy->cfg->num_regulators, phy->supplies); if (ret) { DRM_DEV_ERROR(dev, "%s: regulator enable failed, %d\n", __func__, ret); @@ -817,7 +792,7 @@ pll_restor_fail: if (phy->cfg->ops.disable) phy->cfg->ops.disable(phy); phy_en_fail: - regulator_bulk_disable(phy->cfg->reg_cfg.num, phy->supplies); + regulator_bulk_disable(phy->cfg->num_regulators, phy->supplies); reg_en_fail: dsi_phy_disable_resource(phy); res_en_fail: @@ -831,7 +806,7 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy) phy->cfg->ops.disable(phy); - regulator_bulk_disable(phy->cfg->reg_cfg.num, phy->supplies); + regulator_bulk_disable(phy->cfg->num_regulators, phy->supplies); dsi_phy_disable_resource(phy); } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index dc91b43d5a38..60a99c6525b2 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -29,7 +29,8 @@ struct msm_dsi_phy_ops { }; struct msm_dsi_phy_cfg { - struct dsi_reg_config reg_cfg; + const struct regulator_bulk_data *regulator_data; + int num_regulators; struct msm_dsi_phy_ops ops; unsigned long min_pll_rate; @@ -98,7 +99,7 @@ struct msm_dsi_phy { int id; struct clk *ahb_clk; - struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX]; + struct regulator_bulk_data *supplies; struct msm_dsi_dphy_timing timing; const struct msm_dsi_phy_cfg *cfg; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c index d1a943e2c66a..27b592c776a3 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c @@ -1019,14 +1019,14 @@ static int dsi_10nm_phy_parse_dt(struct msm_dsi_phy *phy) return 0; } +static const struct regulator_bulk_data dsi_phy_10nm_regulators[] = { + { .supply = "vdds", .init_load_uA = 36000 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vdds", 36000}, - }, - }, + .regulator_data = dsi_phy_10nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_10nm_regulators), .ops = { .enable = dsi_10nm_phy_enable, .disable = dsi_10nm_phy_disable, @@ -1043,12 +1043,8 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vdds", 36000}, - }, - }, + .regulator_data = dsi_phy_10nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_10nm_regulators), .ops = { .enable = dsi_10nm_phy_enable, .disable = dsi_10nm_phy_disable, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 7ca30d9b54f5..0f8f4ca46429 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -1023,14 +1023,18 @@ static void dsi_14nm_phy_disable(struct msm_dsi_phy *phy) wmb(); } +static const struct regulator_bulk_data dsi_phy_14nm_17mA_regulators[] = { + { .supply = "vcca", .init_load_uA = 17000 }, +}; + +static const struct regulator_bulk_data dsi_phy_14nm_73p4mA_regulators[] = { + { .supply = "vcca", .init_load_uA = 73400 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vcca", 17000}, - }, - }, + .regulator_data = dsi_phy_14nm_17mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators), .ops = { .enable = dsi_14nm_phy_enable, .disable = dsi_14nm_phy_disable, @@ -1046,12 +1050,8 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vcca", 73400}, - }, - }, + .regulator_data = dsi_phy_14nm_73p4mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_14nm_73p4mA_regulators), .ops = { .enable = dsi_14nm_phy_enable, .disable = dsi_14nm_phy_disable, @@ -1067,12 +1067,8 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vcca", 17000}, - }, - }, + .regulator_data = dsi_phy_14nm_17mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators), .ops = { .enable = dsi_14nm_phy_enable, .disable = dsi_14nm_phy_disable, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c index b7c621d94981..c9752b991744 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c @@ -129,15 +129,15 @@ static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) dsi_20nm_phy_regulator_ctrl(phy, false); } +static const struct regulator_bulk_data dsi_phy_20nm_regulators[] = { + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ + { .supply = "vcca", .init_load_uA = 10000 }, /* 1.0 V */ +}; + const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { .has_phy_regulator = true, - .reg_cfg = { - .num = 2, - .regs = { - {"vddio", 100000}, /* 1.8 V */ - {"vcca", 10000}, /* 1.0 V */ - }, - }, + .regulator_data = dsi_phy_20nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_20nm_regulators), .ops = { .enable = dsi_20nm_phy_enable, .disable = dsi_20nm_phy_disable, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 8535659520f9..4c1bf55c5f38 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -764,14 +764,14 @@ static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) wmb(); } +static const struct regulator_bulk_data dsi_phy_28nm_regulators[] = { + { .supply = "vddio", .init_load_uA = 100000 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = { .has_phy_regulator = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vddio", 100000}, - }, - }, + .regulator_data = dsi_phy_28nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators), .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, @@ -787,12 +787,8 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs = { .has_phy_regulator = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vddio", 100000}, - }, - }, + .regulator_data = dsi_phy_28nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators), .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, @@ -808,12 +804,8 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = { .has_phy_regulator = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = dsi_phy_28nm_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators), .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index e96f5adca275..26c08047e20c 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -638,14 +638,14 @@ static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) wmb(); } +static const struct regulator_bulk_data dsi_phy_28nm_8960_regulators[] = { + { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ +}; + const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = { .has_phy_regulator = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vddio", 100000}, /* 1.8 V */ - }, - }, + .regulator_data = dsi_phy_28nm_8960_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_28nm_8960_regulators), .ops = { .enable = dsi_28nm_phy_enable, .disable = dsi_28nm_phy_disable, diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 7897c9ddb0bb..9e7fa7d88ead 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -1032,14 +1032,18 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) DBG("DSI%d PHY disabled", phy->id); } +static const struct regulator_bulk_data dsi_phy_7nm_36mA_regulators[] = { + { .supply = "vdds", .init_load_uA = 36000 }, +}; + +static const struct regulator_bulk_data dsi_phy_7nm_37750uA_regulators[] = { + { .supply = "vdds", .init_load_uA = 37550 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vdds", 36000}, - }, - }, + .regulator_data = dsi_phy_7nm_36mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_36mA_regulators), .ops = { .enable = dsi_7nm_phy_enable, .disable = dsi_7nm_phy_disable, @@ -1061,12 +1065,8 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vdds", 36000}, - }, - }, + .regulator_data = dsi_phy_7nm_36mA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_36mA_regulators), .ops = { .enable = dsi_7nm_phy_enable, .disable = dsi_7nm_phy_disable, @@ -1083,12 +1083,8 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = { .has_phy_lane = true, - .reg_cfg = { - .num = 1, - .regs = { - {"vdds", 37550}, - }, - }, + .regulator_data = dsi_phy_7nm_37750uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_37750uA_regulators), .ops = { .enable = dsi_7nm_phy_enable, .disable = dsi_7nm_phy_disable, From d175d6e0bb10e276cb074fb952cf859c37956567 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 4 Aug 2022 07:38:53 -0700 Subject: [PATCH 75/84] drm/msm/dsi: Improve dsi_phy_driver_probe() probe error handling The dsi_phy_driver_probe() function has a "goto fail" for no reason. Change it to just always return directly when it sees an error. Make this simpler by leveraging dev_err_probe() which is designed to make code like this shorter / simpler. NOTE: as part of this, we now pass through error codes directly from msm_ioremap_size() rather than translating to -ENOMEM. This changed mostly because it's much more convenient when using dev_err_probe() and also it's usually encouraged not to hide error codes like the old code was doing unless there is a good reason. I can't see any reason why we'd need to return -ENOMEM instead of -EINVAL from the probe function. Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/496324/ Link: https://lore.kernel.org/r/20220804073608.v4.6.I969118a35934a0e5007fe4f80e3e28e9c0b7602a@changeid Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 74 ++++++++++----------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 5880b33e4b5e..7fc0975cb869 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -621,12 +621,9 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) phy->pdev = pdev; phy->id = dsi_phy_get_id(phy); - if (phy->id < 0) { - ret = phy->id; - DRM_DEV_ERROR(dev, "%s: couldn't identify PHY index, %d\n", - __func__, ret); - goto fail; - } + if (phy->id < 0) + return dev_err_probe(dev, phy->id, + "Couldn't identify PHY index\n"); phy->regulator_ldo_mode = of_property_read_bool(dev->of_node, "qcom,dsi-phy-regulator-ldo-mode"); @@ -634,88 +631,71 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) phy->cphy_mode = (phy_type == PHY_TYPE_CPHY); phy->base = msm_ioremap_size(pdev, "dsi_phy", &phy->base_size); - if (IS_ERR(phy->base)) { - DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__); - ret = -ENOMEM; - goto fail; - } + if (IS_ERR(phy->base)) + return dev_err_probe(dev, PTR_ERR(phy->base), + "Failed to map phy base\n"); phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", &phy->pll_size); - if (IS_ERR(phy->pll_base)) { - DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__); - ret = -ENOMEM; - goto fail; - } + if (IS_ERR(phy->pll_base)) + return dev_err_probe(dev, PTR_ERR(phy->pll_base), + "Failed to map pll base\n"); if (phy->cfg->has_phy_lane) { phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", &phy->lane_size); - if (IS_ERR(phy->lane_base)) { - DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", __func__); - ret = -ENOMEM; - goto fail; - } + if (IS_ERR(phy->lane_base)) + return dev_err_probe(dev, PTR_ERR(phy->lane_base), + "Failed to map phy lane base\n"); } if (phy->cfg->has_phy_regulator) { phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", &phy->reg_size); - if (IS_ERR(phy->reg_base)) { - DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n", __func__); - ret = -ENOMEM; - goto fail; - } + if (IS_ERR(phy->reg_base)) + return dev_err_probe(dev, PTR_ERR(phy->reg_base), + "Failed to map phy regulator base\n"); } if (phy->cfg->ops.parse_dt_properties) { ret = phy->cfg->ops.parse_dt_properties(phy); if (ret) - goto fail; + return ret; } ret = devm_regulator_bulk_get_const(dev, phy->cfg->num_regulators, phy->cfg->regulator_data, &phy->supplies); if (ret) - goto fail; + return ret; phy->ahb_clk = msm_clk_get(pdev, "iface"); - if (IS_ERR(phy->ahb_clk)) { - DRM_DEV_ERROR(dev, "%s: Unable to get ahb clk\n", __func__); - ret = PTR_ERR(phy->ahb_clk); - goto fail; - } + if (IS_ERR(phy->ahb_clk)) + return dev_err_probe(dev, PTR_ERR(phy->ahb_clk), + "Unable to get ahb clk\n"); /* PLL init will call into clk_register which requires * register access, so we need to enable power and ahb clock. */ ret = dsi_phy_enable_resource(phy); if (ret) - goto fail; + return ret; if (phy->cfg->ops.pll_init) { ret = phy->cfg->ops.pll_init(phy); - if (ret) { - DRM_DEV_INFO(dev, - "%s: pll init failed: %d, need separate pll clk driver\n", - __func__, ret); - goto fail; - } + if (ret) + return dev_err_probe(dev, ret, + "PLL init failed; need separate clk driver\n"); } ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, phy->provided_clocks); - if (ret) { - DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret); - goto fail; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to register clk provider\n"); dsi_phy_disable_resource(phy); platform_set_drvdata(pdev, phy); return 0; - -fail: - return ret; } static struct platform_driver dsi_phy_platform_driver = { From ac229a22f2fef6e9fdde6f38d49ea3f58abdb07b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Aug 2022 20:44:17 +0300 Subject: [PATCH 76/84] drm/msm/dsi: drop the hpd worker It makes no sense to have the HPD worker in the MSM DSI driver anymore. It is only queued from the dsi_host_attach/detach() callbacks, where it plays no useful role. Either way the panel or next bridge will be present and will report it's status directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/498740/ Link: https://lore.kernel.org/r/20220822174417.292926-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_host.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 40f27ed57340..d7d025fadda9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -144,7 +144,6 @@ struct msm_dsi_host { u32 err_work_state; struct work_struct err_work; - struct work_struct hpd_work; struct workqueue_struct *workqueue; /* DSI 6G TX buffer*/ @@ -1427,14 +1426,6 @@ static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host, return len; } -static void dsi_hpd_worker(struct work_struct *work) -{ - struct msm_dsi_host *msm_host = - container_of(work, struct msm_dsi_host, hpd_work); - - drm_helper_hpd_irq_event(msm_host->dev); -} - static void dsi_err_worker(struct work_struct *work) { struct msm_dsi_host *msm_host = @@ -1624,8 +1615,6 @@ static int dsi_host_attach(struct mipi_dsi_host *host, return ret; DBG("id=%d", msm_host->id); - if (msm_host->dev) - queue_work(msm_host->workqueue, &msm_host->hpd_work); return 0; } @@ -1640,8 +1629,6 @@ static int dsi_host_detach(struct mipi_dsi_host *host, msm_host->device_node = NULL; DBG("id=%d", msm_host->id); - if (msm_host->dev) - queue_work(msm_host->workqueue, &msm_host->hpd_work); return 0; } @@ -2055,7 +2042,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) /* setup workqueue */ msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); INIT_WORK(&msm_host->err_work, dsi_err_worker); - INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker); msm_dsi->id = msm_host->id; From b29200959e7b1806ef9299dd38a245c0dd533316 Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Fri, 26 Aug 2022 07:28:21 +0000 Subject: [PATCH 77/84] drm/msm/dsi: Remove the unneeded result variable Return the value msm_dsi_phy_enable() directly instead of storing it in another redundant variable. Reported-by: Zeal Robot Signed-off-by: ye xingchen Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/499621/ Link: https://lore.kernel.org/r/20220826072821.253150-1-ye.xingchen@zte.com.cn Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index cb84d185d73a..0b516a04945f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -141,14 +141,11 @@ static int enable_phy(struct msm_dsi *msm_dsi, struct msm_dsi_phy_shared_timings *shared_timings) { struct msm_dsi_phy_clk_request clk_req; - int ret; bool is_bonded_dsi = IS_BONDED_DSI(); msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_bonded_dsi); - ret = msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings); - - return ret; + return msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings); } static int From 02c830b3719280be4c43fe78f24fbf5db4192f91 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 11 Jul 2022 12:43:17 +0300 Subject: [PATCH 78/84] drm/mipi-dsi: pass DSC data through the struct mipi_dsi_device The commit 0f40ba48de3b ("drm/msm/dsi: Pass DSC params to drm_panel") added a pointer to the DSC data to the struct drm_panel. However DSC support is not limited to the DSI panels. MIPI DSI bridges can also consume DSC command streams. Thus add struct drm_dsc_config pointer to the struct mipi_dsi_device. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/493306/ Link: https://lore.kernel.org/r/20220711094320.368062-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- include/drm/drm_mipi_dsi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 91a164bdd8f3..bb20bc27ce87 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -179,6 +179,7 @@ struct mipi_dsi_device_info { * @lp_rate: maximum lane frequency for low power mode in hertz, this should * be set to the real limits of the hardware, zero is only accepted for * legacy drivers + * @dsc: panel/bridge DSC pps payload to be sent */ struct mipi_dsi_device { struct mipi_dsi_host *host; @@ -191,6 +192,7 @@ struct mipi_dsi_device { unsigned long mode_flags; unsigned long hs_rate; unsigned long lp_rate; + struct drm_dsc_config *dsc; }; #define MIPI_DSI_MODULE_PREFIX "mipi-dsi:" From 574922e617f305404ecb0f6d62da2dcd222102bc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 11 Jul 2022 12:43:18 +0300 Subject: [PATCH 79/84] drm/msm/dsi: fetch DSC pps payload from struct mipi_dsi_device Now that struct mipi_dsi_device provides DSC data, fetch it from the mentioned struct rather than from the struct drm_panel itself. This would allow supporting MIPI DSI bridges handling DSC on their input side. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/493307/ Link: https://lore.kernel.org/r/20220711094320.368062-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_host.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index d7d025fadda9..9bb124c26a00 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1604,6 +1604,8 @@ static int dsi_host_attach(struct mipi_dsi_host *host, msm_host->lanes = dsi->lanes; msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; + if (dsi->dsc) + msm_host->dsc = dsi->dsc; /* Some gpios defined in panel DT need to be controlled by host */ ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev); @@ -2074,14 +2076,9 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; - struct drm_panel *panel; int ret; msm_host->dev = dev; - panel = msm_dsi_host_get_panel(&msm_host->base); - - if (!IS_ERR(panel) && panel->dsc) - msm_host->dsc = panel->dsc; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { From 549eae27743116da08a7846e09f1e910992af655 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 11 Jul 2022 12:43:19 +0300 Subject: [PATCH 80/84] drm/panel: drop DSC pps pointer Complete the move of DSC data pointer from struct drm_panel to struct mipi_dsi_device. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/493309/ Link: https://lore.kernel.org/r/20220711094320.368062-4-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- include/drm/drm_panel.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 3a271128c078..994bfcdd84c5 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -188,13 +188,6 @@ struct drm_panel { * Panel entry in registry. */ struct list_head list; - - /** - * @dsc: - * - * Panel DSC pps payload to be sent - */ - struct drm_dsc_config *dsc; }; void drm_panel_init(struct drm_panel *panel, struct device *dev, From 007ac0262b0dbb5523e99f03c6f3f44e09b15f66 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 12 Jul 2022 16:22:58 +0300 Subject: [PATCH 81/84] drm/msm/dsi: switch to DRM_PANEL_BRIDGE Currently the DSI driver has two separate paths: one if the next device in a chain is a bridge and another one if the panel is connected directly to the DSI host. Simplify the code path by using panel-bridge driver (already selected in Kconfig) and dropping support for handling the panel directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/493608/ Link: https://lore.kernel.org/r/20220712132258.671263-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.c | 35 +--- drivers/gpu/drm/msm/dsi/dsi.h | 16 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 25 --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 283 +++----------------------- 4 files changed, 36 insertions(+), 323 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 8f1ed31b048a..39bbabb5daf6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -6,14 +6,6 @@ #include "dsi.h" #include "dsi_cfg.h" -struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) -{ - if (!msm_dsi || !msm_dsi_device_connected(msm_dsi)) - return NULL; - - return msm_dsi->encoder; -} - bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi) { unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host); @@ -220,7 +212,6 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoder) { struct msm_drm_private *priv; - struct drm_bridge *ext_bridge; int ret; if (WARN_ON(!encoder) || WARN_ON(!msm_dsi) || WARN_ON(!dev)) @@ -254,26 +245,10 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, goto fail; } - /* - * check if the dsi encoder output is connected to a panel or an - * external bridge. We create a connector only if we're connected to a - * drm_panel device. When we're connected to an external bridge, we - * assume that the drm_bridge driver will create the connector itself. - */ - ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host); - - if (ext_bridge) - msm_dsi->connector = - msm_dsi_manager_ext_bridge_init(msm_dsi->id); - else - msm_dsi->connector = - msm_dsi_manager_connector_init(msm_dsi->id); - - if (IS_ERR(msm_dsi->connector)) { - ret = PTR_ERR(msm_dsi->connector); + ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); - msm_dsi->connector = NULL; goto fail; } @@ -287,12 +262,6 @@ fail: msm_dsi->bridge = NULL; } - /* don't destroy connector if we didn't make it */ - if (msm_dsi->connector && !msm_dsi->external_bridge) - msm_dsi->connector->funcs->destroy(msm_dsi->connector); - - msm_dsi->connector = NULL; - return ret; } diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 805883187462..2a96b4fe7839 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "msm_drv.h" #include "disp/msm_disp_snapshot.h" @@ -36,8 +35,6 @@ struct msm_dsi { struct drm_device *dev; struct platform_device *pdev; - /* connector managed by us when we're connected to a drm_panel */ - struct drm_connector *connector; /* internal dsi bridge attached to MDP interface */ struct drm_bridge *bridge; @@ -45,10 +42,8 @@ struct msm_dsi { struct msm_dsi_phy *phy; /* - * panel/external_bridge connected to dsi bridge output, only one of the - * two can be valid at a time + * external_bridge connected to dsi bridge output */ - struct drm_panel *panel; struct drm_bridge *external_bridge; struct device *phy_dev; @@ -63,8 +58,7 @@ struct msm_dsi { /* dsi manager */ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); -struct drm_connector *msm_dsi_manager_connector_init(u8 id); -struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); +int msm_dsi_manager_ext_bridge_init(u8 id); 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); @@ -74,11 +68,9 @@ void msm_dsi_manager_tpg_enable(void); /* msm dsi */ static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) { - return msm_dsi->panel || msm_dsi->external_bridge; + return msm_dsi->external_bridge; } -struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); - /* dsi host */ struct msm_dsi_host; int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, @@ -103,9 +95,7 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, const struct drm_display_mode *mode); enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, const struct drm_display_mode *mode); -struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host); unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host); -struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host); int msm_dsi_host_register(struct mipi_dsi_host *host); void msm_dsi_host_unregister(struct mipi_dsi_host *host); void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 9bb124c26a00..57a4c0fa614b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -163,7 +163,6 @@ struct msm_dsi_host { struct drm_dsc_config *dsc; /* connected device info */ - struct device_node *device_node; unsigned int channel; unsigned int lanes; enum mipi_dsi_pixel_format format; @@ -1628,8 +1627,6 @@ static int dsi_host_detach(struct mipi_dsi_host *host, dsi_dev_detach(msm_host->pdev); - msm_host->device_node = NULL; - DBG("id=%d", msm_host->id); return 0; @@ -1893,16 +1890,6 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) goto err; } - /* Get panel node from the output port's endpoint data */ - device_node = of_graph_get_remote_node(np, 1, 0); - if (!device_node) { - DRM_DEV_DEBUG(dev, "%s: no valid device\n", __func__); - ret = -ENODEV; - goto err; - } - - msm_host->device_node = device_node; - if (of_property_read_bool(np, "syscon-sfpb")) { msm_host->sfpb = syscon_regmap_lookup_by_phandle(np, "syscon-sfpb"); @@ -2587,23 +2574,11 @@ enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, return MODE_OK; } -struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host) -{ - return of_drm_find_panel(to_msm_dsi_host(host)->device_node); -} - unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host) { return to_msm_dsi_host(host)->mode_flags; } -struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host) -{ - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - - return of_drm_find_bridge(msm_host->device_node); -} - void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 0b516a04945f..3a1417397283 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -211,39 +211,26 @@ static void dsi_mgr_phy_disable(int id) } } -struct dsi_connector { - struct drm_connector base; - int id; -}; - struct dsi_bridge { struct drm_bridge base; int id; }; -#define to_dsi_connector(x) container_of(x, struct dsi_connector, base) #define to_dsi_bridge(x) container_of(x, struct dsi_bridge, base) -static inline int dsi_mgr_connector_get_id(struct drm_connector *connector) -{ - struct dsi_connector *dsi_connector = to_dsi_connector(connector); - return dsi_connector->id; -} - static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge) { struct dsi_bridge *dsi_bridge = to_dsi_bridge(bridge); return dsi_bridge->id; } -static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id) +static void msm_dsi_manager_set_split_display(u8 id) { - struct msm_drm_private *priv = conn->dev->dev_private; - struct msm_kms *kms = priv->kms; 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; - struct drm_panel *panel; if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) { master_dsi = other_dsi; @@ -253,89 +240,18 @@ static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id) slave_dsi = other_dsi; } - /* - * There is only 1 panel in the global panel list for bonded DSI mode. - * Therefore slave dsi should get the drm_panel instance from master - * dsi. - */ - panel = msm_dsi_host_get_panel(master_dsi->host); - if (IS_ERR(panel)) { - DRM_ERROR("Could not find panel for %u (%ld)\n", msm_dsi->id, - PTR_ERR(panel)); - return PTR_ERR(panel); - } - - if (!panel || !IS_BONDED_DSI()) - goto out; - - drm_object_attach_property(&conn->base, - conn->dev->mode_config.tile_property, 0); + 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->panel && kms->funcs->set_split_display) { + 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)); } - -out: - msm_dsi->panel = panel; - return 0; -} - -static enum drm_connector_status dsi_mgr_connector_detect( - struct drm_connector *connector, bool force) -{ - int id = dsi_mgr_connector_get_id(connector); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - - return msm_dsi->panel ? connector_status_connected : - connector_status_disconnected; -} - -static void dsi_mgr_connector_destroy(struct drm_connector *connector) -{ - struct dsi_connector *dsi_connector = to_dsi_connector(connector); - - DBG(""); - - drm_connector_cleanup(connector); - - kfree(dsi_connector); -} - -static int dsi_mgr_connector_get_modes(struct drm_connector *connector) -{ - int id = dsi_mgr_connector_get_id(connector); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_panel *panel = msm_dsi->panel; - int num; - - if (!panel) - return 0; - - /* - * In bonded DSI mode, we have one connector that can be - * attached to the drm_panel. - */ - num = drm_panel_get_modes(panel, connector); - if (!num) - return 0; - - return num; -} - -static struct drm_encoder * -dsi_mgr_connector_best_encoder(struct drm_connector *connector) -{ - int id = dsi_mgr_connector_get_id(connector); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - - DBG(""); - return msm_dsi_get_encoder(msm_dsi); } static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge) @@ -400,7 +316,6 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); struct mipi_dsi_host *host = msm_dsi->host; - struct drm_panel *panel = msm_dsi->panel; bool is_bonded_dsi = IS_BONDED_DSI(); int ret; @@ -415,18 +330,6 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (!dsi_mgr_power_on_early(bridge)) dsi_mgr_bridge_power_on(bridge); - /* Always call panel functions once, because even for dual panels, - * there is only one drm_panel instance. - */ - if (panel) { - ret = drm_panel_prepare(panel); - if (ret) { - pr_err("%s: prepare panel %d failed, %d\n", __func__, - id, ret); - goto panel_prep_fail; - } - } - ret = msm_dsi_host_enable(host); if (ret) { pr_err("%s: enable host %d failed, %d\n", __func__, id, ret); @@ -446,9 +349,6 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) host1_en_fail: msm_dsi_host_disable(host); host_en_fail: - if (panel) - drm_panel_unprepare(panel); -panel_prep_fail: return; } @@ -466,62 +366,12 @@ void msm_dsi_manager_tpg_enable(void) } } -static void dsi_mgr_bridge_enable(struct drm_bridge *bridge) -{ - int id = dsi_mgr_bridge_get_id(bridge); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_panel *panel = msm_dsi->panel; - bool is_bonded_dsi = IS_BONDED_DSI(); - 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)) - return; - - if (panel) { - ret = drm_panel_enable(panel); - if (ret) { - pr_err("%s: enable panel %d failed, %d\n", __func__, id, - ret); - } - } -} - -static void dsi_mgr_bridge_disable(struct drm_bridge *bridge) -{ - int id = dsi_mgr_bridge_get_id(bridge); - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_panel *panel = msm_dsi->panel; - bool is_bonded_dsi = IS_BONDED_DSI(); - 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)) - return; - - if (panel) { - ret = drm_panel_disable(panel); - if (ret) - pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, - ret); - } -} - static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) { int id = dsi_mgr_bridge_get_id(bridge); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); struct mipi_dsi_host *host = msm_dsi->host; - struct drm_panel *panel = msm_dsi->panel; bool is_bonded_dsi = IS_BONDED_DSI(); int ret; @@ -548,13 +398,6 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) pr_err("%s: host1 disable failed, %d\n", __func__, ret); } - if (panel) { - ret = drm_panel_unprepare(panel); - if (ret) - pr_err("%s: Panel %d unprepare failed,%d\n", __func__, - id, ret); - } - msm_dsi_host_disable_irq(host); if (is_bonded_dsi && msm_dsi1) msm_dsi_host_disable_irq(msm_dsi1->host); @@ -611,76 +454,13 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, return msm_dsi_host_check_dsc(host, mode); } -static const struct drm_connector_funcs dsi_mgr_connector_funcs = { - .detect = dsi_mgr_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = dsi_mgr_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = { - .get_modes = dsi_mgr_connector_get_modes, - .best_encoder = dsi_mgr_connector_best_encoder, -}; - static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { .pre_enable = dsi_mgr_bridge_pre_enable, - .enable = dsi_mgr_bridge_enable, - .disable = dsi_mgr_bridge_disable, .post_disable = dsi_mgr_bridge_post_disable, .mode_set = dsi_mgr_bridge_mode_set, .mode_valid = dsi_mgr_bridge_mode_valid, }; -/* initialize connector when we're connected to a drm_panel */ -struct drm_connector *msm_dsi_manager_connector_init(u8 id) -{ - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct drm_connector *connector = NULL; - struct dsi_connector *dsi_connector; - int ret; - - dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL); - if (!dsi_connector) - return ERR_PTR(-ENOMEM); - - dsi_connector->id = id; - - connector = &dsi_connector->base; - - ret = drm_connector_init(msm_dsi->dev, connector, - &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI); - if (ret) - return ERR_PTR(ret); - - drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs); - - /* Enable HPD to let hpd event is handled - * when panel is attached to the host. - */ - connector->polled = DRM_CONNECTOR_POLL_HPD; - - /* Display driver doesn't support interlace now. */ - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_connector_attach_encoder(connector, msm_dsi->encoder); - - ret = msm_dsi_manager_panel_init(connector, id); - if (ret) { - DRM_DEV_ERROR(msm_dsi->dev->dev, "init panel failed %d\n", ret); - goto fail; - } - - return connector; - -fail: - connector->funcs->destroy(connector); - return ERR_PTR(ret); -} - /* initialize bridge */ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) { @@ -719,18 +499,21 @@ fail: return ERR_PTR(ret); } -struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id) +int msm_dsi_manager_ext_bridge_init(u8 id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_device *dev = msm_dsi->dev; - struct drm_connector *connector; struct drm_encoder *encoder; struct drm_bridge *int_bridge, *ext_bridge; int ret; int_bridge = msm_dsi->bridge; - ext_bridge = msm_dsi->external_bridge = - msm_dsi_host_get_bridge(msm_dsi->host); + ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev, + msm_dsi->pdev->dev.of_node, 1, 0); + if (IS_ERR(ext_bridge)) + return PTR_ERR(ext_bridge); + + msm_dsi->external_bridge = ext_bridge; encoder = msm_dsi->encoder; @@ -742,36 +525,32 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id) ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret == -EINVAL) { - struct drm_connector *connector; - struct list_head *connector_list; - - /* link the internal dsi bridge to the external bridge */ - drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); - /* - * we need the drm_connector created by the external bridge - * driver (or someone else) to feed it to our driver's - * priv->connector[] list, mainly for msm_fbdev_init() + * link the internal dsi bridge to the external bridge, + * connector is created by the next bridge. */ - connector_list = &dev->mode_config.connector_list; + ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); + if (ret < 0) + return ret; + } else { + struct drm_connector *connector; - list_for_each_entry(connector, connector_list, head) { - if (drm_connector_has_possible_encoder(connector, encoder)) - return connector; + /* We are in charge of the connector, create one now. */ + connector = drm_bridge_connector_init(dev, encoder); + if (IS_ERR(connector)) { + DRM_ERROR("Unable to create bridge connector\n"); + return PTR_ERR(connector); } - return ERR_PTR(-ENODEV); + ret = drm_connector_attach_encoder(connector, encoder); + if (ret < 0) + return ret; } - connector = drm_bridge_connector_init(dev, encoder); - if (IS_ERR(connector)) { - DRM_ERROR("Unable to create bridge connector\n"); - return ERR_CAST(connector); - } + /* The pipeline is ready, ping encoders if necessary */ + msm_dsi_manager_set_split_display(id); - drm_connector_attach_encoder(connector, encoder); - - return connector; + return 0; } void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) From 682493e401a2c5f7a5f6d851939f7c03536970ba Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 29 Aug 2022 09:54:50 -0700 Subject: [PATCH 82/84] drm/msm/dsi: Remove use of device_node in dsi_host_parse_dt() Clang warns: drivers/gpu/drm/msm/dsi/dsi_host.c:1903:14: error: variable 'device_node' is uninitialized when used here [-Werror,-Wuninitialized] of_node_put(device_node); ^~~~~~~~~~~ drivers/gpu/drm/msm/dsi/dsi_host.c:1870:44: note: initialize the variable 'device_node' to silence this warning struct device_node *endpoint, *device_node; ^ = NULL 1 error generated. device_node's assignment was removed but not all of its uses. Remove the call to of_node_put() and the variable declaration to clean up the warning. Fixes: 36246dd50225 ("drm/msm/dsi: switch to DRM_PANEL_BRIDGE") Link: https://github.com/ClangBuiltLinux/linux/issues/1700 Signed-off-by: Nathan Chancellor Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/500182/ Link: https://lore.kernel.org/r/20220829165450.217628-1-nathan@kernel.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_host.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 57a4c0fa614b..7fbf391c024f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1867,7 +1867,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) { struct device *dev = &msm_host->pdev->dev; struct device_node *np = dev->of_node; - struct device_node *endpoint, *device_node; + struct device_node *endpoint; int ret = 0; /* @@ -1900,8 +1900,6 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) } } - of_node_put(device_node); - err: of_node_put(endpoint); From e3ea01f4187461d0685b5b97915f86d6d6a0425c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 4 Jul 2022 19:11:46 +0300 Subject: [PATCH 83/84] dt-bindings: phy: qcom, hdmi-phy-qmp: add clock-cells and XO clock As the QMP HDMI PHY is a clock provider, add constant #clock-cells property. For the compatibility with older DTs the property is not marked as required. Also add the XO clock to the list of the clocks used by the driver. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Dmitry Baryshkov Acked-by: Vinod Koul Patchwork: https://patchwork.freedesktop.org/patch/492316/ Link: https://lore.kernel.org/r/20220704161148.814510-2-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- .../bindings/phy/qcom,hdmi-phy-qmp.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml index eea2e02678ed..83fe4b39b56f 100644 --- a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml @@ -28,12 +28,15 @@ properties: - const: hdmi_phy clocks: - maxItems: 2 + minItems: 2 + maxItems: 3 clock-names: + minItems: 2 items: - const: iface - const: ref + - const: xo power-domains: maxItems: 1 @@ -44,6 +47,9 @@ properties: vddio-supply: description: phandle to VDD I/O supply regulator + '#clock-cells': + const: 0 + '#phy-cells': const: 0 @@ -75,9 +81,12 @@ examples: "hdmi_phy"; clocks = <&mmcc 116>, - <&gcc 214>; + <&gcc 214>, + <&xo_board>; clock-names = "iface", - "ref"; + "ref", + "xo"; + #clock-cells = <0>; #phy-cells = <0>; vddio-supply = <&vreg_l12a_1p8>; From e8b595f7b058c7909e410f3e0736d95e8f909d01 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 4 Jul 2022 19:11:47 +0300 Subject: [PATCH 84/84] drm/msm/hdmi: make hdmi_phy_8996 OF clk provider On MSM8996 the HDMI PHY provides the PLL clock to the MMCC. As we are preparing to convert the MSM8996 to use DT clocks properties (rather than global clock names), register the OF clock provider. While we are at it, also change the driver to use clk_parent_data rather parent_names to setup a link to the XO clock. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/492318/ Link: https://lore.kernel.org/r/20220704161148.814510-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c index b06d9d25a189..4dd055416620 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c @@ -691,15 +691,13 @@ static const struct clk_ops hdmi_8996_pll_ops = { .is_enabled = hdmi_8996_pll_is_enabled, }; -static const char * const hdmi_pll_parents[] = { - "xo", -}; - static const struct clk_init_data pll_init = { .name = "hdmipll", .ops = &hdmi_8996_pll_ops, - .parent_names = hdmi_pll_parents, - .num_parents = ARRAY_SIZE(hdmi_pll_parents), + .parent_data = (const struct clk_parent_data[]){ + { .fw_name = "xo", .name = "xo_board" }, + }, + .num_parents = 1, .flags = CLK_IGNORE_UNUSED, }; @@ -707,8 +705,7 @@ int msm_hdmi_pll_8996_init(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct hdmi_pll_8996 *pll; - struct clk *clk; - int i; + int i, ret; pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); if (!pll) @@ -735,10 +732,16 @@ int msm_hdmi_pll_8996_init(struct platform_device *pdev) } pll->clk_hw.init = &pll_init; - clk = devm_clk_register(dev, &pll->clk_hw); - if (IS_ERR(clk)) { + ret = devm_clk_hw_register(dev, &pll->clk_hw); + if (ret) { DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return -EINVAL; + return ret; + } + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw); + if (ret) { + DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret); + return ret; } return 0;