From ddd147d91d509c9d9fc6159efc5b56f61440bb9a Mon Sep 17 00:00:00 2001 From: Louis Chauvet Date: Fri, 7 Feb 2025 18:35:22 +0100 Subject: [PATCH 01/34] drm: writeback: Fix kernel doc name During the creation of drmm_ variants for writeback connector, one function was renamed, but not the kernel doc. To remove the warning, use the proper name in kernel doc. Fixes: 135d8fc7af44 ("drm: writeback: Create an helper for drm_writeback_connector initialization") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/all/20250207142201.550ce870@canb.auug.org.au/ Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20250207-b4-fix-warning-v1-1-b4964beb60a3@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_writeback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index f139b49af4c9..edbeab88ff2b 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -213,7 +213,7 @@ static void delete_writeback_properties(struct drm_device *dev) } /** - * drm_writeback_connector_init_with_encoder - Initialize a writeback connector with + * __drm_writeback_connector_init - Initialize a writeback connector with * a custom encoder * * @dev: DRM device From 4ce2c7e201c265df1c62a9190a98a98803208b8f Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 17 Feb 2025 12:04:28 +0000 Subject: [PATCH 02/34] drm/panel: ilitek-ili9882t: fix GPIO name in error message This driver uses the enable-gpios property and it is confusing that the error message refers to reset-gpios. Use the correct name when the enable GPIO is not found. Fixes: e2450d32e5fb5 ("drm/panel: ili9882t: Break out as separate driver") Signed-off-by: John Keeping Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20250217120428.3779197-1-jkeeping@inmusicbrands.com --- drivers/gpu/drm/panel/panel-ilitek-ili9882t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index 266a087fe14c..3c24a63b6be8 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -607,7 +607,7 @@ static int ili9882t_add(struct ili9882t *ili) ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ili->enable_gpio)) { - dev_err(dev, "cannot get reset-gpios %ld\n", + dev_err(dev, "cannot get enable-gpios %ld\n", PTR_ERR(ili->enable_gpio)); return PTR_ERR(ili->enable_gpio); } From 60341a6d79aa5e18a9c4ad8d7193e1ec6f8741b0 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Thu, 20 Feb 2025 15:04:06 +0100 Subject: [PATCH 03/34] drm/atomic-helper: Add a note in drm_atomic_helper_reset_crtc() kernel-doc As suggested in [0], add a note indicating that drm_atomic_helper_reset_crtc() can be a no-op in some cases. [0]:https://lore.kernel.org/all/Z7XfnPGDYspwG42y@phenom.ffwll.local/ Signed-off-by: Herve Codina Reviewed-by: Simona Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20250220140406.593314-1-herve.codina@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 7a25e70694ba..5302ab324898 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3409,6 +3409,10 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all); * This implies a reset of all active components available between the CRTC and * connectors. * + * NOTE: This relies on resetting &drm_crtc_state.connectors_changed. + * For drivers which optimize out unnecessary modesets this will result in + * a no-op commit, achieving nothing. + * * Returns: * 0 on success or a negative error code on failure. */ From 27e21f22db9993769b5c983113ccffcac65d772a Mon Sep 17 00:00:00 2001 From: Jeff Hugo Date: Wed, 19 Feb 2025 14:41:12 -0700 Subject: [PATCH 04/34] MAINTAINERS: Update my email address Qualcomm is migrating away from quicinc.com email addresses towards ones with *.qualcomm.com. Signed-off-by: Jeff Hugo Reviewed-by: Bjorn Andersson Link: https://patchwork.freedesktop.org/patch/msgid/20250219214112.2168604-1-jeff.hugo@oss.qualcomm.com --- .mailmap | 3 ++- MAINTAINERS | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index ae0adc499f4a..f4b927e48ad1 100644 --- a/.mailmap +++ b/.mailmap @@ -320,7 +320,8 @@ Jeff Garzik Jeff Layton Jeff Layton Jeff Layton -Jeffrey Hugo +Jeff Hugo +Jeff Hugo Jens Axboe Jens Axboe Jens Axboe diff --git a/MAINTAINERS b/MAINTAINERS index 950e8b7c0805..815a28c7e6fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19426,7 +19426,7 @@ F: drivers/clk/qcom/ F: include/dt-bindings/clock/qcom,* QUALCOMM CLOUD AI (QAIC) DRIVER -M: Jeffrey Hugo +M: Jeff Hugo R: Carl Vanderlip L: linux-arm-msm@vger.kernel.org L: dri-devel@lists.freedesktop.org From acf3256160bdabcb5c07032f3bf6eb5a21f5b95f Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 14 Feb 2025 09:21:09 -0700 Subject: [PATCH 05/34] bus: mhi: host: Avoid possible uninitialized fw_load_type If mhi_fw_load_handler() bails out early because the EE is not capable of loading firmware, we may reference fw_load_type in cleanup which is uninitialized at this point. The cleanup code checks fw_load_type as a proxy for knowing if fbc_image was allocated and needs to be freed, but we can directly test for that. This avoids the possible uninitialized access and appears to be clearer code. Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/e3148ac4-7bb8-422d-ae0f-18a8eb15e269@stanley.mountain/ Fixes: f88f1d0998ea ("bus: mhi: host: Add a policy to enable image transfer via BHIe in PBL") Signed-off-by: Jeffrey Hugo Acked-by: Manivannan Sadhasivam Reviewed-by: Carl Vanderlip Signed-off-by: Jeff Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20250214162109.3555300-1-quic_jhugo@quicinc.com --- drivers/bus/mhi/host/boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c index c8e48f621a8c..efa3b6dddf4d 100644 --- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -608,7 +608,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) return; error_ready_state: - if (fw_load_type == MHI_FW_LOAD_FBC) { + if (mhi_cntrl->fbc_image) { mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); mhi_cntrl->fbc_image = NULL; } From b6eb664d89e7ed1e3369fe2860fea31e6dc45e34 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:33 +0000 Subject: [PATCH 06/34] drm/sched: Add internal job peek/pop API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Idea is to add helpers for peeking and popping jobs from entities with the goal of decoupling the hidden assumption in the code that queue_node is the first element in struct drm_sched_job. That assumption usually comes in the form of: while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) Which breaks if the queue_node is re-positioned due to_drm_sched_job being implemented with a container_of. This also allows us to remove duplicate definitions of to_drm_sched_job. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-2-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_entity.c | 11 +++-- drivers/gpu/drm/scheduler/sched_internal.h | 48 ++++++++++++++++++++++ drivers/gpu/drm/scheduler/sched_main.c | 7 ++-- 3 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 drivers/gpu/drm/scheduler/sched_internal.h diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 69bcf0e99d57..a171f05ad761 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -28,10 +28,9 @@ #include #include -#include "gpu_scheduler_trace.h" +#include "sched_internal.h" -#define to_drm_sched_job(sched_job) \ - container_of((sched_job), struct drm_sched_job, queue_node) +#include "gpu_scheduler_trace.h" /** * drm_sched_entity_init - Init a context entity used by scheduler when @@ -255,7 +254,7 @@ static void drm_sched_entity_kill(struct drm_sched_entity *entity) /* The entity is guaranteed to not be used by the scheduler */ prev = rcu_dereference_check(entity->last_scheduled, true); dma_fence_get(prev); - while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) { + while ((job = drm_sched_entity_queue_pop(entity))) { struct drm_sched_fence *s_fence = job->s_fence; dma_fence_get(&s_fence->finished); @@ -477,7 +476,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) { struct drm_sched_job *sched_job; - sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue)); + sched_job = drm_sched_entity_queue_peek(entity); if (!sched_job) return NULL; @@ -513,7 +512,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) { struct drm_sched_job *next; - next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue)); + next = drm_sched_entity_queue_peek(entity); if (next) { struct drm_sched_rq *rq; diff --git a/drivers/gpu/drm/scheduler/sched_internal.h b/drivers/gpu/drm/scheduler/sched_internal.h new file mode 100644 index 000000000000..bd34898911d7 --- /dev/null +++ b/drivers/gpu/drm/scheduler/sched_internal.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef _DRM_GPU_SCHEDULER_INTERNAL_H_ +#define _DRM_GPU_SCHEDULER_INTERNAL_H_ + +/** + * drm_sched_entity_queue_pop - Low level helper for popping queued jobs + * + * @entity: scheduler entity + * + * Low level helper for popping queued jobs. + * + * Returns: The job dequeued or NULL. + */ +static inline struct drm_sched_job * +drm_sched_entity_queue_pop(struct drm_sched_entity *entity) +{ + struct spsc_node *node; + + node = spsc_queue_pop(&entity->job_queue); + if (!node) + return NULL; + + return container_of(node, struct drm_sched_job, queue_node); +} + +/** + * drm_sched_entity_queue_peek - Low level helper for peeking at the job queue + * + * @entity: scheduler entity + * + * Low level helper for peeking at the job queue + * + * Returns: The job at the head of the queue or NULL. + */ +static inline struct drm_sched_job * +drm_sched_entity_queue_peek(struct drm_sched_entity *entity) +{ + struct spsc_node *node; + + node = spsc_queue_peek(&entity->job_queue); + if (!node) + return NULL; + + return container_of(node, struct drm_sched_job, queue_node); +} + +#endif diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 8c36a59afb72..c634993f1346 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -78,6 +78,8 @@ #include #include +#include "sched_internal.h" + #define CREATE_TRACE_POINTS #include "gpu_scheduler_trace.h" @@ -87,9 +89,6 @@ static struct lockdep_map drm_sched_lockdep_map = { }; #endif -#define to_drm_sched_job(sched_job) \ - container_of((sched_job), struct drm_sched_job, queue_node) - int drm_sched_policy = DRM_SCHED_POLICY_FIFO; /** @@ -123,7 +122,7 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched, { struct drm_sched_job *s_job; - s_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue)); + s_job = drm_sched_entity_queue_peek(entity); if (!s_job) return false; From 80b6ef8ae25ade45e6418df3ddf699a5a10a7ca4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:34 +0000 Subject: [PATCH 07/34] drm/amdgpu: Pop jobs from the queue more robustly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace a copy of DRM scheduler's to_drm_sched_job with a copy of a newly added drm_sched_entity_queue_pop. This allows breaking the hidden dependency that queue_node has to be the first element in struct drm_sched_job. A comment is also added with a reference to the mailing list discussion explaining the copied helper will be removed when the whole broken amdgpu_job_stop_all_jobs_on_sched is removed. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Cc: Zhang, Hawking Reviewed-by: Christian König Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-3-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 100f04475943..1899c601c95c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -411,8 +411,24 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) return fence; } -#define to_drm_sched_job(sched_job) \ - container_of((sched_job), struct drm_sched_job, queue_node) +/* + * This is a duplicate function from DRM scheduler sched_internal.h. + * Plan is to remove it when amdgpu_job_stop_all_jobs_on_sched is removed, due + * latter being incorrect and racy. + * + * See https://lore.kernel.org/amd-gfx/44edde63-7181-44fb-a4f7-94e50514f539@amd.com/ + */ +static struct drm_sched_job * +drm_sched_entity_queue_pop(struct drm_sched_entity *entity) +{ + struct spsc_node *node; + + node = spsc_queue_pop(&entity->job_queue); + if (!node) + return NULL; + + return container_of(node, struct drm_sched_job, queue_node); +} void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched) { @@ -425,7 +441,7 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched) struct drm_sched_rq *rq = sched->sched_rq[i]; spin_lock(&rq->lock); list_for_each_entry(s_entity, &rq->entities, list) { - while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) { + while ((s_job = drm_sched_entity_queue_pop(s_entity))) { struct drm_sched_fence *s_fence = s_job->s_fence; dma_fence_signal(&s_fence->scheduled); From b76f1467dc56fccecfdd63357e2c71542ecd96c5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:35 +0000 Subject: [PATCH 08/34] drm/sched: Remove a hole from struct drm_sched_job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can re-order some struct members and take u32 credits outside of the pointer sandwich and also for the last_dependency member we can get away with an unsigned int since for dependency we use xa_limit_32b. Pahole report before: /* size: 160, cachelines: 3, members: 14 */ /* sum members: 156, holes: 1, sum holes: 4 */ /* last cacheline: 32 bytes */ And after: /* size: 152, cachelines: 3, members: 14 */ /* last cacheline: 24 bytes */ Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Acked-by: Danilo Krummrich Acked-by: Christian König Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-4-tvrtko.ursulin@igalia.com --- include/drm/gpu_scheduler.h | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 6bf458dbce84..1c1138308e66 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -338,8 +338,14 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f); * to schedule the job. */ struct drm_sched_job { - struct spsc_node queue_node; - struct list_head list; + u64 id; + + /** + * @submit_ts: + * + * When the job was pushed into the entity queue. + */ + ktime_t submit_ts; /** * @sched: @@ -349,24 +355,30 @@ struct drm_sched_job { * has finished. */ struct drm_gpu_scheduler *sched; + struct drm_sched_fence *s_fence; + struct drm_sched_entity *entity; + enum drm_sched_priority s_priority; u32 credits; + /** @last_dependency: tracks @dependencies as they signal */ + unsigned int last_dependency; + atomic_t karma; + + struct spsc_node queue_node; + struct list_head list; /* * work is used only after finish_cb has been used and will not be * accessed anymore. */ union { - struct dma_fence_cb finish_cb; - struct work_struct work; + struct dma_fence_cb finish_cb; + struct work_struct work; }; - uint64_t id; - atomic_t karma; - enum drm_sched_priority s_priority; - struct drm_sched_entity *entity; struct dma_fence_cb cb; + /** * @dependencies: * @@ -375,16 +387,6 @@ struct drm_sched_job { * drm_sched_job_add_implicit_dependencies(). */ struct xarray dependencies; - - /** @last_dependency: tracks @dependencies as they signal */ - unsigned long last_dependency; - - /** - * @submit_ts: - * - * When the job was pushed into the entity queue. - */ - ktime_t submit_ts; }; static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job, From 4b7320bfd49dcaf33ef8ab724b88f7baf6bd9978 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:36 +0000 Subject: [PATCH 09/34] drm/sched: Move drm_sched_entity_is_ready to internal header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helper is for scheduler internal use so lets hide it from DRM drivers completely. At the same time we change the method of checking whethere there is anything in the queue from peeking to looking at the node count. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-5-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_entity.c | 12 ------------ drivers/gpu/drm/scheduler/sched_internal.h | 13 +++++++++++++ include/drm/gpu_scheduler.h | 1 - 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index a171f05ad761..87f88259ddf6 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -151,18 +151,6 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) return false; } -/* Return true if entity could provide a job. */ -bool drm_sched_entity_is_ready(struct drm_sched_entity *entity) -{ - if (spsc_queue_peek(&entity->job_queue) == NULL) - return false; - - if (READ_ONCE(entity->dependency)) - return false; - - return true; -} - /** * drm_sched_entity_error - return error of last scheduled job * @entity: scheduler entity to check diff --git a/drivers/gpu/drm/scheduler/sched_internal.h b/drivers/gpu/drm/scheduler/sched_internal.h index bd34898911d7..23ceda8c32e5 100644 --- a/drivers/gpu/drm/scheduler/sched_internal.h +++ b/drivers/gpu/drm/scheduler/sched_internal.h @@ -45,4 +45,17 @@ drm_sched_entity_queue_peek(struct drm_sched_entity *entity) return container_of(node, struct drm_sched_job, queue_node); } +/* Return true if entity could provide a job. */ +static inline bool +drm_sched_entity_is_ready(struct drm_sched_entity *entity) +{ + if (!spsc_queue_count(&entity->job_queue)) + return false; + + if (READ_ONCE(entity->dependency)) + return false; + + return true; +} + #endif diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 1c1138308e66..6cd0f288f6ed 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -632,7 +632,6 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity); void drm_sched_entity_push_job(struct drm_sched_job *sched_job); void drm_sched_entity_set_priority(struct drm_sched_entity *entity, enum drm_sched_priority priority); -bool drm_sched_entity_is_ready(struct drm_sched_entity *entity); int drm_sched_entity_error(struct drm_sched_entity *entity); struct drm_sched_fence *drm_sched_fence_alloc( From 71a18f7266f301b20faf9f5fd7aee228c83bb4a3 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:37 +0000 Subject: [PATCH 10/34] drm/sched: Move internal prototypes to internal header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have a header file for internal scheduler interfaces we can move some more prototypes into it. By doing that we eliminate the chance of drivers trying to use something which was not intended to be used. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-6-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/scheduler/sched_fence.c | 2 ++ drivers/gpu/drm/scheduler/sched_internal.h | 30 ++++++++++++++++++++++ include/drm/gpu_scheduler.h | 27 ------------------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index 0f35f009b9d3..e971528504a5 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -29,6 +29,8 @@ #include +#include "sched_internal.h" + static struct kmem_cache *sched_fence_slab; static int __init drm_sched_fence_slab_init(void) diff --git a/drivers/gpu/drm/scheduler/sched_internal.h b/drivers/gpu/drm/scheduler/sched_internal.h index 23ceda8c32e5..599cf6e1bb74 100644 --- a/drivers/gpu/drm/scheduler/sched_internal.h +++ b/drivers/gpu/drm/scheduler/sched_internal.h @@ -3,6 +3,36 @@ #ifndef _DRM_GPU_SCHEDULER_INTERNAL_H_ #define _DRM_GPU_SCHEDULER_INTERNAL_H_ + +/* Used to choose between FIFO and RR job-scheduling */ +extern int drm_sched_policy; + +#define DRM_SCHED_POLICY_RR 0 +#define DRM_SCHED_POLICY_FIFO 1 + +void drm_sched_wakeup(struct drm_gpu_scheduler *sched); + +void drm_sched_rq_add_entity(struct drm_sched_rq *rq, + struct drm_sched_entity *entity); +void drm_sched_rq_remove_entity(struct drm_sched_rq *rq, + struct drm_sched_entity *entity); + +void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity, + struct drm_sched_rq *rq, ktime_t ts); + +void drm_sched_entity_select_rq(struct drm_sched_entity *entity); +struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity); + +struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *s_entity, + void *owner); +void drm_sched_fence_init(struct drm_sched_fence *fence, + struct drm_sched_entity *entity); +void drm_sched_fence_free(struct drm_sched_fence *fence); + +void drm_sched_fence_scheduled(struct drm_sched_fence *fence, + struct dma_fence *parent); +void drm_sched_fence_finished(struct drm_sched_fence *fence, int result); + /** * drm_sched_entity_queue_pop - Low level helper for popping queued jobs * diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 6cd0f288f6ed..8cb12f6231b8 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -71,12 +71,6 @@ enum drm_sched_priority { DRM_SCHED_PRIORITY_COUNT }; -/* Used to choose between FIFO and RR job-scheduling */ -extern int drm_sched_policy; - -#define DRM_SCHED_POLICY_RR 0 -#define DRM_SCHED_POLICY_FIFO 1 - /** * struct drm_sched_entity - A wrapper around a job queue (typically * attached to the DRM file_priv). @@ -601,7 +595,6 @@ void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, void drm_sched_tdr_queue_imm(struct drm_gpu_scheduler *sched); void drm_sched_job_cleanup(struct drm_sched_job *job); -void drm_sched_wakeup(struct drm_gpu_scheduler *sched); bool drm_sched_wqueue_ready(struct drm_gpu_scheduler *sched); void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched); void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched); @@ -611,14 +604,6 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched); void drm_sched_increase_karma(struct drm_sched_job *bad); void drm_sched_fault(struct drm_gpu_scheduler *sched); -void drm_sched_rq_add_entity(struct drm_sched_rq *rq, - struct drm_sched_entity *entity); -void drm_sched_rq_remove_entity(struct drm_sched_rq *rq, - struct drm_sched_entity *entity); - -void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity, - struct drm_sched_rq *rq, ktime_t ts); - int drm_sched_entity_init(struct drm_sched_entity *entity, enum drm_sched_priority priority, struct drm_gpu_scheduler **sched_list, @@ -627,23 +612,11 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout); void drm_sched_entity_fini(struct drm_sched_entity *entity); void drm_sched_entity_destroy(struct drm_sched_entity *entity); -void drm_sched_entity_select_rq(struct drm_sched_entity *entity); -struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity); void drm_sched_entity_push_job(struct drm_sched_job *sched_job); void drm_sched_entity_set_priority(struct drm_sched_entity *entity, enum drm_sched_priority priority); int drm_sched_entity_error(struct drm_sched_entity *entity); -struct drm_sched_fence *drm_sched_fence_alloc( - struct drm_sched_entity *s_entity, void *owner); -void drm_sched_fence_init(struct drm_sched_fence *fence, - struct drm_sched_entity *entity); -void drm_sched_fence_free(struct drm_sched_fence *fence); - -void drm_sched_fence_scheduled(struct drm_sched_fence *fence, - struct dma_fence *parent); -void drm_sched_fence_finished(struct drm_sched_fence *fence, int result); - unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched); void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, unsigned long remaining); From 27d4815149ba0c80ef2db2a82f0512f647e76d62 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 21 Feb 2025 10:50:38 +0000 Subject: [PATCH 11/34] drm/sched: Group exported prototypes by object type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do a bit of house keeping in gpu_scheduler.h by grouping the API by type of object it operates on. Signed-off-by: Tvrtko Ursulin Cc: Christian König Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250221105038.79665-7-tvrtko.ursulin@igalia.com --- include/drm/gpu_scheduler.h | 60 ++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 8cb12f6231b8..50928a7ae98e 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -383,12 +383,6 @@ struct drm_sched_job { struct xarray dependencies; }; -static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job, - int threshold) -{ - return s_job && atomic_inc_return(&s_job->karma) > threshold; -} - enum drm_gpu_sched_stat { DRM_GPU_SCHED_STAT_NONE, /* Reserve 0 */ DRM_GPU_SCHED_STAT_NOMINAL, @@ -566,14 +560,36 @@ struct drm_sched_init_args { struct device *dev; }; +/* Scheduler operations */ + int drm_sched_init(struct drm_gpu_scheduler *sched, const struct drm_sched_init_args *args); void drm_sched_fini(struct drm_gpu_scheduler *sched); + +unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched); +void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, + unsigned long remaining); +void drm_sched_tdr_queue_imm(struct drm_gpu_scheduler *sched); +bool drm_sched_wqueue_ready(struct drm_gpu_scheduler *sched); +void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched); +void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched); +void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad); +void drm_sched_start(struct drm_gpu_scheduler *sched, int errno); +void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched); +void drm_sched_fault(struct drm_gpu_scheduler *sched); + +struct drm_gpu_scheduler * +drm_sched_pick_best(struct drm_gpu_scheduler **sched_list, + unsigned int num_sched_list); + +/* Jobs */ + int drm_sched_job_init(struct drm_sched_job *job, struct drm_sched_entity *entity, u32 credits, void *owner); void drm_sched_job_arm(struct drm_sched_job *job); +void drm_sched_entity_push_job(struct drm_sched_job *sched_job); int drm_sched_job_add_dependency(struct drm_sched_job *job, struct dma_fence *fence); int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job, @@ -588,21 +604,16 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job, bool write); bool drm_sched_job_has_dependency(struct drm_sched_job *job, struct dma_fence *fence); - -void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, - struct drm_gpu_scheduler **sched_list, - unsigned int num_sched_list); - -void drm_sched_tdr_queue_imm(struct drm_gpu_scheduler *sched); void drm_sched_job_cleanup(struct drm_sched_job *job); -bool drm_sched_wqueue_ready(struct drm_gpu_scheduler *sched); -void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched); -void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched); -void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad); -void drm_sched_start(struct drm_gpu_scheduler *sched, int errno); -void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched); void drm_sched_increase_karma(struct drm_sched_job *bad); -void drm_sched_fault(struct drm_gpu_scheduler *sched); + +static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job, + int threshold) +{ + return s_job && atomic_inc_return(&s_job->karma) > threshold; +} + +/* Entities */ int drm_sched_entity_init(struct drm_sched_entity *entity, enum drm_sched_priority priority, @@ -612,16 +623,11 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout); void drm_sched_entity_fini(struct drm_sched_entity *entity); void drm_sched_entity_destroy(struct drm_sched_entity *entity); -void drm_sched_entity_push_job(struct drm_sched_job *sched_job); void drm_sched_entity_set_priority(struct drm_sched_entity *entity, enum drm_sched_priority priority); int drm_sched_entity_error(struct drm_sched_entity *entity); - -unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched); -void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, - unsigned long remaining); -struct drm_gpu_scheduler * -drm_sched_pick_best(struct drm_gpu_scheduler **sched_list, - unsigned int num_sched_list); +void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, + struct drm_gpu_scheduler **sched_list, + unsigned int num_sched_list); #endif From ed531feda7852de0aa702fbe3d23a0f743ccc77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Feb 2025 18:49:36 +0100 Subject: [PATCH 12/34] drm/bridge: ti-sn65dsi86: Check for CONFIG_PWM using IS_REACHABLE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently CONFIG_PWM is a bool but I intend to change it to tristate. If CONFIG_PWM=m in the configuration, the cpp symbol CONFIG_PWM isn't defined and so the PWM code paths in the ti-sn65dsi86 driver are not used. The correct way to check for CONFIG_PWM is using IS_REACHABLE which does the right thing for all cases CONFIG_DRM_TI_SN65DSI86 ∈ { y, m } x CONFIG_PWM ∈ { y, m, n }. There is no change until CONFIG_PWM actually becomes tristate. Signed-off-by: Uwe Kleine-König Reviewed-by: Louis Chauvet Reviewed-by: Robert Foss Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250217174936.758420-2-u.kleine-koenig@baylibre.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index ae34585e05b3..01d456b955ab 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -195,7 +195,7 @@ struct ti_sn65dsi86 { struct gpio_chip gchip; DECLARE_BITMAP(gchip_output, SN_NUM_GPIOS); #endif -#if defined(CONFIG_PWM) +#if IS_REACHABLE(CONFIG_PWM) struct pwm_chip *pchip; bool pwm_enabled; atomic_t pwm_pin_busy; @@ -1362,7 +1362,7 @@ static struct auxiliary_driver ti_sn_bridge_driver = { /* ----------------------------------------------------------------------------- * PWM Controller */ -#if defined(CONFIG_PWM) +#if IS_REACHABLE(CONFIG_PWM) static int ti_sn_pwm_pin_request(struct ti_sn65dsi86 *pdata) { return atomic_xchg(&pdata->pwm_pin_busy, 1) ? -EBUSY : 0; @@ -1956,7 +1956,7 @@ static int ti_sn65dsi86_probe(struct i2c_client *client) return ret; } - if (IS_ENABLED(CONFIG_PWM)) { + if (IS_REACHABLE(CONFIG_PWM)) { ret = ti_sn65dsi86_add_aux_device(pdata, &pdata->pwm_aux, "pwm"); if (ret) return ret; From 4d098000ac193f359e6b8ca4801dbdbd6a27b41f Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Thu, 16 Jan 2025 05:48:01 -0800 Subject: [PATCH 13/34] drm/repaper: fix integer overflows in repeat functions There are conditions, albeit somewhat unlikely, under which right hand expressions, calculating the end of time period in functions like repaper_frame_fixed_repeat(), may overflow. For instance, if 'factor10x' in repaper_get_temperature() is high enough (170), as is 'epd->stage_time' in repaper_probe(), then the resulting value of 'end' will not fit in unsigned int expression. Mitigate this by casting 'epd->factored_stage_time' to wider type before any multiplication is done. Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: 3589211e9b03 ("drm/tinydrm: Add RePaper e-ink driver") Cc: stable@vger.kernel.org Signed-off-by: Nikita Zhandarovich Signed-off-by: Alex Lanzano Link: https://patchwork.freedesktop.org/patch/msgid/20250116134801.22067-1-n.zhandarovich@fintech.ru --- drivers/gpu/drm/tiny/repaper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 52ba6c699bc8..5c3b51eb0a97 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -456,7 +456,7 @@ static void repaper_frame_fixed_repeat(struct repaper_epd *epd, u8 fixed_value, enum repaper_stage stage) { u64 start = local_clock(); - u64 end = start + (epd->factored_stage_time * 1000 * 1000); + u64 end = start + ((u64)epd->factored_stage_time * 1000 * 1000); do { repaper_frame_fixed(epd, fixed_value, stage); @@ -467,7 +467,7 @@ static void repaper_frame_data_repeat(struct repaper_epd *epd, const u8 *image, const u8 *mask, enum repaper_stage stage) { u64 start = local_clock(); - u64 end = start + (epd->factored_stage_time * 1000 * 1000); + u64 end = start + ((u64)epd->factored_stage_time * 1000 * 1000); do { repaper_frame_data(epd, image, mask, stage); From fb13d3497bdcf4f544be25f716b6bdf1a4f8e63a Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Thu, 20 Feb 2025 10:27:21 +0530 Subject: [PATCH 14/34] drm/mipi-dsi: extend "multi" functions and use them in sony-td4353-jdi Removes mipi_dsi_dcs_set_tear_off and replaces it with a multi version as after replacing it in sony-td4353-jdi, it doesn't appear anywhere else. sony-td4353-jdi is converted to use multi style functions, including mipi_dsi_dcs_set_tear_off_multi. Signed-off-by: Tejas Vipin Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20250220045721.145905-1-tejasvipin76@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250220045721.145905-1-tejasvipin76@gmail.com --- drivers/gpu/drm/drm_mipi_dsi.c | 42 +++---- drivers/gpu/drm/panel/panel-sony-td4353-jdi.c | 107 ++++-------------- include/drm/drm_mipi_dsi.h | 2 +- 3 files changed, 47 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 5e5c5f84daac..2e148753ea97 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -1265,25 +1265,6 @@ int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, } EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address); -/** - * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect - * output signal on the TE signal line - * @dsi: DSI peripheral device - * - * Return: 0 on success or a negative error code on failure - */ -int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi) -{ - ssize_t err; - - err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off); - /** * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect * output signal on the TE signal line. @@ -1713,6 +1694,29 @@ void mipi_dsi_turn_on_peripheral_multi(struct mipi_dsi_multi_context *ctx) } EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral_multi); +/** + * mipi_dsi_dcs_set_tear_off_multi() - turn off the display module's Tearing Effect + * output signal on the TE signal line + * @ctx: Context for multiple DSI transactions + */ +void mipi_dsi_dcs_set_tear_off_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t err; + + if (ctx->accum_err) + return; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0); + if (err < 0) { + ctx->accum_err = err; + dev_err(dev, "Failed to set tear off: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off_multi); + /** * mipi_dsi_dcs_soft_reset_multi() - perform a software reset of the display module * @ctx: Context for multiple DSI transactions diff --git a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c index 472195d4bbbe..97f4bb4e1029 100644 --- a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c +++ b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c @@ -47,93 +47,40 @@ static inline struct sony_td4353_jdi *to_sony_td4353_jdi(struct drm_panel *panel static int sony_td4353_jdi_on(struct sony_td4353_jdi *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 1080 - 1); - if (ret < 0) { - dev_err(dev, "Failed to set column address: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 2160 - 1); - if (ret < 0) { - dev_err(dev, "Failed to set page address: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0); - if (ret < 0) { - dev_err(dev, "Failed to set tear scanline: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - if (ret < 0) { - dev_err(dev, "Failed to set tear on: %d\n", ret); - return ret; - } + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 1080 - 1); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 2160 - 1); + mipi_dsi_dcs_set_tear_scanline_multi(&dsi_ctx, 0); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00); - - ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77); - if (ret < 0) { - dev_err(dev, "Failed to set pixel format: %d\n", ret); - return ret; - } - - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, - 0x00, 0x00, 0x08, 0x6f); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(70); + mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_PARTIAL_ROWS, + 0x00, 0x00, 0x08, 0x6f); - mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to turn display on: %d\n", ret); - return ret; - } - - return 0; + return dsi_ctx.accum_err; } -static int sony_td4353_jdi_off(struct sony_td4353_jdi *ctx) +static void sony_td4353_jdi_off(struct sony_td4353_jdi *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(22); - - ret = mipi_dsi_dcs_set_tear_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set tear off: %d\n", ret); - return ret; - } - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(80); - - return 0; + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 22); + mipi_dsi_dcs_set_tear_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 80); } static void sony_td4353_assert_reset_gpios(struct sony_td4353_jdi *ctx, int mode) @@ -146,14 +93,11 @@ static void sony_td4353_assert_reset_gpios(struct sony_td4353_jdi *ctx, int mode static int sony_td4353_jdi_prepare(struct drm_panel *panel) { struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel); - struct device *dev = &ctx->dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + if (ret < 0) return ret; - } msleep(100); @@ -161,7 +105,6 @@ static int sony_td4353_jdi_prepare(struct drm_panel *panel) ret = sony_td4353_jdi_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to power on panel: %d\n", ret); sony_td4353_assert_reset_gpios(ctx, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return ret; @@ -173,12 +116,8 @@ static int sony_td4353_jdi_prepare(struct drm_panel *panel) static int sony_td4353_jdi_unprepare(struct drm_panel *panel) { struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = sony_td4353_jdi_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to power off panel: %d\n", ret); + sony_td4353_jdi_off(ctx); sony_td4353_assert_reset_gpios(ctx, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 94400a78031f..bd40a443385c 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -346,7 +346,6 @@ int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, u16 end); int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, u16 end); -int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi); int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, enum mipi_dsi_dcs_tear_mode mode); int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format); @@ -379,6 +378,7 @@ void mipi_dsi_dcs_set_page_address_multi(struct mipi_dsi_multi_context *ctx, u16 start, u16 end); void mipi_dsi_dcs_set_tear_scanline_multi(struct mipi_dsi_multi_context *ctx, u16 scanline); +void mipi_dsi_dcs_set_tear_off_multi(struct mipi_dsi_multi_context *ctx); /** * mipi_dsi_generic_write_seq - transmit data using a generic write packet From 761992a4b4deacb519f4a6089936b7fd22b4aa0a Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Mon, 24 Feb 2025 14:50:51 +0100 Subject: [PATCH 15/34] dt-bindings: display: simple: add BOE AV101HDT-A10 panel add a compatible string for the BOE AV101HDT-A10 10.1" LVDS panel Signed-off-by: Maud Spierings Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250224-initial_display-v1-1-5ccbbf613543@gocontroll.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250224-initial_display-v1-1-5ccbbf613543@gocontroll.com --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index e3ee3a332bb7..b0de4fd6f3d4 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -63,6 +63,8 @@ properties: - auo,t215hvn01 # Shanghai AVIC Optoelectronics 7" 1024x600 color TFT-LCD panel - avic,tm070ddh03 + # BOE AV101HDT-a10 10.1" 1280x720 LVDS panel + - boe,av101hdt-a10 # BOE BP082WX1-100 8.2" WXGA (1280x800) LVDS panel - boe,bp082wx1-100 # BOE BP101WX1-100 10.1" WXGA (1280x800) LVDS panel From 1a4d1d9f068506f4f334c03514d2e93e21830f19 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Mon, 24 Feb 2025 14:50:52 +0100 Subject: [PATCH 16/34] dt-bindings: display: simple: Add BOE AV123Z7M-N17 panel Add support for the BOE AV123Z7M-N17 12.3" LVDS panel. Signed-off-by: Maud Spierings Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250224-initial_display-v1-2-5ccbbf613543@gocontroll.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250224-initial_display-v1-2-5ccbbf613543@gocontroll.com --- .../bindings/display/panel/panel-simple-lvds-dual-ports.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml index e80fc7006984..548f5ac14500 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml @@ -40,6 +40,8 @@ properties: - auo,g185han01 # AU Optronics Corporation 19.0" (1280x1024) TFT LCD panel - auo,g190ean01 + # BOE AV123Z7M-N17 12.3" (1920x720) LVDS TFT LCD panel + - boe,av123z7m-n17 # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel - koe,tx26d202vm0bwa # Lincoln Technology Solutions, LCD185-101CT 10.1" TFT 1920x1200 From b554c009da1c3c6cb8c4b5da2ac2f37fb527e927 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Mon, 24 Feb 2025 14:50:57 +0100 Subject: [PATCH 17/34] drm/panel: simple: add BOE AV101HDT-A10 panel add support for the BOE AV101HDT-A10 10.1" LVDS panel Signed-off-by: Maud Spierings Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250224-initial_display-v1-7-5ccbbf613543@gocontroll.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250224-initial_display-v1-7-5ccbbf613543@gocontroll.com --- drivers/gpu/drm/panel/panel-simple.c | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9b2f128fd309..a52977ab73dc 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1374,6 +1374,35 @@ static const struct panel_desc bananapi_s070wv20_ct16 = { }, }; +static const struct display_timing boe_av101hdt_a10_timing = { + .pixelclock = { 74210000, 75330000, 76780000, }, + .hactive = { 1280, 1280, 1280, }, + .hfront_porch = { 10, 42, 33, }, + .hback_porch = { 10, 18, 33, }, + .hsync_len = { 30, 10, 30, }, + .vactive = { 720, 720, 720, }, + .vfront_porch = { 200, 183, 200, }, + .vback_porch = { 8, 8, 8, }, + .vsync_len = { 2, 19, 2, }, + .flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc boe_av101hdt_a10 = { + .timings = &boe_av101hdt_a10_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 224, + .height = 126, + }, + .delay = { + .enable = 50, + .disable = 50, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode boe_bp101wx1_100_mode = { .clock = 78945, .hdisplay = 1280, @@ -4813,6 +4842,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "bananapi,s070wv20-ct16", .data = &bananapi_s070wv20_ct16, + }, { + .compatible = "boe,av101hdt-a10", + .data = &boe_av101hdt_a10, }, { .compatible = "boe,bp082wx1-100", .data = &boe_bp082wx1_100, From d34bd3c7cb84425dd6146a8d07af597b93ad4c4d Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Mon, 24 Feb 2025 14:50:58 +0100 Subject: [PATCH 18/34] drm/panel: simple: Add BOE AV123Z7M-N17 panel Add support for the BOE AV123Z7M-N17 12.3" LVDS panel. Signed-off-by: Maud Spierings Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250224-initial_display-v1-8-5ccbbf613543@gocontroll.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250224-initial_display-v1-8-5ccbbf613543@gocontroll.com --- drivers/gpu/drm/panel/panel-simple.c | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index a52977ab73dc..232b03c1a259 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1403,6 +1403,35 @@ static const struct panel_desc boe_av101hdt_a10 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct display_timing boe_av123z7m_n17_timing = { + .pixelclock = { 86600000, 88000000, 90800000, }, + .hactive = { 1920, 1920, 1920, }, + .hfront_porch = { 10, 10, 10, }, + .hback_porch = { 10, 10, 10, }, + .hsync_len = { 9, 12, 25, }, + .vactive = { 720, 720, 720, }, + .vfront_porch = { 7, 10, 13, }, + .vback_porch = { 7, 10, 13, }, + .vsync_len = { 7, 11, 14, }, + .flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc boe_av123z7m_n17 = { + .timings = &boe_av123z7m_n17_timing, + .bpc = 8, + .num_timings = 1, + .size = { + .width = 292, + .height = 110, + }, + .delay = { + .prepare = 50, + .disable = 50, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode boe_bp101wx1_100_mode = { .clock = 78945, .hdisplay = 1280, @@ -4845,6 +4874,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "boe,av101hdt-a10", .data = &boe_av101hdt_a10, + }, { + .compatible = "boe,av123z7m-n17", + .data = &boe_av123z7m_n17, }, { .compatible = "boe,bp082wx1-100", .data = &boe_bp082wx1_100, From 40115947b59f2ca361a47615304dff0a2b69a2b4 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Mon, 17 Feb 2025 12:39:33 +0100 Subject: [PATCH 19/34] drm: panel: Add a panel driver for the Summit display This is the display panel used for the touchbar on laptops that have it. Co-developed-by: Nick Chan Signed-off-by: Nick Chan Reviewed-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Reviewed-by: Neal Gompa Signed-off-by: Sasha Finkelstein Link: https://lore.kernel.org/r/20250217-adpdrm-v7-3-ca2e44b3c7d8@gmail.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20250217-adpdrm-v7-3-ca2e44b3c7d8@gmail.com --- drivers/gpu/drm/panel/Kconfig | 9 ++ drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-summit.c | 132 +++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-summit.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index d7469c565d1d..5085a82e4bc6 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -925,6 +925,15 @@ config DRM_PANEL_SIMPLE that it can be automatically turned off when the panel goes into a low power state. +config DRM_PANEL_SUMMIT + tristate "Apple Summit display panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for the "Summit" display panel + used as a touchbar on certain Apple laptops. + config DRM_PANEL_SYNAPTICS_R63353 tristate "Synaptics R63353-based panels" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 7dcf72646cac..10ac2e850f5c 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -89,6 +89,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o +obj-$(CONFIG_DRM_PANEL_SUMMIT) += panel-summit.o obj-$(CONFIG_DRM_PANEL_SYNAPTICS_R63353) += panel-synaptics-r63353.o obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DRM_PANEL_SONY_TD4353_JDI) += panel-sony-td4353-jdi.o diff --git a/drivers/gpu/drm/panel/panel-summit.c b/drivers/gpu/drm/panel/panel-summit.c new file mode 100644 index 000000000000..e780faee1857 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-summit.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include