From d223f98f02099b002903b9b22b56febae16ef80d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Apr 2019 15:58:54 -0700 Subject: drm/v3d: Add support for compute shader dispatch. The compute shader dispatch interface is pretty simple -- just pass in the regs that userspace has passed us, with no CLs to run. However, with no CL to run it means that we need to do manual cache flushing of the L2 after the HW execution completes (for SSBO, atomic, and image_load_store writes that are the output of compute shaders). This doesn't yet expose the L2 cache's ability to have a region of the address space not write back to memory (which could be used for shared_var storage). So far, the Mesa side has been tested on V3D v4.2 simpenrose (passing the ES31 tests), and on the kernel side on 7278 (failing atomic compswap tests in a way that doesn't reproduce on simpenrose). v2: Fix excessive allocation for the clean_job (reported by Dan Carpenter). Keep refs on jobs until clean_job is finished, to avoid spurious MMU errors if the output BOs are freed by userspace before L2 cleaning is finished. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20190416225856.20264-4-eric@anholt.net Acked-by: Rob Clark --- include/uapi/drm/v3d_drm.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h index ea70669d2138..58fbe48c91e9 100644 --- a/include/uapi/drm/v3d_drm.h +++ b/include/uapi/drm/v3d_drm.h @@ -37,6 +37,7 @@ extern "C" { #define DRM_V3D_GET_PARAM 0x04 #define DRM_V3D_GET_BO_OFFSET 0x05 #define DRM_V3D_SUBMIT_TFU 0x06 +#define DRM_V3D_SUBMIT_CSD 0x07 #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl) #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo) @@ -45,6 +46,7 @@ extern "C" { #define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param) #define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset) #define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu) +#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd) /** * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D @@ -190,6 +192,7 @@ enum drm_v3d_param { DRM_V3D_PARAM_V3D_CORE0_IDENT1, DRM_V3D_PARAM_V3D_CORE0_IDENT2, DRM_V3D_PARAM_SUPPORTS_TFU, + DRM_V3D_PARAM_SUPPORTS_CSD, }; struct drm_v3d_get_param { @@ -230,6 +233,31 @@ struct drm_v3d_submit_tfu { __u32 out_sync; }; +/* Submits a compute shader for dispatch. This job will block on any + * previous compute shaders submitted on this fd, and any other + * synchronization must be performed with in_sync/out_sync. + */ +struct drm_v3d_submit_csd { + __u32 cfg[7]; + __u32 coef[4]; + + /* Pointer to a u32 array of the BOs that are referenced by the job. + */ + __u64 bo_handles; + + /* Number of BO handles passed in (size is that times 4). */ + __u32 bo_handle_count; + + /* sync object to block on before running the CSD job. Each + * CSD job will execute in the order submitted to its FD. + * Synchronization against rendering/TFU jobs or CSD from + * other fds requires using sync objects. + */ + __u32 in_sync; + /* Sync object to signal when the CSD job is done. */ + __u32 out_sync; +}; + #if defined(__cplusplus) } #endif -- cgit v1.3-6-gb490 From 96354b5ca4ac74d2e47e75987283963001b517f6 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 17 Apr 2019 22:15:19 +0000 Subject: drm: increase drm mmap_range size to 1TB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After patch "drm: Use the same mmap-range offset and size for GEM and TTM", application failed to create bo of system memory because drm mmap_range size decrease to 64GB from original 1TB. This is not big enough for applications. Increase the drm mmap_range size to 1TB. Reviewed-by: Thomas Zimmermann Reviewed-by: Christian König Signed-off-by: Philip Yang Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20190417221507.933-1-Philip.Yang@amd.com --- include/drm/drm_vma_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h index f4f8ff1cdeec..76ac5e97a559 100644 --- a/include/drm/drm_vma_manager.h +++ b/include/drm/drm_vma_manager.h @@ -35,7 +35,7 @@ */ #if BITS_PER_LONG == 64 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) -#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) +#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 256) #else #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) -- cgit v1.3-6-gb490 From 7d26097b4beb802fb6ce7cd6389ac4bf12b1a6ae Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 1 Mar 2019 13:56:12 +0100 Subject: drm/atomic: Create __drm_atomic_helper_crtc_reset() for subclassing crtc_state. We already have __drm_atomic_helper_connector_reset() and __drm_atomic_helper_plane_reset(), extend this to crtc as well. This will allow us to set default values in the crtc_state, without having to do it in each driver separately. Of all drivers that need conversion, only nouveau is done in this commit, because it wrote its own __drm_atomic_helper_crtc_reset(), clashing with the drm core. Signed-off-by: Maarten Lankhorst Cc: Ben Skeggs Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20190301125627.7285-3-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_state_helper.c | 34 +++++++++++++++++++++++++------ drivers/gpu/drm/nouveau/dispnv50/head.c | 13 +++--------- include/drm/drm_atomic_state_helper.h | 2 ++ 3 files changed, 33 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 59ffb6b9c745..06a97a268e81 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -56,6 +56,29 @@ * for these functions. */ +/** + * __drm_atomic_helper_crtc_reset - reset state on CRTC + * @crtc: drm CRTC + * @crtc_state: CRTC state to assign + * + * Initializes the newly allocated @crtc_state and assigns it to + * the &drm_crtc->state pointer of @crtc, usually required when + * initializing the drivers or when called from the &drm_crtc_funcs.reset + * hook. + * + * This is useful for drivers that subclass the CRTC state. + */ +void +__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + if (crtc_state) + crtc_state->crtc = crtc; + + crtc->state = crtc_state; +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_reset); + /** * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs * @crtc: drm CRTC @@ -65,14 +88,13 @@ */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) { - if (crtc->state) - __drm_atomic_helper_crtc_destroy_state(crtc->state); - - kfree(crtc->state); - crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); + struct drm_crtc_state *crtc_state = + kzalloc(sizeof(*crtc->state), GFP_KERNEL); if (crtc->state) - crtc->state->crtc = crtc; + crtc->funcs->atomic_destroy_state(crtc, crtc->state); + + __drm_atomic_helper_crtc_reset(crtc, crtc_state); } EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 2e7a0c347ddb..93754743090f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -419,16 +419,6 @@ nv50_head_atomic_duplicate_state(struct drm_crtc *crtc) return &asyh->state; } -static void -__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - if (crtc->state) - crtc->funcs->atomic_destroy_state(crtc, crtc->state); - crtc->state = state; - crtc->state->crtc = crtc; -} - static void nv50_head_reset(struct drm_crtc *crtc) { @@ -437,6 +427,9 @@ nv50_head_reset(struct drm_crtc *crtc) if (WARN_ON(!(asyh = kzalloc(sizeof(*asyh), GFP_KERNEL)))) return; + if (crtc->state) + nv50_head_atomic_destroy_state(crtc, crtc->state); + __drm_atomic_helper_crtc_reset(crtc, &asyh->state); } diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 66c92cbd8e16..4e6d2e7a40b8 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -37,6 +37,8 @@ struct drm_private_state; struct drm_modeset_acquire_ctx; struct drm_device; +void __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, + struct drm_crtc_state *state); void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, struct drm_crtc_state *state); -- cgit v1.3-6-gb490 From 67b886d290052dbf2bcfc876a5ae41a5fe461edf Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Thu, 21 Mar 2019 15:09:56 -0500 Subject: dma-buf: Remove leftover [un]map_atomic comments The map_atomic/unmap_atomic callbacks have been removed, remove the related comments. Fixes: f664a5269542 ("dma-buf: remove kmap_atomic interface") Signed-off-by: Andrew F. Davis Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20190321200957.16938-1-afd@ti.com --- include/linux/dma-buf.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include') diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 58725f890b5b..e4a8dab2bc54 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -39,11 +39,6 @@ struct dma_buf_attachment; /** * struct dma_buf_ops - operations possible on struct dma_buf - * @map_atomic: [optional] maps a page from the buffer into kernel address - * space, users may not block until the subsequent unmap call. - * This callback must not sleep. - * @unmap_atomic: [optional] unmaps a atomically mapped page from the buffer. - * This Callback must not sleep. * @map: [optional] maps a page from the buffer into kernel address space. * @unmap: [optional] unmaps a page from the buffer. * @vmap: [optional] creates a virtual mapping for the buffer into kernel -- cgit v1.3-6-gb490 From d5ae7712b7ffbb435e8f3d98f2123eff4734c77f Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Thu, 21 Mar 2019 15:09:57 -0500 Subject: dma-buf: Update [un]map documentation to match the other functions Other function have inline documentation, a couple still have theirs at the top of the structure, update the docs and move them inline. Signed-off-by: Andrew F. Davis Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20190321200957.16938-2-afd@ti.com --- include/linux/dma-buf.h | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index e4a8dab2bc54..a0bd071466fc 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -39,8 +39,6 @@ struct dma_buf_attachment; /** * struct dma_buf_ops - operations possible on struct dma_buf - * @map: [optional] maps a page from the buffer into kernel address space. - * @unmap: [optional] unmaps a page from the buffer. * @vmap: [optional] creates a virtual mapping for the buffer into kernel * address space. Same restrictions as for vmap and friends apply. * @vunmap: [optional] unmaps a vmap from the buffer @@ -200,8 +198,6 @@ struct dma_buf_ops { * to be restarted. */ int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); - void *(*map)(struct dma_buf *, unsigned long); - void (*unmap)(struct dma_buf *, unsigned long, void *); /** * @mmap: @@ -240,6 +236,31 @@ struct dma_buf_ops { */ int (*mmap)(struct dma_buf *, struct vm_area_struct *vma); + /** + * @map: + * + * Maps a page from the buffer into kernel address space. The page is + * specified by offset into the buffer in PAGE_SIZE units. + * + * This callback is optional. + * + * Returns: + * + * Virtual address pointer where requested page can be accessed. NULL + * on error or when this function is unimplemented by the exporter. + */ + void *(*map)(struct dma_buf *, unsigned long); + + /** + * @unmap: + * + * Unmaps a page from the buffer. Page offset and address pointer should + * be the same as the one passed to and returned by matching call to map. + * + * This callback is optional. + */ + void (*unmap)(struct dma_buf *, unsigned long, void *); + void *(*vmap)(struct dma_buf *); void (*vunmap)(struct dma_buf *, void *vaddr); }; -- cgit v1.3-6-gb490 From 5918045c4ed492fb5813f980dcf89a90fefd0a4e Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 18 Apr 2019 11:00:21 -0400 Subject: drm/scheduler: rework job destruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now destroy finished jobs from the worker thread to make sure that we never destroy a job currently in timeout processing. By this we avoid holding lock around ring mirror list in drm_sched_stop which should solve a deadlock reported by a user. v2: Remove unused variable. v4: Move guilty job free into sched code. v5: Move sched->hw_rq_count to drm_sched_start to account for counter decrement in drm_sched_stop even when we don't call resubmit jobs if guily job did signal. v6: remove unused variable Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109692 Acked-by: Chunming Zhou Signed-off-by: Christian König Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/1555599624-12285-3-git-send-email-andrey.grodzovsky@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 +- drivers/gpu/drm/etnaviv/etnaviv_dump.c | 5 - drivers/gpu/drm/etnaviv/etnaviv_sched.c | 2 +- drivers/gpu/drm/lima/lima_sched.c | 2 +- drivers/gpu/drm/panfrost/panfrost_job.c | 2 +- drivers/gpu/drm/scheduler/sched_main.c | 159 +++++++++++++++++------------ drivers/gpu/drm/v3d/v3d_sched.c | 2 +- include/drm/gpu_scheduler.h | 6 +- 8 files changed, 102 insertions(+), 85 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7cee269ec3e3..a0e165c91a78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3334,7 +3334,7 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, if (!ring || !ring->sched.thread) continue; - drm_sched_stop(&ring->sched); + drm_sched_stop(&ring->sched, &job->base); /* after all hw jobs are reset, hw fence is meaningless, so force_completion */ amdgpu_fence_driver_force_completion(ring); @@ -3343,8 +3343,6 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, if(job) drm_sched_increase_karma(&job->base); - - if (!amdgpu_sriov_vf(adev)) { if (!need_full_reset) @@ -3482,8 +3480,7 @@ end: return r; } -static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev, - struct amdgpu_job *job) +static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev) { int i; @@ -3623,7 +3620,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ /* Post ASIC reset for all devs .*/ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - amdgpu_device_post_asic_reset(tmp_adev, tmp_adev == adev ? job : NULL); + amdgpu_device_post_asic_reset(tmp_adev); if (r) { /* bad news, how to tell it to userspace ? */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index 33854c94cb85..b24ddc406bba 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -118,7 +118,6 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) unsigned int n_obj, n_bomap_pages; size_t file_size, mmu_size; __le64 *bomap, *bomap_start; - unsigned long flags; /* Only catch the first event, or when manually re-armed */ if (!etnaviv_dump_core) @@ -135,13 +134,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) mmu_size + gpu->buffer.size; /* Add in the active command buffers */ - spin_lock_irqsave(&gpu->sched.job_list_lock, flags); list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { submit = to_etnaviv_submit(s_job); file_size += submit->cmdbuf.size; n_obj++; } - spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags); /* Add in the active buffer objects */ list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) { @@ -183,14 +180,12 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) gpu->buffer.size, etnaviv_cmdbuf_get_va(&gpu->buffer)); - spin_lock_irqsave(&gpu->sched.job_list_lock, flags); list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) { submit = to_etnaviv_submit(s_job); etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, submit->cmdbuf.vaddr, submit->cmdbuf.size, etnaviv_cmdbuf_get_va(&submit->cmdbuf)); } - spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags); /* Reserve space for the bomap */ if (n_bomap_pages) { diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 6d24fea1766b..a813c824e154 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -109,7 +109,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) } /* block scheduler */ - drm_sched_stop(&gpu->sched); + drm_sched_stop(&gpu->sched, sched_job); if(sched_job) drm_sched_increase_karma(sched_job); diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index d53bd45f8d96..58a15479d175 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -258,7 +258,7 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe, struct lima_sched_task *task) { - drm_sched_stop(&pipe->base); + drm_sched_stop(&pipe->base, &task->base); if (task) drm_sched_increase_karma(&task->base); diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index a5716c8fe8b3..9bb9260d9181 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -387,7 +387,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) mutex_lock(&pfdev->reset_lock); for (i = 0; i < NUM_JOB_SLOTS; i++) - drm_sched_stop(&pfdev->js->queue[i].sched); + drm_sched_stop(&pfdev->js->queue[i].sched, sched_job); if (sched_job) drm_sched_increase_karma(sched_job); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 19fc601c9eeb..7816de7e8c82 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -265,32 +265,6 @@ void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, } EXPORT_SYMBOL(drm_sched_resume_timeout); -/* job_finish is called after hw fence signaled - */ -static void drm_sched_job_finish(struct work_struct *work) -{ - struct drm_sched_job *s_job = container_of(work, struct drm_sched_job, - finish_work); - struct drm_gpu_scheduler *sched = s_job->sched; - unsigned long flags; - - /* - * Canceling the timeout without removing our job from the ring mirror - * list is safe, as we will only end up in this worker if our jobs - * finished fence has been signaled. So even if some another worker - * manages to find this job as the next job in the list, the fence - * signaled check below will prevent the timeout to be restarted. - */ - cancel_delayed_work_sync(&sched->work_tdr); - - spin_lock_irqsave(&sched->job_list_lock, flags); - /* queue TDR for next job */ - drm_sched_start_timeout(sched); - spin_unlock_irqrestore(&sched->job_list_lock, flags); - - sched->ops->free_job(s_job); -} - static void drm_sched_job_begin(struct drm_sched_job *s_job) { struct drm_gpu_scheduler *sched = s_job->sched; @@ -315,6 +289,13 @@ static void drm_sched_job_timedout(struct work_struct *work) if (job) job->sched->ops->timedout_job(job); + /* + * Guilty job did complete and hence needs to be manually removed + * See drm_sched_stop doc. + */ + if (list_empty(&job->node)) + job->sched->ops->free_job(job); + spin_lock_irqsave(&sched->job_list_lock, flags); drm_sched_start_timeout(sched); spin_unlock_irqrestore(&sched->job_list_lock, flags); @@ -371,23 +352,26 @@ EXPORT_SYMBOL(drm_sched_increase_karma); * @sched: scheduler instance * @bad: bad scheduler job * + * Stop the scheduler and also removes and frees all completed jobs. + * Note: bad job will not be freed as it might be used later and so it's + * callers responsibility to release it manually if it's not part of the + * mirror list any more. + * */ -void drm_sched_stop(struct drm_gpu_scheduler *sched) +void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad) { - struct drm_sched_job *s_job; + struct drm_sched_job *s_job, *tmp; unsigned long flags; - struct dma_fence *last_fence = NULL; kthread_park(sched->thread); /* - * Verify all the signaled jobs in mirror list are removed from the ring - * by waiting for the latest job to enter the list. This should insure that - * also all the previous jobs that were in flight also already singaled - * and removed from the list. + * Iterate the job list from later to earlier one and either deactive + * their HW callbacks or remove them from mirror list if they already + * signaled. + * This iteration is thread safe as sched thread is stopped. */ - spin_lock_irqsave(&sched->job_list_lock, flags); - list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { + list_for_each_entry_safe_reverse(s_job, tmp, &sched->ring_mirror_list, node) { if (s_job->s_fence->parent && dma_fence_remove_callback(s_job->s_fence->parent, &s_job->cb)) { @@ -395,16 +379,30 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched) s_job->s_fence->parent = NULL; atomic_dec(&sched->hw_rq_count); } else { - last_fence = dma_fence_get(&s_job->s_fence->finished); - break; + /* + * remove job from ring_mirror_list. + * Locking here is for concurrent resume timeout + */ + spin_lock_irqsave(&sched->job_list_lock, flags); + list_del_init(&s_job->node); + spin_unlock_irqrestore(&sched->job_list_lock, flags); + + /* + * Wait for job's HW fence callback to finish using s_job + * before releasing it. + * + * Job is still alive so fence refcount at least 1 + */ + dma_fence_wait(&s_job->s_fence->finished, false); + + /* + * We must keep bad job alive for later use during + * recovery by some of the drivers + */ + if (bad != s_job) + sched->ops->free_job(s_job); } } - spin_unlock_irqrestore(&sched->job_list_lock, flags); - - if (last_fence) { - dma_fence_wait(last_fence, false); - dma_fence_put(last_fence); - } } EXPORT_SYMBOL(drm_sched_stop); @@ -418,21 +416,22 @@ EXPORT_SYMBOL(drm_sched_stop); void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery) { struct drm_sched_job *s_job, *tmp; + unsigned long flags; int r; - if (!full_recovery) - goto unpark; - /* * Locking the list is not required here as the sched thread is parked - * so no new jobs are being pushed in to HW and in drm_sched_stop we - * flushed all the jobs who were still in mirror list but who already - * signaled and removed them self from the list. Also concurrent + * so no new jobs are being inserted or removed. Also concurrent * GPU recovers can't run in parallel. */ list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { struct dma_fence *fence = s_job->s_fence->parent; + atomic_inc(&sched->hw_rq_count); + + if (!full_recovery) + continue; + if (fence) { r = dma_fence_add_callback(fence, &s_job->cb, drm_sched_process_job); @@ -445,9 +444,12 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery) drm_sched_process_job(NULL, &s_job->cb); } - drm_sched_start_timeout(sched); + if (full_recovery) { + spin_lock_irqsave(&sched->job_list_lock, flags); + drm_sched_start_timeout(sched); + spin_unlock_irqrestore(&sched->job_list_lock, flags); + } -unpark: kthread_unpark(sched->thread); } EXPORT_SYMBOL(drm_sched_start); @@ -464,7 +466,6 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) uint64_t guilty_context; bool found_guilty = false; - /*TODO DO we need spinlock here ? */ list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { struct drm_sched_fence *s_fence = s_job->s_fence; @@ -477,7 +478,6 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) dma_fence_set_error(&s_fence->finished, -ECANCELED); s_job->s_fence->parent = sched->ops->run_job(s_job); - atomic_inc(&sched->hw_rq_count); } } EXPORT_SYMBOL(drm_sched_resubmit_jobs); @@ -514,7 +514,6 @@ int drm_sched_job_init(struct drm_sched_job *job, return -ENOMEM; job->id = atomic64_inc_return(&sched->job_id_count); - INIT_WORK(&job->finish_work, drm_sched_job_finish); INIT_LIST_HEAD(&job->node); return 0; @@ -597,24 +596,53 @@ static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb) struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb); struct drm_sched_fence *s_fence = s_job->s_fence; struct drm_gpu_scheduler *sched = s_fence->sched; - unsigned long flags; - - cancel_delayed_work(&sched->work_tdr); atomic_dec(&sched->hw_rq_count); atomic_dec(&sched->num_jobs); - spin_lock_irqsave(&sched->job_list_lock, flags); - /* remove job from ring_mirror_list */ - list_del_init(&s_job->node); - spin_unlock_irqrestore(&sched->job_list_lock, flags); + trace_drm_sched_process_job(s_fence); drm_sched_fence_finished(s_fence); - - trace_drm_sched_process_job(s_fence); wake_up_interruptible(&sched->wake_up_worker); +} + +/** + * drm_sched_cleanup_jobs - destroy finished jobs + * + * @sched: scheduler instance + * + * Remove all finished jobs from the mirror list and destroy them. + */ +static void drm_sched_cleanup_jobs(struct drm_gpu_scheduler *sched) +{ + unsigned long flags; + + /* Don't destroy jobs while the timeout worker is running */ + if (!cancel_delayed_work(&sched->work_tdr)) + return; + + + while (!list_empty(&sched->ring_mirror_list)) { + struct drm_sched_job *job; + + job = list_first_entry(&sched->ring_mirror_list, + struct drm_sched_job, node); + if (!dma_fence_is_signaled(&job->s_fence->finished)) + break; + + spin_lock_irqsave(&sched->job_list_lock, flags); + /* remove job from ring_mirror_list */ + list_del_init(&job->node); + spin_unlock_irqrestore(&sched->job_list_lock, flags); + + sched->ops->free_job(job); + } + + /* queue timeout for next job */ + spin_lock_irqsave(&sched->job_list_lock, flags); + drm_sched_start_timeout(sched); + spin_unlock_irqrestore(&sched->job_list_lock, flags); - schedule_work(&s_job->finish_work); } /** @@ -656,9 +684,10 @@ static int drm_sched_main(void *param) struct dma_fence *fence; wait_event_interruptible(sched->wake_up_worker, + (drm_sched_cleanup_jobs(sched), (!drm_sched_blocked(sched) && (entity = drm_sched_select_entity(sched))) || - kthread_should_stop()); + kthread_should_stop())); if (!entity) continue; diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index b4255807b3a7..8c2df6d95283 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -268,7 +268,7 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job) /* block scheduler */ for (q = 0; q < V3D_MAX_QUEUES; q++) - drm_sched_stop(&v3d->queue[q].sched); + drm_sched_stop(&v3d->queue[q].sched, sched_job); if (sched_job) drm_sched_increase_karma(sched_job); diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 0daca4d8dad9..9ee0f2735d71 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -167,9 +167,6 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f); * @sched: the scheduler instance on which this job is scheduled. * @s_fence: contains the fences for the scheduling of job. * @finish_cb: the callback for the finished fence. - * @finish_work: schedules the function @drm_sched_job_finish once the job has - * finished to remove the job from the - * @drm_gpu_scheduler.ring_mirror_list. * @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list. * @id: a unique id assigned to each job scheduled on the scheduler. * @karma: increment on every hang caused by this job. If this exceeds the hang @@ -188,7 +185,6 @@ struct drm_sched_job { struct drm_gpu_scheduler *sched; struct drm_sched_fence *s_fence; struct dma_fence_cb finish_cb; - struct work_struct finish_work; struct list_head node; uint64_t id; atomic_t karma; @@ -296,7 +292,7 @@ int drm_sched_job_init(struct drm_sched_job *job, void *owner); void drm_sched_job_cleanup(struct drm_sched_job *job); void drm_sched_wakeup(struct drm_gpu_scheduler *sched); -void drm_sched_stop(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, bool full_recovery); void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched); void drm_sched_increase_karma(struct drm_sched_job *bad); -- cgit v1.3-6-gb490 From a5343b8a2ca5799ee6370e3cca77369a4c598221 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 18 Apr 2019 11:00:23 -0400 Subject: drm/scheduler: Add flag to hint the release of guilty job. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Sched thread's cleanup function races against TO handler and removes the guilty job from mirror list and we have no way of differentiating if the job was removed from within the TO handler or from the sched thread's clean-up function. Fix: Add a flag to scheduler to hint the TO handler that the guilty job needs to be explicitly released. v2: whitespace fix Reviewed-by: Christian König Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/1555599624-12285-5-git-send-email-andrey.grodzovsky@amd.com --- drivers/gpu/drm/scheduler/sched_main.c | 9 +++++++-- include/drm/gpu_scheduler.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 03e6bd8a1a42..f8f0e1c19002 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -293,8 +293,10 @@ static void drm_sched_job_timedout(struct work_struct *work) * Guilty job did complete and hence needs to be manually removed * See drm_sched_stop doc. */ - if (list_empty(&job->node)) + if (sched->free_guilty) { job->sched->ops->free_job(job); + sched->free_guilty = false; + } spin_lock_irqsave(&sched->job_list_lock, flags); drm_sched_start_timeout(sched); @@ -395,10 +397,13 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad) /* * We must keep bad job alive for later use during - * recovery by some of the drivers + * recovery by some of the drivers but leave a hint + * that the guilty job must be released. */ if (bad != s_job) sched->ops->free_job(s_job); + else + sched->free_guilty = true; } } diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 9ee0f2735d71..57b4121c750a 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -259,6 +259,7 @@ struct drm_sched_backend_ops { * guilty and it will be considered for scheduling further. * @num_jobs: the number of jobs in queue in the scheduler * @ready: marks if the underlying HW is ready to work + * @free_guilty: A hit to time out handler to free the guilty job. * * One scheduler is implemented for each hardware ring. */ @@ -279,6 +280,7 @@ struct drm_gpu_scheduler { int hang_limit; atomic_t num_jobs; bool ready; + bool free_guilty; }; int drm_sched_init(struct drm_gpu_scheduler *sched, -- cgit v1.3-6-gb490 From 27edadf6df811bcad0f7fa2f89321b4590a425bc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 6 May 2019 16:46:29 +0200 Subject: drm/doc: Improve docs for conn_state->best_encoder It's mandatory and considered core state since ioctls rely on this working. Thanks to Laurent for pointing out this gap. v2: Clarify to "atomic drivers" only. Cc: Laurent Pinchart Cc: Sean Paul Acked-by: Sean Paul Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20190506144629.5976-1-daniel.vetter@ffwll.ch --- include/drm/drm_connector.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 02a131202add..f43f40d5888a 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -517,6 +517,10 @@ struct drm_connector_state { * Used by the atomic helpers to select the encoder, through the * &drm_connector_helper_funcs.atomic_best_encoder or * &drm_connector_helper_funcs.best_encoder callbacks. + * + * NOTE: Atomic drivers must fill this out (either themselves or through + * helpers), for otherwise the GETCONNECTOR and GETENCODER IOCTLs will + * not return correct data to userspace. */ struct drm_encoder *best_encoder; -- cgit v1.3-6-gb490 From bc93475587850c097bfbc08f2ffa81171e0a1602 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 6 May 2019 20:01:31 +0200 Subject: drm/fb-helper: No need to cache rotation and sw_rotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Getting rotation info is cheap so we can do it on demand. This is done in preparation for the removal of struct drm_fb_helper_crtc. Cc: Hans de Goede Signed-off-by: Noralf Trønnes Acked-by: Daniel Vetter Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20190506180139.6913-4-noralf@tronnes.org --- drivers/gpu/drm/drm_fb_helper.c | 131 ++++++++++++++++++++-------------------- include/drm/drm_fb_helper.h | 8 --- 2 files changed, 65 insertions(+), 74 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index c521e7490380..1bfbd16c23de 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -388,6 +388,49 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); +/* Check if the plane can hw rotate to match panel orientation */ +static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset, + unsigned int *rotation) +{ + struct drm_connector *connector = modeset->connectors[0]; + struct drm_plane *plane = modeset->crtc->primary; + u64 valid_mask = 0; + unsigned int i; + + if (!modeset->num_connectors) + return false; + + switch (connector->display_info.panel_orientation) { + case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: + *rotation = DRM_MODE_ROTATE_180; + break; + case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: + *rotation = DRM_MODE_ROTATE_90; + break; + case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: + *rotation = DRM_MODE_ROTATE_270; + break; + default: + *rotation = DRM_MODE_ROTATE_0; + } + + /* + * TODO: support 90 / 270 degree hardware rotation, + * depending on the hardware this may require the framebuffer + * to be in a specific tiling format. + */ + if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) + return false; + + for (i = 0; i < plane->rotation_property->num_values; i++) + valid_mask |= (1ULL << plane->rotation_property->values[i]); + + if (!(*rotation & valid_mask)) + return false; + + return true; +} + static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) { struct drm_device *dev = fb_helper->dev; @@ -428,10 +471,13 @@ retry: for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; struct drm_plane *primary = mode_set->crtc->primary; + unsigned int rotation; - /* Cannot fail as we've already gotten the plane state above */ - plane_state = drm_atomic_get_new_plane_state(state, primary); - plane_state->rotation = fb_helper->crtc_info[i].rotation; + if (drm_fb_helper_panel_rotation(mode_set, &rotation)) { + /* Cannot fail as we've already gotten the plane state above */ + plane_state = drm_atomic_get_new_plane_state(state, primary); + plane_state->rotation = rotation; + } ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) @@ -881,7 +927,6 @@ int drm_fb_helper_init(struct drm_device *dev, if (!fb_helper->crtc_info[i].mode_set.connectors) goto out_free; fb_helper->crtc_info[i].mode_set.num_connectors = 0; - fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0; } i = 0; @@ -2510,62 +2555,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } -/* - * This function checks if rotation is necessary because of panel orientation - * and if it is, if it is supported. - * If rotation is necessary and supported, it gets set in fb_crtc.rotation. - * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets - * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only - * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do - * the unsupported rotation. - */ -static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper, - struct drm_fb_helper_crtc *fb_crtc, - struct drm_connector *connector) -{ - struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; - uint64_t valid_mask = 0; - int i, rotation; - - fb_crtc->rotation = DRM_MODE_ROTATE_0; - - switch (connector->display_info.panel_orientation) { - case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: - rotation = DRM_MODE_ROTATE_180; - break; - case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: - rotation = DRM_MODE_ROTATE_90; - break; - case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: - rotation = DRM_MODE_ROTATE_270; - break; - default: - rotation = DRM_MODE_ROTATE_0; - } - - /* - * TODO: support 90 / 270 degree hardware rotation, - * depending on the hardware this may require the framebuffer - * to be in a specific tiling format. - */ - if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) { - fb_helper->sw_rotations |= rotation; - return; - } - - for (i = 0; i < plane->rotation_property->num_values; i++) - valid_mask |= (1ULL << plane->rotation_property->values[i]); - - if (!(rotation & valid_mask)) { - fb_helper->sw_rotations |= rotation; - return; - } - - fb_crtc->rotation = rotation; - /* Rotating in hardware, fbcon should not rotate */ - fb_helper->sw_rotations |= DRM_MODE_ROTATE_0; -} - static struct drm_fb_helper_crtc * drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) { @@ -2812,7 +2801,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_fb_helper_modeset_release(fb_helper, &fb_helper->crtc_info[i].mode_set); - fb_helper->sw_rotations = 0; drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_display_mode *mode = modes[i]; struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; @@ -2832,7 +2820,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, modeset->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); drm_connector_get(connector); - drm_setup_crtc_rotation(fb_helper, fb_crtc, connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; modeset->y = offset->y; @@ -2855,11 +2842,23 @@ out: static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) { struct fb_info *info = fb_helper->fbdev; + unsigned int rotation, sw_rotations = 0; int i; - for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.num_connectors) - fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; + for (i = 0; i < fb_helper->crtc_count; i++) { + struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set; + + if (!modeset->num_connectors) + continue; + + modeset->fb = fb_helper->fb; + + if (drm_fb_helper_panel_rotation(modeset, &rotation)) + /* Rotating in hardware, fbcon should not rotate */ + sw_rotations |= DRM_MODE_ROTATE_0; + else + sw_rotations |= rotation; + } mutex_lock(&fb_helper->dev->mode_config.mutex); drm_fb_helper_for_each_connector(fb_helper, i) { @@ -2875,7 +2874,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) } mutex_unlock(&fb_helper->dev->mode_config.mutex); - switch (fb_helper->sw_rotations) { + switch (sw_rotations) { case DRM_MODE_ROTATE_0: info->fbcon_rotate_hint = FB_ROTATE_UR; break; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 40af2866c26a..b0a14aef2e39 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -51,7 +51,6 @@ struct drm_fb_helper_crtc { struct drm_mode_set mode_set; struct drm_display_mode *desired_mode; int x, y; - int rotation; }; /** @@ -151,13 +150,6 @@ struct drm_fb_helper { struct drm_fb_helper_crtc *crtc_info; int connector_count; int connector_info_alloc_count; - /** - * @sw_rotations: - * Bitmask of all rotations requested for panel-orientation which - * could not be handled in hardware. If only one bit is set - * fbdev->fbcon_rotate_hint gets set to the requested rotation. - */ - int sw_rotations; /** * @connector_info: * -- cgit v1.3-6-gb490 From c8de0d5ff978a581717a1576e676b68bdc86c996 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Mon, 6 May 2019 20:01:32 +0200 Subject: drm/fb-helper: Remove drm_fb_helper_crtc->{x, y, desired_mode} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The values are already present in the modeset. This is done in preparation for the removal of struct drm_fb_helper_crtc. Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20190506180139.6913-5-noralf@tronnes.org --- drivers/gpu/drm/drm_fb_helper.c | 12 ++++-------- include/drm/drm_fb_helper.h | 2 -- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1bfbd16c23de..c259a28522f8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2031,16 +2031,16 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, */ bool lastv = true, lasth = true; - desired_mode = fb_helper->crtc_info[i].desired_mode; mode_set = &fb_helper->crtc_info[i].mode_set; + desired_mode = mode_set->mode; if (!desired_mode) continue; crtc_count++; - x = fb_helper->crtc_info[i].x; - y = fb_helper->crtc_info[i].y; + x = mode_set->x; + y = mode_set->y; sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); @@ -2814,11 +2814,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y); - fb_crtc->desired_mode = mode; - fb_crtc->x = offset->x; - fb_crtc->y = offset->y; - modeset->mode = drm_mode_duplicate(dev, - fb_crtc->desired_mode); + modeset->mode = drm_mode_duplicate(dev, mode); drm_connector_get(connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index b0a14aef2e39..2af1c6d3e147 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -49,8 +49,6 @@ struct drm_fb_offset { struct drm_fb_helper_crtc { struct drm_mode_set mode_set; - struct drm_display_mode *desired_mode; - int x, y; }; /** -- cgit v1.3-6-gb490 From 85438a8ddf031f416758ecf8c080ff92075acb01 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:11 +0200 Subject: drm: Add |struct drm_gem_vram_object| and helpers The type |struct drm_gem_vram_object| implements a GEM object for simple framebuffer devices with dedicated video memory. The BO is either located in VRAM or system memory. The implementation has been created from the respective code in ast, bochs and mgag200. These drivers copy their implementation from each other; except for the names of several data types. The helpers are currently build with TTM, but this is considered an implementation detail and may change in future updates. v5: * do WARN_ON_ONCE for pin-count mismatches * allocate only 2 entries in placements array v4: * cleanups from checkpatch.pl * removed several fixed-size types from interfaces * DRM_VRAM_HELPER now selects DRM_TTM * remove separate config option for GEM VRAM v2: * rename to |struct drm_gem_vram_object| * move drm_is_gem_ttm() to a later patch in the series * add drm_gem_vram_kmap_at() * return is_iomem from kmap functions * redefine TTM placement flags for public interface * documentation fixes Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-2-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- Documentation/gpu/drm-mm.rst | 15 ++ drivers/gpu/drm/Kconfig | 7 + drivers/gpu/drm/Makefile | 4 + drivers/gpu/drm/drm_gem_vram_helper.c | 412 +++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_vram_helper_common.c | 6 + include/drm/drm_gem_vram_helper.h | 92 +++++++ 6 files changed, 536 insertions(+) create mode 100644 drivers/gpu/drm/drm_gem_vram_helper.c create mode 100644 drivers/gpu/drm/drm_vram_helper_common.c create mode 100644 include/drm/drm_gem_vram_helper.h (limited to 'include') diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 54a696d961a7..a3b685089512 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -380,6 +380,21 @@ GEM CMA Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c :export: +VRAM Helper Function Reference +============================== + +GEM VRAM Helper Functions Reference +----------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c + :doc: overview + +.. kernel-doc:: include/drm/drm_gem_vram_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c + :export: + VMA Offset Manager ================== diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 2267e84d5cb4..13d7b321db0d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -160,6 +160,13 @@ config DRM_TTM GPU memory types. Will be enabled automatically if a device driver uses it. +config DRM_VRAM_HELPER + tristate + depends on DRM + select DRM_TTM + help + Helpers for VRAM memory management + config DRM_GEM_CMA_HELPER bool depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 72f5036d9bfa..ed49b2480766 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,6 +32,10 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm_vram_helper-y := drm_gem_vram_helper.o \ + drm_vram_helper_common.o +obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o + drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c new file mode 100644 index 000000000000..761a546412f8 --- /dev/null +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +/** + * DOC: overview + * + * This library provides a GEM buffer object that is backed by video RAM + * (VRAM). It can be used for framebuffer devices with dedicated memory. + */ + +/* + * Buffer-objects helpers + */ + +static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo) +{ + /* We got here via ttm_bo_put(), which means that the + * TTM buffer object in 'bo' has already been cleaned + * up; only release the GEM object. + */ + drm_gem_object_release(&gbo->gem); +} + +static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo) +{ + drm_gem_vram_cleanup(gbo); + kfree(gbo); +} + +static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo); + + drm_gem_vram_destroy(gbo); +} + +static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, + unsigned long pl_flag) +{ + unsigned int i; + unsigned int c = 0; + + gbo->placement.placement = gbo->placements; + gbo->placement.busy_placement = gbo->placements; + + if (pl_flag & TTM_PL_FLAG_VRAM) + gbo->placements[c++].flags = TTM_PL_FLAG_WC | + TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_VRAM; + + if (pl_flag & TTM_PL_FLAG_SYSTEM) + gbo->placements[c++].flags = TTM_PL_MASK_CACHING | + TTM_PL_FLAG_SYSTEM; + + if (!c) + gbo->placements[c++].flags = TTM_PL_MASK_CACHING | + TTM_PL_FLAG_SYSTEM; + + gbo->placement.num_placement = c; + gbo->placement.num_busy_placement = c; + + for (i = 0; i < c; ++i) { + gbo->placements[i].fpfn = 0; + gbo->placements[i].lpfn = 0; + } +} + +static int drm_gem_vram_init(struct drm_device *dev, + struct ttm_bo_device *bdev, + struct drm_gem_vram_object *gbo, + size_t size, unsigned long pg_align, + bool interruptible) +{ + int ret; + size_t acc_size; + + ret = drm_gem_object_init(dev, &gbo->gem, size); + if (ret) + return ret; + + acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); + + gbo->bo.bdev = bdev; + drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); + + ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, + &gbo->placement, pg_align, interruptible, acc_size, + NULL, NULL, ttm_buffer_object_destroy); + if (ret) + goto err_drm_gem_object_release; + + return 0; + +err_drm_gem_object_release: + drm_gem_object_release(&gbo->gem); + return ret; +} + +/** + * drm_gem_vram_create() - Creates a VRAM-backed GEM object + * @dev: the DRM device + * @bdev: the TTM BO device backing the object + * @size: the buffer size in bytes + * @pg_align: the buffer's alignment in multiples of the page size + * @interruptible: sleep interruptible if waiting for memory + * + * Returns: + * A new instance of &struct drm_gem_vram_object on success, or + * an ERR_PTR()-encoded error code otherwise. + */ +struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, + struct ttm_bo_device *bdev, + size_t size, + unsigned long pg_align, + bool interruptible) +{ + struct drm_gem_vram_object *gbo; + int ret; + + gbo = kzalloc(sizeof(*gbo), GFP_KERNEL); + if (!gbo) + return ERR_PTR(-ENOMEM); + + ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible); + if (ret < 0) + goto err_kfree; + + return gbo; + +err_kfree: + kfree(gbo); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_gem_vram_create); + +/** + * drm_gem_vram_put() - Releases a reference to a VRAM-backed GEM object + * @gbo: the GEM VRAM object + * + * See ttm_bo_put() for more information. + */ +void drm_gem_vram_put(struct drm_gem_vram_object *gbo) +{ + ttm_bo_put(&gbo->bo); +} +EXPORT_SYMBOL(drm_gem_vram_put); + +/** + * drm_gem_vram_reserve() - Reserves a VRAM-backed GEM object + * @gbo: the GEM VRAM object + * @no_wait: don't wait for buffer object to become available + * + * See ttm_bo_reserve() for more information. + * + * Returns: + * 0 on success, or + * a negative error code otherwise + */ +int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait) +{ + return ttm_bo_reserve(&gbo->bo, true, no_wait, NULL); +} +EXPORT_SYMBOL(drm_gem_vram_reserve); + +/** + * drm_gem_vram_unreserve() - \ + Release a reservation acquired by drm_gem_vram_reserve() + * @gbo: the GEM VRAM object + * + * See ttm_bo_unreserve() for more information. + */ +void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo) +{ + ttm_bo_unreserve(&gbo->bo); +} +EXPORT_SYMBOL(drm_gem_vram_unreserve); + +/** + * drm_gem_vram_mmap_offset() - Returns a GEM VRAM object's mmap offset + * @gbo: the GEM VRAM object + * + * See drm_vma_node_offset_addr() for more information. + * + * Returns: + * The buffer object's offset for userspace mappings on success, or + * 0 if no offset is allocated. + */ +u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo) +{ + return drm_vma_node_offset_addr(&gbo->bo.vma_node); +} +EXPORT_SYMBOL(drm_gem_vram_mmap_offset); + +/** + * drm_gem_vram_offset() - \ + Returns a GEM VRAM object's offset in video memory + * @gbo: the GEM VRAM object + * + * This function returns the buffer object's offset in the device's video + * memory. The buffer object has to be pinned to %TTM_PL_VRAM. + * + * Returns: + * The buffer object's offset in video memory on success, or + * a negative errno code otherwise. + */ +s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo) +{ + if (WARN_ON_ONCE(!gbo->pin_count)) + return (s64)-ENODEV; + return gbo->bo.offset; +} +EXPORT_SYMBOL(drm_gem_vram_offset); + +/** + * drm_gem_vram_pin() - Pins a GEM VRAM object in a region. + * @gbo: the GEM VRAM object + * @pl_flag: a bitmask of possible memory regions + * + * Pinning a buffer object ensures that it is not evicted from + * a memory region. A pinned buffer object has to be unpinned before + * it can be pinned to another region. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (gbo->pin_count) { + ++gbo->pin_count; + return 0; + } + + drm_gem_vram_placement(gbo, pl_flag); + for (i = 0; i < gbo->placement.num_placement; ++i) + gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + gbo->pin_count = 1; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_pin); + +/** + * drm_gem_vram_unpin() - Unpins a GEM VRAM object + * @gbo: the GEM VRAM object + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (WARN_ON_ONCE(!gbo->pin_count)) + return 0; + + --gbo->pin_count; + if (gbo->pin_count) + return 0; + + for (i = 0; i < gbo->placement.num_placement ; ++i) + gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_unpin); + +/** + * drm_gem_vram_push_to_system() - \ + Unpins a GEM VRAM object and moves it to system memory + * @gbo: the GEM VRAM object + * + * This operation only works if the caller holds the final pin on the + * buffer object. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (WARN_ON_ONCE(!gbo->pin_count)) + return 0; + + --gbo->pin_count; + if (gbo->pin_count) + return 0; + + if (gbo->kmap.virtual) + ttm_bo_kunmap(&gbo->kmap); + + drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); + for (i = 0; i < gbo->placement.num_placement ; ++i) + gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_push_to_system); + +/** + * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space + * @gbo: the GEM VRAM object + * @map: establish a mapping if necessary + * @is_iomem: returns true if the mapped memory is I/O memory, or false \ + otherwise; can be NULL + * @kmap: the mapping's kmap object + * + * This function maps the buffer object into the kernel's address space + * or returns the current mapping. If the parameter map is false, the + * function only queries the current mapping, but does not establish a + * new one. + * + * Returns: + * The buffers virtual address if mapped, or + * NULL if not mapped, or + * an ERR_PTR()-encoded error code otherwise. + */ +void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem, struct ttm_bo_kmap_obj *kmap) +{ + int ret; + + if (kmap->virtual || !map) + goto out; + + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap); + if (ret) + return ERR_PTR(ret); + +out: + if (!is_iomem) + return kmap->virtual; + if (!kmap->virtual) { + *is_iomem = false; + return NULL; + } + return ttm_kmap_obj_virtual(kmap, is_iomem); +} +EXPORT_SYMBOL(drm_gem_vram_kmap_at); + +/** + * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space + * @gbo: the GEM VRAM object + * @map: establish a mapping if necessary + * @is_iomem: returns true if the mapped memory is I/O memory, or false \ + otherwise; can be NULL + * + * This function maps the buffer object into the kernel's address space + * or returns the current mapping. If the parameter map is false, the + * function only queries the current mapping, but does not establish a + * new one. + * + * Returns: + * The buffers virtual address if mapped, or + * NULL if not mapped, or + * an ERR_PTR()-encoded error code otherwise. + */ +void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem) +{ + return drm_gem_vram_kmap_at(gbo, map, is_iomem, &gbo->kmap); +} +EXPORT_SYMBOL(drm_gem_vram_kmap); + +/** + * drm_gem_vram_kunmap_at() - Unmaps a GEM VRAM object + * @gbo: the GEM VRAM object + * @kmap: the mapping's kmap object + */ +void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, + struct ttm_bo_kmap_obj *kmap) +{ + if (!kmap->virtual) + return; + + ttm_bo_kunmap(kmap); + kmap->virtual = NULL; +} +EXPORT_SYMBOL(drm_gem_vram_kunmap_at); + +/** + * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object + * @gbo: the GEM VRAM object + */ +void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) +{ + drm_gem_vram_kunmap_at(gbo, &gbo->kmap); +} +EXPORT_SYMBOL(drm_gem_vram_kunmap); diff --git a/drivers/gpu/drm/drm_vram_helper_common.c b/drivers/gpu/drm/drm_vram_helper_common.c new file mode 100644 index 000000000000..7c25daca18d0 --- /dev/null +++ b/drivers/gpu/drm/drm_vram_helper_common.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +MODULE_DESCRIPTION("DRM VRAM memory-management helpers"); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h new file mode 100644 index 000000000000..5802dd694939 --- /dev/null +++ b/include/drm/drm_gem_vram_helper.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef DRM_GEM_VRAM_HELPER_H +#define DRM_GEM_VRAM_HELPER_H + +#include +#include +#include +#include /* for container_of() */ + +struct filp; + +#define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM +#define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM + +/* + * Buffer-object helpers + */ + +/** + * struct drm_gem_vram_object - GEM object backed by VRAM + * @gem: GEM object + * @bo: TTM buffer object + * @kmap: Mapping information for @bo + * @placement: TTM placement information. Supported placements are \ + %TTM_PL_VRAM and %TTM_PL_SYSTEM + * @placements: TTM placement information. + * @pin_count: Pin counter + * + * The type struct drm_gem_vram_object represents a GEM object that is + * backed by VRAM. It can be used for simple framebuffer devices with + * dedicated memory. The buffer object can be evicted to system memory if + * video memory becomes scarce. + */ +struct drm_gem_vram_object { + struct drm_gem_object gem; + struct ttm_buffer_object bo; + struct ttm_bo_kmap_obj kmap; + + /* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */ + struct ttm_placement placement; + struct ttm_place placements[2]; + + int pin_count; +}; + +/** + * Returns the container of type &struct drm_gem_vram_object + * for field bo. + * @bo: the VRAM buffer object + * Returns: The containing GEM VRAM object + */ +static inline struct drm_gem_vram_object *drm_gem_vram_of_bo( + struct ttm_buffer_object *bo) +{ + return container_of(bo, struct drm_gem_vram_object, bo); +} + +/** + * Returns the container of type &struct drm_gem_vram_object + * for field gem. + * @gem: the GEM object + * Returns: The containing GEM VRAM object + */ +static inline struct drm_gem_vram_object *drm_gem_vram_of_gem( + struct drm_gem_object *gem) +{ + return container_of(gem, struct drm_gem_vram_object, gem); +} + +struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, + struct ttm_bo_device *bdev, + size_t size, + unsigned long pg_align, + bool interruptible); +void drm_gem_vram_put(struct drm_gem_vram_object *gbo); +int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait); +void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo); +u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); +s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); +int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); +int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); +int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo); +void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem, struct ttm_bo_kmap_obj *kmap); +void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem); +void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, + struct ttm_bo_kmap_obj *kmap); +void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); + +#endif -- cgit v1.3-6-gb490 From 6c812bc5074bbc969e78fadfbba7ac41fe61ddeb Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:12 +0200 Subject: drm: Add |struct drm_gem_vram_object| callbacks for |struct ttm_bo_driver| The provided helpers can be used for the respective callback functions in |struct ttm_bo_driver|. v2: * drm_is_gem_vram() is now a private function * documentation fixes Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-3-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 50 +++++++++++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 10 +++++++ 2 files changed, 60 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 761a546412f8..d6c4e0d0a1c5 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -410,3 +410,53 @@ void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) drm_gem_vram_kunmap_at(gbo, &gbo->kmap); } EXPORT_SYMBOL(drm_gem_vram_kunmap); + +/* + * Helpers for struct ttm_bo_driver + */ + +static bool drm_is_gem_vram(struct ttm_buffer_object *bo) +{ + return (bo->destroy == ttm_buffer_object_destroy); +} + +/** + * drm_gem_vram_bo_driver_evict_flags() - \ + Implements &struct ttm_bo_driver.evict_flags + * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo + * @pl: TTM placement information. + */ +void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *pl) +{ + struct drm_gem_vram_object *gbo; + + /* TTM may pass BOs that are not GEM VRAM BOs. */ + if (!drm_is_gem_vram(bo)) + return; + + gbo = drm_gem_vram_of_bo(bo); + drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); + *pl = gbo->placement; +} +EXPORT_SYMBOL(drm_gem_vram_bo_driver_evict_flags); + +/** + * drm_gem_vram_bo_driver_verify_access() - \ + Implements &struct ttm_bo_driver.verify_access + * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo + * @filp: File pointer. + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo); + + return drm_vma_node_verify_access(&gbo->gem.vma_node, + filp->private_data); +} +EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 5802dd694939..1915d3958304 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -89,4 +89,14 @@ void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, struct ttm_bo_kmap_obj *kmap); void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); +/* + * Helpers for struct ttm_bo_driver + */ + +void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *pl); + +int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp); + #endif -- cgit v1.3-6-gb490 From 737000fd9c7d32dd378733cc4bba17555b241be0 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:13 +0200 Subject: drm: Add |struct drm_gem_vram_object| callbacks for |struct drm_driver| The provided helpers can be used for the respective callback functions in |struct drm_driver|. v4: * cleanups from checkpatch.pl v2: * documentation fixes Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-4-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 49 +++++++++++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 10 +++++++ 2 files changed, 59 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index d6c4e0d0a1c5..264028374336 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -460,3 +460,52 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, filp->private_data); } EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); + +/* + * Helpers for struct drm_driver + */ + +/** + * drm_gem_vram_driver_gem_free_object_unlocked() - \ + Implements &struct drm_driver.gem_free_object_unlocked + * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem + */ +void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_put(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked); + +/** + * drm_gem_vram_driver_dumb_mmap_offset() - \ + Implements &struct drm_driver.dumb_mmap_offset + * @file: DRM file pointer. + * @dev: DRM device. + * @handle: GEM handle + * @offset: Returns the mapping's memory offset on success + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, + struct drm_device *dev, + uint32_t handle, uint64_t *offset) +{ + struct drm_gem_object *gem; + struct drm_gem_vram_object *gbo; + + gem = drm_gem_object_lookup(file, handle); + if (!gem) + return -ENOENT; + + gbo = drm_gem_vram_of_gem(gem); + *offset = drm_gem_vram_mmap_offset(gbo); + + drm_gem_object_put_unlocked(gem); + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 1915d3958304..b87cb2e9d9da 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -99,4 +99,14 @@ void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, struct file *filp); +/* + * Helpers for struct drm_driver + */ + +void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); + +int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, + struct drm_device *dev, + uint32_t handle, uint64_t *offset); + #endif -- cgit v1.3-6-gb490 From fed1eec080b9b23f5a80a0c4f19ae49a2d14c69e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:14 +0200 Subject: drm: Add drm_gem_vram_fill_create_dumb() to create dumb buffers The helper function drm_gem_vram_fill_create_dumb() implements most of struct drm_driver.dumb_create() for GEM-VRAM buffer objects. It's not a full implementation of the callback, as several driver-specific parameters are still required. v4: * cleanups from checkpatch.pl v2: * documentation fixes Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-5-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 62 +++++++++++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 8 +++++ 2 files changed, 70 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 264028374336..aba073279ca2 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include /** @@ -411,6 +412,67 @@ void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) } EXPORT_SYMBOL(drm_gem_vram_kunmap); +/** + * drm_gem_vram_fill_create_dumb() - \ + Helper for implementing &struct drm_driver.dumb_create + * @file: the DRM file + * @dev: the DRM device + * @bdev: the TTM BO device managing the buffer object + * @pg_align: the buffer's alignment in multiples of the page size + * @interruptible: sleep interruptible if waiting for memory + * @args: the arguments as provided to \ + &struct drm_driver.dumb_create + * + * This helper function fills &struct drm_mode_create_dumb, which is used + * by &struct drm_driver.dumb_create. Implementations of this interface + * should forwards their arguments to this helper, plus the driver-specific + * parameters. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_fill_create_dumb(struct drm_file *file, + struct drm_device *dev, + struct ttm_bo_device *bdev, + unsigned long pg_align, + bool interruptible, + struct drm_mode_create_dumb *args) +{ + size_t pitch, size; + struct drm_gem_vram_object *gbo; + int ret; + u32 handle; + + pitch = args->width * ((args->bpp + 7) / 8); + size = pitch * args->height; + + size = roundup(size, PAGE_SIZE); + if (!size) + return -EINVAL; + + gbo = drm_gem_vram_create(dev, bdev, size, pg_align, interruptible); + if (IS_ERR(gbo)) + return PTR_ERR(gbo); + + ret = drm_gem_handle_create(file, &gbo->gem, &handle); + if (ret) + goto err_drm_gem_object_put_unlocked; + + drm_gem_object_put_unlocked(&gbo->gem); + + args->pitch = pitch; + args->size = size; + args->handle = handle; + + return 0; + +err_drm_gem_object_put_unlocked: + drm_gem_object_put_unlocked(&gbo->gem); + return ret; +} +EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb); + /* * Helpers for struct ttm_bo_driver */ diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index b87cb2e9d9da..8e54f721c9f8 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -8,6 +8,7 @@ #include #include /* for container_of() */ +struct drm_mode_create_dumb; struct filp; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM @@ -89,6 +90,13 @@ void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, struct ttm_bo_kmap_obj *kmap); void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); +int drm_gem_vram_fill_create_dumb(struct drm_file *file, + struct drm_device *dev, + struct ttm_bo_device *bdev, + unsigned long pg_align, + bool interruptible, + struct drm_mode_create_dumb *args); + /* * Helpers for struct ttm_bo_driver */ -- cgit v1.3-6-gb490 From 1f460b497890d6bf54aba6e41fe24bba2217141a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:15 +0200 Subject: drm: Add simple PRIME helpers for GEM VRAM These basic helper functions for GEM VRAM allow for pinning and mapping GEM VRAM objects via the PRIME interfaces. It's not a full implementation, but complete enough for generic fbcon. Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-6-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 98 +++++++++++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 20 +++++++ 2 files changed, 118 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index aba073279ca2..15c6193e4985 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -2,6 +2,7 @@ #include #include +#include #include /** @@ -571,3 +572,100 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, return 0; } EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset); + +/* + * PRIME helpers for struct drm_driver + */ + +/** + * drm_gem_vram_driver_gem_prime_pin() - \ + Implements &struct drm_driver.gem_prime_pin + * @gem: The GEM object to pin + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_pin); + +/** + * drm_gem_vram_driver_gem_prime_unpin() - \ + Implements &struct drm_driver.gem_prime_unpin + * @gem: The GEM object to unpin + */ +void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_unpin(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_unpin); + +/** + * drm_gem_vram_driver_gem_prime_vmap() - \ + Implements &struct drm_driver.gem_prime_vmap + * @gem: The GEM object to map + * + * Returns: + * The buffers virtual address on success, or + * NULL otherwise. + */ +void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + int ret; + void *base; + + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); + if (ret) + return NULL; + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + drm_gem_vram_unpin(gbo); + return NULL; + } + return base; +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vmap); + +/** + * drm_gem_vram_driver_gem_prime_vunmap() - \ + Implements &struct drm_driver.gem_prime_vunmap + * @gem: The GEM object to unmap + * @vaddr: The mapping's base address + */ +void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *gem, + void *vaddr) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vunmap); + +/** + * drm_gem_vram_driver_gem_prime_mmap() - \ + Implements &struct drm_driver.gem_prime_mmap + * @gem: The GEM object to map + * @vma: The VMA describing the mapping + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *gem, + struct vm_area_struct *vma) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + gbo->gem.vma_node.vm_node.start = gbo->bo.vma_node.vm_node.start; + return drm_gem_prime_mmap(gem, vma); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_mmap); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 8e54f721c9f8..9a8bd98b623f 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -116,5 +116,25 @@ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); +/* + * PRIME helpers for struct drm_driver + */ + +int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *obj); +void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *obj); +void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *obj); +void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *obj, + void *vaddr); +int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma); + +#define DRM_GEM_VRAM_DRIVER_PRIME \ + .gem_prime_export = drm_gem_prime_export, \ + .gem_prime_import = drm_gem_prime_import, \ + .gem_prime_pin = drm_gem_vram_driver_gem_prime_pin, \ + .gem_prime_unpin = drm_gem_vram_driver_gem_prime_unpin, \ + .gem_prime_vmap = drm_gem_vram_driver_gem_prime_vmap, \ + .gem_prime_vunmap = drm_gem_vram_driver_gem_prime_vunmap, \ + .gem_prime_mmap = drm_gem_vram_driver_gem_prime_mmap #endif -- cgit v1.3-6-gb490 From 96352eca5c7c36c3e0eb97a6d68fb170ce643ea5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:16 +0200 Subject: drm: Add VRAM MM, a simple memory manager for dedicated VRAM The VRAM MM memory manager is a helper library that manages dedicated video memory of simple framebuffer devices. It is supported to be used with struct drm_gem_vram_object, but does not depend on it. The implementation is based on the respective code from ast, bochs, and mgag200. These drivers share the exact same implementation except for type names. The helpers are currently build with TTM. This may change in future revisions. v4: * cleanups from checkpatch.pl v2: * renamed to struct drm_vram_mm * add drm_vram_mm_mmap() helper * documentation fixes Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-7-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- Documentation/gpu/drm-mm.rst | 13 ++- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_vram_mm_helper.c | 210 +++++++++++++++++++++++++++++++++++ include/drm/drm_vram_mm_helper.h | 69 ++++++++++++ 4 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/drm_vram_mm_helper.c create mode 100644 include/drm/drm_vram_mm_helper.h (limited to 'include') diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index a3b685089512..eba50afbda42 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -79,7 +79,6 @@ count for the TTM, which will call your initialization function. See the radeon_ttm.c file for an example of usage. - The Graphics Execution Manager (GEM) ==================================== @@ -395,6 +394,18 @@ GEM VRAM Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c :export: +VRAM MM Helper Functions Reference +---------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c + :doc: overview + +.. kernel-doc:: include/drm/drm_vram_mm_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c + :export: + VMA Offset Manager ================== diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index ed49b2480766..4c3dc4268b65 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -33,7 +33,8 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_vram_helper-y := drm_gem_vram_helper.o \ - drm_vram_helper_common.o + drm_vram_helper_common.o \ + drm_vram_mm_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \ diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c new file mode 100644 index 000000000000..d17c5169b018 --- /dev/null +++ b/drivers/gpu/drm/drm_vram_mm_helper.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +/** + * DOC: overview + * + * The data structure &struct drm_vram_mm and its helpers implement a memory + * manager for simple framebuffer devices with dedicated video memory. Buffer + * objects are either placed in video RAM or evicted to system memory. These + * helper functions work well with &struct drm_gem_vram_object. + */ + +/* + * TTM TT + */ + +static void backend_func_destroy(struct ttm_tt *tt) +{ + ttm_tt_fini(tt); + kfree(tt); +} + +static struct ttm_backend_func backend_func = { + .destroy = backend_func_destroy +}; + +/* + * TTM BO device + */ + +static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, + uint32_t page_flags) +{ + struct ttm_tt *tt; + int ret; + + tt = kzalloc(sizeof(*tt), GFP_KERNEL); + if (!tt) + return NULL; + + tt->func = &backend_func; + + ret = ttm_tt_init(tt, bo, page_flags); + if (ret < 0) + goto err_ttm_tt_init; + + return tt; + +err_ttm_tt_init: + kfree(tt); + return NULL; +} + +static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man) +{ + switch (type) { + case TTM_PL_SYSTEM: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_VRAM: + man->func = &ttm_bo_manager_func; + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + break; + default: + return -EINVAL; + } + return 0; +} + +static void bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *placement) +{ + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev); + + if (vmm->funcs && vmm->funcs->evict_flags) + vmm->funcs->evict_flags(bo, placement); +} + +static int bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp) +{ + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev); + + if (!vmm->funcs || !vmm->funcs->verify_access) + return 0; + return vmm->funcs->verify_access(bo, filp); +} + +static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = bdev->man + mem->mem_type; + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev); + + if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) + return -EINVAL; + + mem->bus.addr = NULL; + mem->bus.size = mem->num_pages << PAGE_SHIFT; + + switch (mem->mem_type) { + case TTM_PL_SYSTEM: /* nothing to do */ + mem->bus.offset = 0; + mem->bus.base = 0; + mem->bus.is_iomem = false; + break; + case TTM_PL_VRAM: + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = vmm->vram_base; + mem->bus.is_iomem = true; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void bo_driver_io_mem_free(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ } + +static struct ttm_bo_driver bo_driver = { + .ttm_tt_create = bo_driver_ttm_tt_create, + .ttm_tt_populate = ttm_pool_populate, + .ttm_tt_unpopulate = ttm_pool_unpopulate, + .init_mem_type = bo_driver_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, + .evict_flags = bo_driver_evict_flags, + .verify_access = bo_driver_verify_access, + .io_mem_reserve = bo_driver_io_mem_reserve, + .io_mem_free = bo_driver_io_mem_free, +}; + +/* + * struct drm_vram_mm + */ + +/** + * drm_vram_mm_init() - Initialize an instance of VRAM MM. + * @vmm: the VRAM MM instance to initialize + * @dev: the DRM device + * @vram_base: the base address of the video memory + * @vram_size: the size of the video memory in bytes + * @funcs: callback functions for buffer objects + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, + uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs) +{ + int ret; + + vmm->vram_base = vram_base; + vmm->vram_size = vram_size; + vmm->funcs = funcs; + + ret = ttm_bo_device_init(&vmm->bdev, &bo_driver, + dev->anon_inode->i_mapping, + true); + if (ret) + return ret; + + ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_vram_mm_init); + +/** + * drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM. + * @vmm: the VRAM MM instance to clean up + */ +void drm_vram_mm_cleanup(struct drm_vram_mm *vmm) +{ + ttm_bo_device_release(&vmm->bdev); +} +EXPORT_SYMBOL(drm_vram_mm_cleanup); + +/** + * drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap() + * @filp: the mapping's file structure + * @vma: the mapping's memory area + * @vmm: the VRAM MM instance + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, + struct drm_vram_mm *vmm) +{ + return ttm_bo_mmap(filp, vma, &vmm->bdev); +} +EXPORT_SYMBOL(drm_vram_mm_mmap); diff --git a/include/drm/drm_vram_mm_helper.h b/include/drm/drm_vram_mm_helper.h new file mode 100644 index 000000000000..5d45c6447fa4 --- /dev/null +++ b/include/drm/drm_vram_mm_helper.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef DRM_VRAM_MM_HELPER_H +#define DRM_VRAM_MM_HELPER_H + +#include + +struct drm_device; + +/** + * struct drm_vram_mm_funcs - Callback functions for &struct drm_vram_mm + * @evict_flags: Provides an implementation for struct \ + &ttm_bo_driver.evict_flags + * @verify_access: Provides an implementation for \ + struct &ttm_bo_driver.verify_access + * + * These callback function integrate VRAM MM with TTM buffer objects. New + * functions can be added if necessary. + */ +struct drm_vram_mm_funcs { + void (*evict_flags)(struct ttm_buffer_object *bo, + struct ttm_placement *placement); + int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp); +}; + +/** + * struct drm_vram_mm - An instance of VRAM MM + * @vram_base: Base address of the managed video memory + * @vram_size: Size of the managed video memory in bytes + * @bdev: The TTM BO device. + * @funcs: TTM BO functions + * + * The fields &struct drm_vram_mm.vram_base and + * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are + * available for public read access. Use the field + * &struct drm_vram_mm.bdev to access the TTM BO device. + */ +struct drm_vram_mm { + uint64_t vram_base; + size_t vram_size; + + struct ttm_bo_device bdev; + + const struct drm_vram_mm_funcs *funcs; +}; + +/** + * drm_vram_mm_of_bdev() - \ + Returns the container of type &struct ttm_bo_device for field bdev. + * @bdev: the TTM BO device + * + * Returns: + * The containing instance of &struct drm_vram_mm + */ +static inline struct drm_vram_mm *drm_vram_mm_of_bdev( + struct ttm_bo_device *bdev) +{ + return container_of(bdev, struct drm_vram_mm, bdev); +} + +int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, + uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs); +void drm_vram_mm_cleanup(struct drm_vram_mm *vmm); + +int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, + struct drm_vram_mm *vmm); + +#endif -- cgit v1.3-6-gb490 From 5c9dcacfe56673555540933017c54e8f39e947cb Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:17 +0200 Subject: drm: Add default instance for VRAM MM callback functions VRAM MM is most likely be used with GEM VRAM. The latter now provides the required instance of struct drm_vram_mm_funcs for drivers to use. Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-8-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 14 ++++++++++++++ include/drm/drm_gem_vram_helper.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 15c6193e4985..c21b1f920e0a 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -3,6 +3,7 @@ #include #include #include +#include #include /** @@ -524,6 +525,19 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); +/** + * drm_gem_vram_mm_funcs - Functions for &struct drm_vram_mm + * + * Most users of @struct drm_gem_vram_object will also use + * @struct drm_vram_mm. This instance of &struct drm_vram_mm_funcs + * can be used to connect both. + */ +const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = { + .evict_flags = drm_gem_vram_bo_driver_evict_flags, + .verify_access = drm_gem_vram_bo_driver_verify_access +}; +EXPORT_SYMBOL(drm_gem_vram_mm_funcs); + /* * Helpers for struct drm_driver */ diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 9a8bd98b623f..7971656afe87 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -9,6 +9,7 @@ #include /* for container_of() */ struct drm_mode_create_dumb; +struct drm_vram_mm_funcs; struct filp; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM @@ -107,6 +108,8 @@ void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, struct file *filp); +extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs; + /* * Helpers for struct drm_driver */ -- cgit v1.3-6-gb490 From 59f5989ad42b6edd089b47895986ef15259822dc Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 May 2019 10:26:18 +0200 Subject: drm: Integrate VRAM MM into struct drm_device There's now a pointer to struct drm_vram_mm stored in struct drm_device. DRM drivers that use VRAM MM should use this field to refer to their instance of the data structure. Appropriate helpers are now provided as well. Adding struct drm_vram_mm to struct drm_device further avoids wrappers and boilerplate code in drivers. This patch implements default functions for callbacks in struct drm_driver and struct file_operations that use the struct drm_vram_mm stored in struct drm_device. Drivers that need to provide their own implementations can still do so. The patch also adds documentation for the VRAM helper library in general. v5: * set .llseek to no_llseek() from DRM_VRAM_MM_FILE_OPERATIONS v4: * cleanups from checkpatch.pl * document VRAM helper library Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-9-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- Documentation/gpu/drm-mm.rst | 6 +++ drivers/gpu/drm/drm_gem_vram_helper.c | 28 ++++++++++ drivers/gpu/drm/drm_vram_helper_common.c | 92 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_vram_mm_helper.c | 85 +++++++++++++++++++++++++++++ include/drm/drm_device.h | 4 ++ include/drm/drm_gem_vram_helper.h | 19 ++++++- include/drm/drm_vram_mm_helper.h | 33 ++++++++++++ 7 files changed, 266 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index eba50afbda42..c8ebd4f66a6a 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -382,6 +382,12 @@ GEM CMA Helper Functions Reference VRAM Helper Function Reference ============================== +.. kernel-doc:: drivers/gpu/drm/drm_vram_helper_common.c + :doc: overview + +.. kernel-doc:: include/drm/drm_gem_vram_helper.h + :internal: + GEM VRAM Helper Functions Reference ----------------------------------- diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index c21b1f920e0a..8f142b810eb4 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include #include @@ -555,6 +556,33 @@ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem) } EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked); +/** + * drm_gem_vram_driver_create_dumb() - \ + Implements &struct drm_driver.dumb_create + * @file: the DRM file + * @dev: the DRM device + * @args: the arguments as provided to \ + &struct drm_driver.dumb_create + * + * This function requires the driver to use @drm_device.vram_mm for its + * instance of VRAM MM. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_driver_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) + return -EINVAL; + + return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, 0, + false, args); +} +EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create); + /** * drm_gem_vram_driver_dumb_mmap_offset() - \ Implements &struct drm_driver.dumb_mmap_offset diff --git a/drivers/gpu/drm/drm_vram_helper_common.c b/drivers/gpu/drm/drm_vram_helper_common.c index 7c25daca18d0..3b47f7002115 100644 --- a/drivers/gpu/drm/drm_vram_helper_common.c +++ b/drivers/gpu/drm/drm_vram_helper_common.c @@ -2,5 +2,97 @@ #include +/** + * DOC: overview + * + * This library provides &struct drm_gem_vram_object (GEM VRAM), a GEM + * buffer object that is backed by video RAM. It can be used for + * framebuffer devices with dedicated memory. The video RAM can be + * managed with &struct drm_vram_mm (VRAM MM). Both data structures are + * supposed to be used together, but can also be used individually. + * + * With the GEM interface userspace applications create, manage and destroy + * graphics buffers, such as an on-screen framebuffer. GEM does not provide + * an implementation of these interfaces. It's up to the DRM driver to + * provide an implementation that suits the hardware. If the hardware device + * contains dedicated video memory, the DRM driver can use the VRAM helper + * library. Each active buffer object is stored in video RAM. Active + * buffer are used for drawing the current frame, typically something like + * the frame's scanout buffer or the cursor image. If there's no more space + * left in VRAM, inactive GEM objects can be moved to system memory. + * + * The easiest way to use the VRAM helper library is to call + * drm_vram_helper_alloc_mm(). The function allocates and initializes an + * instance of &struct drm_vram_mm in &struct drm_device.vram_mm . Use + * &DRM_GEM_VRAM_DRIVER to initialize &struct drm_driver and + * &DRM_VRAM_MM_FILE_OPERATIONS to initialize &struct file_operations; + * as illustrated below. + * + * .. code-block:: c + * + * struct file_operations fops ={ + * .owner = THIS_MODULE, + * DRM_VRAM_MM_FILE_OPERATION + * }; + * struct drm_driver drv = { + * .driver_feature = DRM_ ... , + * .fops = &fops, + * DRM_GEM_VRAM_DRIVER + * }; + * + * int init_drm_driver() + * { + * struct drm_device *dev; + * uint64_t vram_base; + * unsigned long vram_size; + * int ret; + * + * // setup device, vram base and size + * // ... + * + * ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size, + * &drm_gem_vram_mm_funcs); + * if (ret) + * return ret; + * return 0; + * } + * + * This creates an instance of &struct drm_vram_mm, exports DRM userspace + * interfaces for GEM buffer management and initializes file operations to + * allow for accessing created GEM buffers. With this setup, the DRM driver + * manages an area of video RAM with VRAM MM and provides GEM VRAM objects + * to userspace. + * + * To clean up the VRAM memory management, call drm_vram_helper_release_mm() + * in the driver's clean-up code. + * + * .. code-block:: c + * + * void fini_drm_driver() + * { + * struct drm_device *dev = ...; + * + * drm_vram_helper_release_mm(dev); + * } + * + * For drawing or scanout operations, buffer object have to be pinned in video + * RAM. Call drm_gem_vram_pin() with &DRM_GEM_VRAM_PL_FLAG_VRAM or + * &DRM_GEM_VRAM_PL_FLAG_SYSTEM to pin a buffer object in video RAM or system + * memory. Call drm_gem_vram_unpin() to release the pinned object afterwards. + * If you have to evict a buffer object from video RAM (e.g., for freeing up + * memory), unpin the buffer and call drm_gem_vram_push_to_system(). + * + * A buffer object that is pinned in video RAM has a fixed address within that + * memory region. Call drm_gem_vram_offset() to retrieve this value. Typically + * it's used to program the hardware's scanout engine for framebuffers, set + * the cursor overlay's image for a mouse cursor, or use it as input to the + * hardware's draing engine. + * + * To access a buffer object's memory from the DRM driver, call + * drm_gem_vram_kmap(). It (optionally) maps the buffer into kernel address + * space and returns the memory address. Use drm_gem_vram_kunmap() to + * release the mapping. + */ + MODULE_DESCRIPTION("DRM VRAM memory-management helpers"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c index d17c5169b018..c94a6dc5ade7 100644 --- a/drivers/gpu/drm/drm_vram_mm_helper.c +++ b/drivers/gpu/drm/drm_vram_mm_helper.c @@ -208,3 +208,88 @@ int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, return ttm_bo_mmap(filp, vma, &vmm->bdev); } EXPORT_SYMBOL(drm_vram_mm_mmap); + +/* + * Helpers for integration with struct drm_device + */ + +/** + * drm_vram_helper_alloc_mm - Allocates a device's instance of \ + &struct drm_vram_mm + * @dev: the DRM device + * @vram_base: the base address of the video memory + * @vram_size: the size of the video memory in bytes + * @funcs: callback functions for buffer objects + * + * Returns: + * The new instance of &struct drm_vram_mm on success, or + * an ERR_PTR()-encoded errno code otherwise. + */ +struct drm_vram_mm *drm_vram_helper_alloc_mm( + struct drm_device *dev, uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs) +{ + int ret; + + if (WARN_ON(dev->vram_mm)) + return dev->vram_mm; + + dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL); + if (!dev->vram_mm) + return ERR_PTR(-ENOMEM); + + ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs); + if (ret) + goto err_kfree; + + return dev->vram_mm; + +err_kfree: + kfree(dev->vram_mm); + dev->vram_mm = NULL; + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_vram_helper_alloc_mm); + +/** + * drm_vram_helper_release_mm - Releases a device's instance of \ + &struct drm_vram_mm + * @dev: the DRM device + */ +void drm_vram_helper_release_mm(struct drm_device *dev) +{ + if (!dev->vram_mm) + return; + + drm_vram_mm_cleanup(dev->vram_mm); + kfree(dev->vram_mm); + dev->vram_mm = NULL; +} +EXPORT_SYMBOL(drm_vram_helper_release_mm); + +/* + * Helpers for &struct file_operations + */ + +/** + * drm_vram_mm_file_operations_mmap() - \ + Implements &struct file_operations.mmap() + * @filp: the mapping's file structure + * @vma: the mapping's memory area + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_file_operations_mmap( + struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_device *dev = file_priv->minor->dev; + + if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) + return -EINVAL; + + return drm_vram_mm_mmap(filp, vma, dev->vram_mm); +} +EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap); diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 7f9ef709b2b6..1acfc3bbd3fb 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -17,6 +17,7 @@ struct drm_vblank_crtc; struct drm_sg_mem; struct drm_local_map; struct drm_vma_offset_manager; +struct drm_vram_mm; struct drm_fb_helper; struct inode; @@ -286,6 +287,9 @@ struct drm_device { /** @vma_offset_manager: GEM information */ struct drm_vma_offset_manager *vma_offset_manager; + /** @vram_mm: VRAM MM memory manager */ + struct drm_vram_mm *vram_mm; + /** * @switch_power_state: * diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 7971656afe87..b056f189ba62 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -11,6 +11,7 @@ struct drm_mode_create_dumb; struct drm_vram_mm_funcs; struct filp; +struct vm_area_struct; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM #define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM @@ -115,10 +116,26 @@ extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs; */ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); - +int drm_gem_vram_driver_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args); int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); + +/** + * define DRM_GEM_VRAM_DRIVER - default callback functions for \ + &struct drm_driver + * + * Drivers that use VRAM MM and GEM VRAM can use this macro to initialize + * &struct drm_driver with default functions. + */ +#define DRM_GEM_VRAM_DRIVER \ + .gem_free_object_unlocked = \ + drm_gem_vram_driver_gem_free_object_unlocked, \ + .dumb_create = drm_gem_vram_driver_dumb_create, \ + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset + /* * PRIME helpers for struct drm_driver */ diff --git a/include/drm/drm_vram_mm_helper.h b/include/drm/drm_vram_mm_helper.h index 5d45c6447fa4..a8ffd8599b08 100644 --- a/include/drm/drm_vram_mm_helper.h +++ b/include/drm/drm_vram_mm_helper.h @@ -66,4 +66,37 @@ void drm_vram_mm_cleanup(struct drm_vram_mm *vmm); int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, struct drm_vram_mm *vmm); +/* + * Helpers for integration with struct drm_device + */ + +struct drm_vram_mm *drm_vram_helper_alloc_mm( + struct drm_device *dev, uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs); +void drm_vram_helper_release_mm(struct drm_device *dev); + +/* + * Helpers for &struct file_operations + */ + +int drm_vram_mm_file_operations_mmap( + struct file *filp, struct vm_area_struct *vma); + +/** + * define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \ + &struct file_operations + * + * Drivers that use VRAM MM can use this macro to initialize + * &struct file_operations with default functions. + */ +#define DRM_VRAM_MM_FILE_OPERATIONS \ + .llseek = no_llseek, \ + .read = drm_read, \ + .poll = drm_poll, \ + .unlocked_ioctl = drm_ioctl, \ + .compat_ioctl = drm_compat_ioctl, \ + .mmap = drm_vram_mm_file_operations_mmap, \ + .open = drm_open, \ + .release = drm_release \ + #endif -- cgit v1.3-6-gb490 From 75b3f1cb50bdbdc7fd557ca3ed63b3eb87c2bab3 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Tue, 15 Jan 2019 15:04:18 +0000 Subject: drm: Fix drm.h uapi header for GNU/kFreeBSD Like GNU/Linux, GNU/kFreeBSD's sys/types.h does not define the uintX_t types, which differs from the BSDs' headers. Thus we should include stdint.h to ensure we have all the required integer types. Signed-off-by: James Clarke Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20190115150418.68080-1-jrtc27@jrtc27.com Reviewed-by: Eric Anholt --- include/uapi/drm/drm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 661d73f9a919..8a5b2f8f8eb9 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -50,6 +50,7 @@ typedef unsigned int drm_handle_t; #else /* One of the BSDs */ +#include #include #include typedef int8_t __s8; -- cgit v1.3-6-gb490 From 82ff2fb5d184e95c7877c58359cef4f5d43df9c1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 16 May 2019 18:27:45 +0200 Subject: drm: Add drm_gem_vram_{pin/unpin}_reserved() and convert mgag200 The new interfaces drm_gem_vram_{pin/unpin}_reserved() are variants of the GEM VRAM pin/unpin functions that do not reserve the BO during validation. The mgag200 driver requires this behavior for its cursor handling. The patch also converts the driver to use the new interfaces. Signed-off-by: Thomas Zimmermann Link: http://patchwork.freedesktop.org/patch/msgid/20190516162746.11636-2-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/drm_gem_vram_helper.c | 75 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/mgag200/mgag200_cursor.c | 18 ++++---- include/drm/drm_gem_vram_helper.h | 3 ++ 3 files changed, 88 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 8f142b810eb4..a002c03eaf4c 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -254,6 +254,47 @@ int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) } EXPORT_SYMBOL(drm_gem_vram_pin); +/** + * drm_gem_vram_pin_reserved() - Pins a GEM VRAM object in a region. + * @gbo: the GEM VRAM object + * @pl_flag: a bitmask of possible memory regions + * + * Pinning a buffer object ensures that it is not evicted from + * a memory region. A pinned buffer object has to be unpinned before + * it can be pinned to another region. + * + * This function pins a GEM VRAM object that has already been + * reserved. Use drm_gem_vram_pin() if possible. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, + unsigned long pl_flag) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (gbo->pin_count) { + ++gbo->pin_count; + return 0; + } + + drm_gem_vram_placement(gbo, pl_flag); + for (i = 0; i < gbo->placement.num_placement; ++i) + gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + gbo->pin_count = 1; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_pin_reserved); + /** * drm_gem_vram_unpin() - Unpins a GEM VRAM object * @gbo: the GEM VRAM object @@ -285,6 +326,40 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) } EXPORT_SYMBOL(drm_gem_vram_unpin); +/** + * drm_gem_vram_unpin_reserved() - Unpins a GEM VRAM object + * @gbo: the GEM VRAM object + * + * This function unpins a GEM VRAM object that has already been + * reserved. Use drm_gem_vram_unpin() if possible. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (WARN_ON_ONCE(!gbo->pin_count)) + return 0; + + --gbo->pin_count; + if (gbo->pin_count) + return 0; + + for (i = 0; i < gbo->placement.num_placement ; ++i) + gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_unpin_reserved); + /** * drm_gem_vram_push_to_system() - \ Unpins a GEM VRAM object and moves it to system memory diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index 6c1a9d724d85..1c4fc85315a0 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -23,9 +23,9 @@ static void mga_hide_cursor(struct mga_device *mdev) WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); if (mdev->cursor.pixels_1->pin_count) - drm_gem_vram_unpin(mdev->cursor.pixels_1); + drm_gem_vram_unpin_reserved(mdev->cursor.pixels_1); if (mdev->cursor.pixels_2->pin_count) - drm_gem_vram_unpin(mdev->cursor.pixels_2); + drm_gem_vram_unpin_reserved(mdev->cursor.pixels_2); } int mga_crtc_cursor_set(struct drm_crtc *crtc, @@ -96,26 +96,28 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, /* Move cursor buffers into VRAM if they aren't already */ if (!pixels_1->pin_count) { - ret = drm_gem_vram_pin(pixels_1, DRM_GEM_VRAM_PL_FLAG_VRAM); + ret = drm_gem_vram_pin_reserved(pixels_1, + DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) goto out1; gpu_addr = drm_gem_vram_offset(pixels_1); if (gpu_addr < 0) { - drm_gem_vram_unpin(pixels_1); + drm_gem_vram_unpin_reserved(pixels_1); goto out1; } mdev->cursor.pixels_1_gpu_addr = gpu_addr; } if (!pixels_2->pin_count) { - ret = drm_gem_vram_pin(pixels_2, DRM_GEM_VRAM_PL_FLAG_VRAM); + ret = drm_gem_vram_pin_reserved(pixels_2, + DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) { - drm_gem_vram_unpin(pixels_1); + drm_gem_vram_unpin_reserved(pixels_1); goto out1; } gpu_addr = drm_gem_vram_offset(pixels_2); if (gpu_addr < 0) { - drm_gem_vram_unpin(pixels_1); - drm_gem_vram_unpin(pixels_2); + drm_gem_vram_unpin_reserved(pixels_1); + drm_gem_vram_unpin_reserved(pixels_2); goto out1; } mdev->cursor.pixels_2_gpu_addr = gpu_addr; diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index b056f189ba62..ff1a81761543 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -82,7 +82,10 @@ void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo); u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); +int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, + unsigned long pl_flag); int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); +int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo); int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo); void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, bool *is_iomem, struct ttm_bo_kmap_obj *kmap); -- cgit v1.3-6-gb490 From 05c452c115bffa12f78346723f0282a4264ed200 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 12:31:47 +0200 Subject: drm: Remove users of drm_format_num_planes drm_format_num_planes() is basically a lookup in the drm_format_info table plus an access to the num_planes field of the appropriate entry. Most drivers are using this function while having access to the entry already, which means that we will perform an unnecessary lookup. Removing the call to drm_format_num_planes is therefore more efficient. Some drivers will not have access to that entry in the function, but in this case the overhead is minimal (we just have to call drm_format_info() to perform the lookup) and we can even avoid multiple, inefficient lookups in some places that need multiple fields from the drm_format_info structure. Reviewed-by: Emil Velikov Reviewed-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/5ffcec9d14a50ed538e37d565f546802452ee672.1558002671.git-series.maxime.ripard@bootlin.com --- drivers/gpu/drm/arm/malidp_mw.c | 2 +- drivers/gpu/drm/armada/armada_fb.c | 3 ++- drivers/gpu/drm/drm_fourcc.c | 16 ---------------- drivers/gpu/drm/mediatek/mtk_drm_fb.c | 6 ++++-- drivers/gpu/drm/meson/meson_overlay.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 9 ++++++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 3 ++- drivers/gpu/drm/msm/msm_fb.c | 8 ++++++-- drivers/gpu/drm/omapdrm/omap_fb.c | 4 +++- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 6 +++--- drivers/gpu/drm/tegra/fb.c | 3 ++- drivers/gpu/drm/vc4/vc4_plane.c | 2 +- drivers/gpu/drm/zte/zx_plane.c | 4 +--- include/drm/drm_fourcc.h | 1 - 14 files changed, 32 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 5f102bdaf841..2e812525025d 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -158,7 +158,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, return -EINVAL; } - n_planes = drm_format_num_planes(fb->format->format); + n_planes = fb->format->num_planes; for (i = 0; i < n_planes; i++) { struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c index 058ac7d9920f..a2f6472eb482 100644 --- a/drivers/gpu/drm/armada/armada_fb.c +++ b/drivers/gpu/drm/armada/armada_fb.c @@ -87,6 +87,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev, struct drm_framebuffer *armada_fb_create(struct drm_device *dev, struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode) { + const struct drm_format_info *info = drm_get_format_info(dev, mode); struct armada_gem_object *obj; struct armada_framebuffer *dfb; int ret; @@ -97,7 +98,7 @@ struct drm_framebuffer *armada_fb_create(struct drm_device *dev, mode->pitches[2]); /* We can only handle a single plane at the moment */ - if (drm_format_num_planes(mode->pixel_format) > 1 && + if (info->num_planes > 1 && (mode->handles[0] != mode->handles[1] || mode->handles[0] != mode->handles[2])) { ret = -EINVAL; diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 6ea55fb4526d..873c0001d8c8 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -332,22 +332,6 @@ drm_get_format_info(struct drm_device *dev, } EXPORT_SYMBOL(drm_get_format_info); -/** - * drm_format_num_planes - get the number of planes for format - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The number of planes used by the specified pixel format. - */ -int drm_format_num_planes(uint32_t format) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - return info ? info->num_planes : 1; -} -EXPORT_SYMBOL(drm_format_num_planes); - /** * drm_format_plane_cpp - determine the bytes per pixel value * @format: pixel format (DRM_FORMAT_*) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index e20fcaef2851..68fdef8b12bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -32,10 +32,11 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode, struct drm_gem_object *obj) { + const struct drm_format_info *info = drm_get_format_info(dev, mode); struct drm_framebuffer *fb; int ret; - if (drm_format_num_planes(mode->pixel_format) != 1) + if (info->num_planes != 1) return ERR_PTR(-EINVAL); fb = kzalloc(sizeof(*fb), GFP_KERNEL); @@ -88,6 +89,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd) { + const struct drm_format_info *info = drm_get_format_info(dev, cmd); struct drm_framebuffer *fb; struct drm_gem_object *gem; unsigned int width = cmd->width; @@ -95,7 +97,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, unsigned int size, bpp; int ret; - if (drm_format_num_planes(cmd->pixel_format) != 1) + if (info->num_planes != 1) return ERR_PTR(-EINVAL); gem = drm_gem_object_lookup(file, cmd->handles[0]); diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index bdbf925ff3e8..fb8515b2860c 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -458,7 +458,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, } /* Update Canvas with buffer address */ - priv->viu.vd1_planes = drm_format_num_planes(fb->format->format); + priv->viu.vd1_planes = fb->format->num_planes; switch (priv->viu.vd1_planes) { case 3: diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c index f59fe1a9f4b9..c3d491e8d44b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c @@ -1040,10 +1040,11 @@ int dpu_format_check_modified_format( const struct drm_mode_fb_cmd2 *cmd, struct drm_gem_object **bos) { - int ret, i, num_base_fmt_planes; + const struct drm_format_info *info; const struct dpu_format *fmt; struct dpu_hw_fmt_layout layout; uint32_t bos_total_size = 0; + int ret, i; if (!msm_fmt || !cmd || !bos) { DRM_ERROR("invalid arguments\n"); @@ -1051,14 +1052,16 @@ int dpu_format_check_modified_format( } fmt = to_dpu_format(msm_fmt); - num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format); + info = drm_format_info(fmt->base.pixel_format); + if (!info) + return -EINVAL; ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height, &layout, cmd->pitches); if (ret) return ret; - for (i = 0; i < num_base_fmt_planes; i++) { + for (i = 0; i < info->num_planes; i++) { if (!bos[i]) { DRM_ERROR("invalid handle for plane %d\n", i); return -EINVAL; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 6153514db04c..72ab8d89efa4 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -127,13 +127,14 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, const struct mdp_format *format, u32 width, bool hdecim) { + const struct drm_format_info *info = drm_format_info(format->base.pixel_format); struct mdp5_kms *mdp5_kms = get_kms(smp); int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg); int i, hsub, nplanes, nlines; u32 fmt = format->base.pixel_format; uint32_t blkcfg = 0; - nplanes = drm_format_num_planes(fmt); + nplanes = info->num_planes; hsub = drm_format_horz_chroma_subsampling(fmt); /* different if BWC (compressed framebuffer?) enabled: */ diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 136058978e0f..432beddafb9e 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -106,9 +106,11 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb) struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) { + const struct drm_format_info *info = drm_get_format_info(dev, + mode_cmd); struct drm_gem_object *bos[4] = {0}; struct drm_framebuffer *fb; - int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format); + int ret, i, n = info->num_planes; for (i = 0; i < n; i++) { bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); @@ -135,6 +137,8 @@ out_unref: static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) { + const struct drm_format_info *info = drm_get_format_info(dev, + mode_cmd); struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; struct msm_framebuffer *msm_fb = NULL; @@ -147,7 +151,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, dev, mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); - n = drm_format_num_planes(mode_cmd->pixel_format); + n = info->num_planes; hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 4f8eb9d08f99..cfb641363a32 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -298,7 +298,9 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) { - unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format); + const struct drm_format_info *info = drm_get_format_info(dev, + mode_cmd); + unsigned int num_planes = info->num_planes; struct drm_gem_object *bos[4]; struct drm_framebuffer *fb; int i; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 97438bbbe389..606d176d5d96 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -74,19 +74,19 @@ static struct drm_framebuffer * rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { + const struct drm_format_info *info = drm_get_format_info(dev, + mode_cmd); struct drm_framebuffer *fb; struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER]; struct drm_gem_object *obj; unsigned int hsub; unsigned int vsub; - int num_planes; + int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER); int ret; int i; hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); - num_planes = min(drm_format_num_planes(mode_cmd->pixel_format), - ROCKCHIP_MAX_FB_BUFFER); for (i = 0; i < num_planes; i++) { unsigned int width = mode_cmd->width / (i ? hsub : 1); diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 1dd83a757dba..da0747e317b7 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -131,6 +131,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd) { + const struct drm_format_info *info = drm_get_format_info(drm, cmd); unsigned int hsub, vsub, i; struct tegra_bo *planes[4]; struct drm_gem_object *gem; @@ -140,7 +141,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); - for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) { + for (i = 0; i < info->num_planes; i++) { unsigned int width = cmd->width / (i ? hsub : 1); unsigned int height = cmd->height / (i ? vsub : 1); unsigned int size, bpp; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 4d918d3e4858..e3c0a350cb77 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -592,7 +592,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, u32 ctl0_offset = vc4_state->dlist_count; const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); - int num_planes = drm_format_num_planes(format->drm); + int num_planes = fb->format->num_planes; u32 h_subsample, v_subsample; bool mix_plane_alpha; bool covers_screen; diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index 83d236fd893c..c6a8be444300 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -199,7 +199,6 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, u32 dst_x, dst_y, dst_w, dst_h; uint32_t format; int fmt; - int num_planes; int i; if (!fb) @@ -218,9 +217,8 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, dst_h = drm_rect_height(dst); /* Set up data address registers for Y, Cb and Cr planes */ - num_planes = drm_format_num_planes(format); paddr_reg = layer + VL_Y; - for (i = 0; i < num_planes; i++) { + for (i = 0; i < fb->format->num_planes; i++) { cma_obj = drm_fb_cma_get_gem_obj(fb, i); paddr = cma_obj->paddr + fb->offsets[i]; paddr += src_y * fb->pitches[i]; diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index b3d9d88ab290..41779b327d91 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -268,7 +268,6 @@ drm_get_format_info(struct drm_device *dev, uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth); -int drm_format_num_planes(uint32_t format); int drm_format_plane_cpp(uint32_t format, int plane); int drm_format_horz_chroma_subsampling(uint32_t format); int drm_format_vert_chroma_subsampling(uint32_t format); -- cgit v1.3-6-gb490 From f3e9632cb6241a6c098427510ad3ee041365ae64 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 12:31:48 +0200 Subject: drm: Remove users of drm_format_(horz|vert)_chroma_subsampling drm_format_horz_chroma_subsampling and drm_format_vert_chroma_subsampling are basically a lookup in the drm_format_info table plus an access to the hsub and vsub fields of the appropriate entry. Most drivers are using this function while having access to the entry already, which means that we will perform an unnecessary lookup. Removing the call to these functions is therefore more efficient. Some drivers will not have access to that entry in the function, but in this case the overhead is minimal (we just have to call drm_format_info() to perform the lookup) and we can even avoid multiple, inefficient lookups in some places that need multiple fields from the drm_format_info structure. This is amplified by the fact that most of the time the callers will have to retrieve both the vsub and hsub fields, meaning that they would perform twice the lookup. Reviewed-by: Emil Velikov Reviewed-by: Paul Kocialkowski Reviewed-by: Philipp Zabel Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/6b3cceb8161e2c1d40c2681de99202328b0a8abc.1558002671.git-series.maxime.ripard@bootlin.com --- drivers/gpu/drm/arm/malidp_planes.c | 6 ++--- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 9 ++----- drivers/gpu/drm/drm_fourcc.c | 34 ------------------------- drivers/gpu/drm/imx/ipuv3-plane.c | 15 +++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 9 ++----- drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 24 ++++++++--------- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +- drivers/gpu/drm/msm/msm_fb.c | 8 ++---- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 9 ++----- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 +++----- drivers/gpu/drm/tegra/fb.c | 9 +++---- drivers/gpu/drm/vc4/vc4_plane.c | 13 +++------- include/drm/drm_fourcc.h | 2 -- 13 files changed, 38 insertions(+), 112 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index d42e0ea9a303..8f89813d08c1 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -233,8 +233,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, } } - if ((drm_format_horz_chroma_subsampling(format) != 1) || - (drm_format_vert_chroma_subsampling(format) != 1)) { + if ((info->hsub != 1) || (info->vsub != 1)) { if (!(format == DRM_FORMAT_YUV420_10BIT && (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) { DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n"); @@ -244,8 +243,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, } if (modifier & AFBC_CBR) { - if ((drm_format_horz_chroma_subsampling(format) == 1) || - (drm_format_vert_chroma_subsampling(format) == 1)) { + if ((info->hsub == 1) || (info->vsub == 1)) { DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n"); return false; } diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index e836e2de35ce..fdd607ad27fe 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -603,8 +603,6 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, const struct drm_display_mode *mode; struct drm_crtc_state *crtc_state; unsigned int tmp; - int hsub = 1; - int vsub = 1; int ret; int i; @@ -642,13 +640,10 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) return -EINVAL; - hsub = drm_format_horz_chroma_subsampling(fb->format->format); - vsub = drm_format_vert_chroma_subsampling(fb->format->format); - for (i = 0; i < state->nplanes; i++) { unsigned int offset = 0; - int xdiv = i ? hsub : 1; - int ydiv = i ? vsub : 1; + int xdiv = i ? fb->format->hsub : 1; + int ydiv = i ? fb->format->vsub : 1; state->bpp[i] = fb->format->cpp[i]; if (!state->bpp[i]) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 873c0001d8c8..e4a2c8372c8b 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -352,40 +352,6 @@ int drm_format_plane_cpp(uint32_t format, int plane) } EXPORT_SYMBOL(drm_format_plane_cpp); -/** - * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The horizontal chroma subsampling factor for the - * specified pixel format. - */ -int drm_format_horz_chroma_subsampling(uint32_t format) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - return info ? info->hsub : 1; -} -EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); - -/** - * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The vertical chroma subsampling factor for the - * specified pixel format. - */ -int drm_format_vert_chroma_subsampling(uint32_t format) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - return info ? info->vsub : 1; -} -EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); - /** * drm_format_plane_width - width of the plane given the first plane * @width: width of the first plane diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index d7a727a6e3d7..8f101a0763e3 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -115,8 +115,8 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) cma_obj = drm_fb_cma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); - x /= drm_format_horz_chroma_subsampling(fb->format->format); - y /= drm_format_vert_chroma_subsampling(fb->format->format); + x /= fb->format->hsub; + y /= fb->format->vsub; return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + fb->format->cpp[1] * x - eba; @@ -134,8 +134,8 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) cma_obj = drm_fb_cma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); - x /= drm_format_horz_chroma_subsampling(fb->format->format); - y /= drm_format_vert_chroma_subsampling(fb->format->format); + x /= fb->format->hsub; + y /= fb->format->vsub; return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + fb->format->cpp[2] * x - eba; @@ -352,7 +352,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, struct drm_framebuffer *old_fb = old_state->fb; unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); - int hsub, vsub; int ret; /* Ok to disable */ @@ -471,10 +470,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, * The x/y offsets must be even in case of horizontal/vertical * chroma subsampling. */ - hsub = drm_format_horz_chroma_subsampling(fb->format->format); - vsub = drm_format_vert_chroma_subsampling(fb->format->format); - if (((state->src.x1 >> 16) & (hsub - 1)) || - ((state->src.y1 >> 16) & (vsub - 1))) + if (((state->src.x1 >> 16) & (fb->format->hsub - 1)) || + ((state->src.y1 >> 16) & (fb->format->vsub - 1))) return -EINVAL; break; case DRM_FORMAT_RGB565_A8: diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index da1f727d7495..7994de952353 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -557,14 +557,9 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, struct dpu_plane_state *pstate, const struct dpu_format *fmt, bool color_fill) { - uint32_t chroma_subsmpl_h, chroma_subsmpl_v; + const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format); /* don't chroma subsample if decimating */ - chroma_subsmpl_h = - drm_format_horz_chroma_subsampling(fmt->base.pixel_format); - chroma_subsmpl_v = - drm_format_vert_chroma_subsampling(fmt->base.pixel_format); - /* update scaler. calculate default config for QSEED3 */ _dpu_plane_setup_scaler3(pdpu, pstate, drm_rect_width(&pdpu->pipe_cfg.src_rect), @@ -572,7 +567,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, drm_rect_width(&pdpu->pipe_cfg.dst_rect), drm_rect_height(&pdpu->pipe_cfg.dst_rect), &pstate->scaler3_cfg, fmt, - chroma_subsmpl_h, chroma_subsmpl_v); + info->hsub, info->vsub); } /** diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index be13140967b4..9d9fb6c5fd68 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -650,10 +650,10 @@ static int calc_scalex_steps(struct drm_plane *plane, uint32_t pixel_format, uint32_t src, uint32_t dest, uint32_t phasex_steps[COMP_MAX]) { + const struct drm_format_info *info = drm_format_info(pixel_format); struct mdp5_kms *mdp5_kms = get_kms(plane); struct device *dev = mdp5_kms->dev->dev; uint32_t phasex_step; - unsigned int hsub; int ret; ret = calc_phase_step(src, dest, &phasex_step); @@ -662,11 +662,9 @@ static int calc_scalex_steps(struct drm_plane *plane, return ret; } - hsub = drm_format_horz_chroma_subsampling(pixel_format); - phasex_steps[COMP_0] = phasex_step; phasex_steps[COMP_3] = phasex_step; - phasex_steps[COMP_1_2] = phasex_step / hsub; + phasex_steps[COMP_1_2] = phasex_step / info->hsub; return 0; } @@ -675,10 +673,10 @@ static int calc_scaley_steps(struct drm_plane *plane, uint32_t pixel_format, uint32_t src, uint32_t dest, uint32_t phasey_steps[COMP_MAX]) { + const struct drm_format_info *info = drm_format_info(pixel_format); struct mdp5_kms *mdp5_kms = get_kms(plane); struct device *dev = mdp5_kms->dev->dev; uint32_t phasey_step; - unsigned int vsub; int ret; ret = calc_phase_step(src, dest, &phasey_step); @@ -687,11 +685,9 @@ static int calc_scaley_steps(struct drm_plane *plane, return ret; } - vsub = drm_format_vert_chroma_subsampling(pixel_format); - phasey_steps[COMP_0] = phasey_step; phasey_steps[COMP_3] = phasey_step; - phasey_steps[COMP_1_2] = phasey_step / vsub; + phasey_steps[COMP_1_2] = phasey_step / info->vsub; return 0; } @@ -699,8 +695,9 @@ static int calc_scaley_steps(struct drm_plane *plane, static uint32_t get_scale_config(const struct mdp_format *format, uint32_t src, uint32_t dst, bool horz) { + const struct drm_format_info *info = drm_format_info(format->base.pixel_format); bool scaling = format->is_yuv ? true : (src != dst); - uint32_t sub, pix_fmt = format->base.pixel_format; + uint32_t sub; uint32_t ya_filter, uv_filter; bool yuv = format->is_yuv; @@ -708,8 +705,7 @@ static uint32_t get_scale_config(const struct mdp_format *format, return 0; if (yuv) { - sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) : - drm_format_vert_chroma_subsampling(pix_fmt); + sub = horz ? info->hsub : info->vsub; uv_filter = ((src / sub) <= dst) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN; } @@ -754,7 +750,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX], uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX]) { - uint32_t pix_fmt = format->base.pixel_format; + const struct drm_format_info *info = drm_format_info(format->base.pixel_format); uint32_t lr, tb, req; int i; @@ -763,8 +759,8 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, uint32_t roi_h = src_h; if (format->is_yuv && i == COMP_1_2) { - roi_w /= drm_format_horz_chroma_subsampling(pix_fmt); - roi_h /= drm_format_vert_chroma_subsampling(pix_fmt); + roi_w /= info->hsub; + roi_h /= info->vsub; } lr = (pe_left[i] >= 0) ? diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 72ab8d89efa4..b30b2f4efc60 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -135,7 +135,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, uint32_t blkcfg = 0; nplanes = info->num_planes; - hsub = drm_format_horz_chroma_subsampling(fmt); + hsub = info->hsub; /* different if BWC (compressed framebuffer?) enabled: */ nlines = 2; diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 432beddafb9e..f69c0afd6ec6 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -145,16 +145,12 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb; const struct msm_format *format; int ret, i, n; - unsigned int hsub, vsub; DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", dev, mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); n = info->num_planes; - hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); - vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); - format = kms->funcs->get_format(kms, mode_cmd->pixel_format, mode_cmd->modifier[0]); if (!format) { @@ -180,8 +176,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, } for (i = 0; i < n; i++) { - unsigned int width = mode_cmd->width / (i ? hsub : 1); - unsigned int height = mode_cmd->height / (i ? vsub : 1); + unsigned int width = mode_cmd->width / (i ? info->hsub : 1); + unsigned int height = mode_cmd->height / (i ? info->vsub : 1); unsigned int min_size; min_size = (height - 1) * mode_cmd->pitches[i] diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 606d176d5d96..c318fae28581 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -79,18 +79,13 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, struct drm_framebuffer *fb; struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER]; struct drm_gem_object *obj; - unsigned int hsub; - unsigned int vsub; int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER); int ret; int i; - hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); - vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); - for (i = 0; i < num_planes; i++) { - unsigned int width = mode_cmd->width / (i ? hsub : 1); - unsigned int height = mode_cmd->height / (i ? vsub : 1); + unsigned int width = mode_cmd->width / (i ? info->hsub : 1); + unsigned int height = mode_cmd->height / (i ? info->vsub : 1); unsigned int min_size; obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c709f64b6f80..4189ca17f381 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -320,11 +320,9 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; uint16_t cbcr_hor_scl_mode = SCALE_NONE; uint16_t cbcr_ver_scl_mode = SCALE_NONE; - int hsub = drm_format_horz_chroma_subsampling(info->format); - int vsub = drm_format_vert_chroma_subsampling(info->format); bool is_yuv = false; - uint16_t cbcr_src_w = src_w / hsub; - uint16_t cbcr_src_h = src_h / vsub; + uint16_t cbcr_src_w = src_w / info->hsub; + uint16_t cbcr_src_h = src_h / info->vsub; uint16_t vsu_mode; uint16_t lb_mode; uint32_t val; @@ -828,8 +826,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0); if (is_yuv) { - int hsub = drm_format_horz_chroma_subsampling(fb->format->format); - int vsub = drm_format_vert_chroma_subsampling(fb->format->format); + int hsub = fb->format->hsub; + int vsub = fb->format->vsub; int bpp = fb->format->cpp[1]; uv_obj = fb->obj[1]; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index da0747e317b7..94fb75089d87 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -132,18 +132,15 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, const struct drm_mode_fb_cmd2 *cmd) { const struct drm_format_info *info = drm_get_format_info(drm, cmd); - unsigned int hsub, vsub, i; struct tegra_bo *planes[4]; struct drm_gem_object *gem; struct drm_framebuffer *fb; + unsigned int i; int err; - hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); - vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); - for (i = 0; i < info->num_planes; i++) { - unsigned int width = cmd->width / (i ? hsub : 1); - unsigned int height = cmd->height / (i ? vsub : 1); + unsigned int width = cmd->width / (i ? info->hsub : 1); + unsigned int height = cmd->height / (i ? info->vsub : 1); unsigned int size, bpp; gem = drm_gem_object_lookup(file, cmd->handles[i]); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index e3c0a350cb77..be2274924b34 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -310,10 +310,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); u32 subpixel_src_mask = (1 << 16) - 1; - u32 format = fb->format->format; int num_planes = fb->format->num_planes; struct drm_crtc_state *crtc_state; - u32 h_subsample, v_subsample; + u32 h_subsample = fb->format->hsub; + u32 v_subsample = fb->format->vsub; int i, ret; crtc_state = drm_atomic_get_existing_crtc_state(state->state, @@ -328,9 +328,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) if (ret) return ret; - h_subsample = drm_format_horz_chroma_subsampling(format); - v_subsample = drm_format_vert_chroma_subsampling(format); - for (i = 0; i < num_planes; i++) vc4_state->offsets[i] = bo->paddr + fb->offsets[i]; @@ -593,7 +590,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); int num_planes = fb->format->num_planes; - u32 h_subsample, v_subsample; + u32 h_subsample = fb->format->hsub; + u32 v_subsample = fb->format->vsub; bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0; @@ -623,9 +621,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane, scl1 = vc4_get_scl_field(state, 0); } - h_subsample = drm_format_horz_chroma_subsampling(format->drm); - v_subsample = drm_format_vert_chroma_subsampling(format->drm); - rotation = drm_rotation_simplify(state->rotation, DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X | diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 41779b327d91..eeec449d6c6a 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -269,8 +269,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth); int drm_format_plane_cpp(uint32_t format, int plane); -int drm_format_horz_chroma_subsampling(uint32_t format); -int drm_format_vert_chroma_subsampling(uint32_t format); int drm_format_plane_width(int width, uint32_t format, int plane); int drm_format_plane_height(int height, uint32_t format, int plane); unsigned int drm_format_info_block_width(const struct drm_format_info *info, -- cgit v1.3-6-gb490 From 24c478ead0bf50a758e9dbecc7356e9eebf20271 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 12:31:49 +0200 Subject: drm/fourcc: Pass the format_info pointer to drm_format_plane_cpp So far, the drm_format_plane_cpp function was operating on the format's fourcc and was doing a lookup to retrieve the drm_format_info structure and return the cpp. However, this is inefficient since in most cases, we will have the drm_format_info pointer already available so we shouldn't have to perform a new lookup. Some drm_fourcc functions also already operate on the drm_format_info pointer for that reason, so the API is quite inconsistent there. Let's follow the latter pattern and remove the extra lookup while being a bit more consistent. In order to be extra consistent, also rename that function to drm_format_info_plane_cpp and to a static function in the header to match the current policy. Reviewed-by: Emil Velikov Reviewed-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/32aa13e53dbc98a90207fd290aa8e79f785fb11e.1558002671.git-series.maxime.ripard@bootlin.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 +++- drivers/gpu/drm/arm/malidp_hw.c | 3 ++- drivers/gpu/drm/arm/malidp_planes.c | 2 +- drivers/gpu/drm/drm_client.c | 3 ++- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/drm_format_helper.c | 4 ++-- drivers/gpu/drm/drm_fourcc.c | 20 -------------------- drivers/gpu/drm/i915/intel_sprite.c | 3 ++- drivers/gpu/drm/mediatek/mtk_drm_fb.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 3 ++- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +- drivers/gpu/drm/msm/msm_fb.c | 2 +- drivers/gpu/drm/radeon/radeon_fb.c | 4 +++- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +- drivers/gpu/drm/stm/ltdc.c | 2 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/zte/zx_plane.c | 2 +- include/drm/drm_fourcc.h | 18 +++++++++++++++++- 18 files changed, 42 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index e47609218839..06e73a343724 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -121,6 +121,8 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **gobj_p) { + const struct drm_format_info *info = drm_get_format_info(dev, + mode_cmd); struct amdgpu_device *adev = rfbdev->adev; struct drm_gem_object *gobj = NULL; struct amdgpu_bo *abo = NULL; @@ -131,7 +133,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, int height = mode_cmd->height; u32 cpp; - cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); + cpp = drm_format_info_plane_cpp(info, 0); /* need to align pitch with crtc limits */ mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp, diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 8df12e9a33bb..1c9e869f4c52 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -382,7 +382,8 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * int malidp_format_get_bpp(u32 fmt) { - int bpp = drm_format_plane_cpp(fmt, 0) * 8; + const struct drm_format_info *info = drm_format_info(fmt); + int bpp = drm_format_info_plane_cpp(info, 0) * 8; if (bpp == 0) { switch (fmt) { diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 8f89813d08c1..361c02988375 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -227,7 +227,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, if (modifier & AFBC_SPLIT) { if (!info->is_yuv) { - if (drm_format_plane_cpp(format, 0) <= 2) { + if (drm_format_info_plane_cpp(info, 0) <= 2) { DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n"); return false; } diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index f20d1dda3961..169d8eeaa662 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -243,6 +243,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer) static struct drm_client_buffer * drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format) { + const struct drm_format_info *info = drm_format_info(format); struct drm_mode_create_dumb dumb_args = { }; struct drm_device *dev = client->dev; struct drm_client_buffer *buffer; @@ -258,7 +259,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u dumb_args.width = width; dumb_args.height = height; - dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8; + dumb_args.bpp = drm_format_info_plane_cpp(info, 0) * 8; ret = drm_mode_create_dumb(dev, &dumb_args, client->file); if (ret) goto err_delete; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a52b48fafbd7..e2d9a6da14a5 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -813,7 +813,7 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper, struct drm_clip_rect *clip) { struct drm_framebuffer *fb = fb_helper->fb; - unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0); + unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp; void *src = fb_helper->fbdev->screen_buffer + offset; void *dst = fb_helper->buffer->vaddr + offset; diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index a18da35145b7..8ad66aa1362a 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -36,7 +36,7 @@ static unsigned int clip_offset(struct drm_rect *clip, void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { - unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0); + unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; @@ -63,7 +63,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { - unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0); + unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); unsigned int offset = clip_offset(clip, fb->pitches[0], cpp); size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index e4a2c8372c8b..5f63fc74e265 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -332,26 +332,6 @@ drm_get_format_info(struct drm_device *dev, } EXPORT_SYMBOL(drm_get_format_info); -/** - * drm_format_plane_cpp - determine the bytes per pixel value - * @format: pixel format (DRM_FORMAT_*) - * @plane: plane index - * - * Returns: - * The bytes per pixel value for the specified plane. - */ -int drm_format_plane_cpp(uint32_t format, int plane) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - if (!info || plane >= info->num_planes) - return 0; - - return info->cpp[plane]; -} -EXPORT_SYMBOL(drm_format_plane_cpp); - /** * drm_format_plane_width - width of the plane given the first plane * @width: width of the first plane diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 2913e89280d7..e35601b1f878 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -325,7 +325,8 @@ skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation) { - int cpp = drm_format_plane_cpp(pixel_format, 0); + const struct drm_format_info *info = drm_format_info(pixel_format); + int cpp = drm_format_info_plane_cpp(info, 0); /* * "The stride in bytes must not exceed the diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index 68fdef8b12bd..0d5334a5a9a7 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -104,7 +104,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, if (!gem) return ERR_PTR(-ENOENT); - bpp = drm_format_plane_cpp(cmd->pixel_format, 0); + bpp = drm_format_info_plane_cpp(info, 0); size = (height - 1) * cmd->pitches[0] + width * bpp; size += cmd->offsets[0]; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index f33d7007e830..59b24e0c5070 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -782,6 +782,7 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h) static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) { + const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ARGB8888); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_kms *mdp5_kms = get_kms(crtc); @@ -800,7 +801,7 @@ static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) width = mdp5_crtc->cursor.width; height = mdp5_crtc->cursor.height; - stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0); + stride = width * drm_format_info_plane_cpp(info, 0); get_roi(crtc, &roi_w, &roi_h); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index b30b2f4efc60..1ca294694597 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -158,7 +158,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, for (i = 0; i < nplanes; i++) { int n, fetch_stride, cpp; - cpp = drm_format_plane_cpp(fmt, i); + cpp = drm_format_info_plane_cpp(info, i); fetch_stride = width * cpp / (i ? hsub : 1); n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size); diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index f69c0afd6ec6..29e45f2144b5 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -181,7 +181,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, unsigned int min_size; min_size = (height - 1) * mode_cmd->pitches[i] - + width * drm_format_plane_cpp(mode_cmd->pixel_format, i) + + width * drm_format_info_plane_cpp(info, i) + mode_cmd->offsets[i]; if (bos[i]->size < min_size) { diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 1298b84cb1c7..dbf596fc4339 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -125,6 +125,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **gobj_p) { + const struct drm_format_info *info; struct radeon_device *rdev = rfbdev->rdev; struct drm_gem_object *gobj = NULL; struct radeon_bo *rbo = NULL; @@ -135,7 +136,8 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, int height = mode_cmd->height; u32 cpp; - cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); + info = drm_get_format_info(rdev->ddev, mode_cmd); + cpp = drm_format_info_plane_cpp(info, 0); /* need to align pitch with crtc limits */ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index c318fae28581..57873c99ae29 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -98,7 +98,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, min_size = (height - 1) * mode_cmd->pitches[i] + mode_cmd->offsets[i] + - width * drm_format_plane_cpp(mode_cmd->pixel_format, i); + width * drm_format_info_plane_cpp(info, i); if (obj->size < min_size) { drm_gem_object_put_unlocked(obj); diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 97912e2c663d..e7abe54b9746 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -784,7 +784,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, /* Configures the color frame buffer pitch in bytes & line length */ pitch_in_bytes = fb->pitches[0]; - line_length = drm_format_plane_cpp(fb->format->format, 0) * + line_length = drm_format_info_plane_cpp(fb->format, 0) * (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; val = ((pitch_in_bytes << 16) | line_length); reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 94fb75089d87..d1042196a30f 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -149,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, goto unreference; } - bpp = drm_format_plane_cpp(cmd->pixel_format, i); + bpp = drm_format_info_plane_cpp(info, i); size = (height - 1) * cmd->pitches[i] + width * bpp + cmd->offsets[i]; diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index c6a8be444300..d97a4dff515d 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -222,7 +222,7 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, cma_obj = drm_fb_cma_get_gem_obj(fb, i); paddr = cma_obj->paddr + fb->offsets[i]; paddr += src_y * fb->pitches[i]; - paddr += src_x * drm_format_plane_cpp(format, i); + paddr += src_x * drm_format_info_plane_cpp(fb->format, i); zx_writel(paddr_reg, paddr); paddr_reg += 4; } diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index eeec449d6c6a..6b5a82b31bc4 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -260,6 +260,23 @@ drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info) return info->is_yuv && info->hsub == 1 && info->vsub == 1; } +/** + * drm_format_info_plane_cpp - determine the bytes per pixel value + * @format: pixel format info + * @plane: plane index + * + * Returns: + * The bytes per pixel value for the specified plane. + */ +static inline +int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane) +{ + if (!info || plane >= info->num_planes) + return 0; + + return info->cpp[plane]; +} + const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); const struct drm_format_info * @@ -268,7 +285,6 @@ drm_get_format_info(struct drm_device *dev, uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth); -int drm_format_plane_cpp(uint32_t format, int plane); int drm_format_plane_width(int width, uint32_t format, int plane); int drm_format_plane_height(int height, uint32_t format, int plane); unsigned int drm_format_info_block_width(const struct drm_format_info *info, -- cgit v1.3-6-gb490 From bf39607c16141811d0f5fe67e231364c96a87e09 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 12:31:50 +0200 Subject: drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height So far, the drm_format_plane_height/width functions were operating on the format's fourcc and was doing a lookup to retrieve the drm_format_info structure and return the cpp. However, this is inefficient since in most cases, we will have the drm_format_info pointer already available so we shouldn't have to perform a new lookup. Some drm_fourcc functions also already operate on the drm_format_info pointer for that reason, so the API is quite inconsistent there. Let's follow the latter pattern and remove the extra lookup while being a bit more consistent. In order to be extra consistent, also rename that function to drm_format_info_plane_cpp and to a static function in the header to match the current policy. The parameters order have also be changed to match the other functions prototype. Reviewed-by: Emil Velikov Reviewed-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/514af1d489d80b8b1767e3716b663ce5103da6eb.1558002671.git-series.maxime.ripard@bootlin.com --- drivers/gpu/drm/drm_fourcc.c | 48 ----------------------------------- drivers/gpu/drm/meson/meson_overlay.c | 12 ++++----- include/drm/drm_fourcc.h | 46 +++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 56 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 5f63fc74e265..35b459d186c5 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -332,54 +332,6 @@ drm_get_format_info(struct drm_device *dev, } EXPORT_SYMBOL(drm_get_format_info); -/** - * drm_format_plane_width - width of the plane given the first plane - * @width: width of the first plane - * @format: pixel format - * @plane: plane index - * - * Returns: - * The width of @plane, given that the width of the first plane is @width. - */ -int drm_format_plane_width(int width, uint32_t format, int plane) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - if (!info || plane >= info->num_planes) - return 0; - - if (plane == 0) - return width; - - return width / info->hsub; -} -EXPORT_SYMBOL(drm_format_plane_width); - -/** - * drm_format_plane_height - height of the plane given the first plane - * @height: height of the first plane - * @format: pixel format - * @plane: plane index - * - * Returns: - * The height of @plane, given that the height of the first plane is @height. - */ -int drm_format_plane_height(int height, uint32_t format, int plane) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - if (!info || plane >= info->num_planes) - return 0; - - if (plane == 0) - return height; - - return height / info->vsub; -} -EXPORT_SYMBOL(drm_format_plane_height); - /** * drm_format_info_block_width - width in pixels of block. * @info: pixel format info diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index fb8515b2860c..55b3f2f2e608 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -466,8 +466,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2]; priv->viu.vd1_stride2 = fb->pitches[2]; priv->viu.vd1_height2 = - drm_format_plane_height(fb->height, - fb->format->format, 2); + drm_format_info_plane_height(fb->format, + fb->height, 2); DRM_DEBUG("plane 2 addr 0x%x stride %d height %d\n", priv->viu.vd1_addr2, priv->viu.vd1_stride2, @@ -478,8 +478,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1]; priv->viu.vd1_stride1 = fb->pitches[1]; priv->viu.vd1_height1 = - drm_format_plane_height(fb->height, - fb->format->format, 1); + drm_format_info_plane_height(fb->format, + fb->height, 1); DRM_DEBUG("plane 1 addr 0x%x stride %d height %d\n", priv->viu.vd1_addr1, priv->viu.vd1_stride1, @@ -490,8 +490,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0]; priv->viu.vd1_stride0 = fb->pitches[0]; priv->viu.vd1_height0 = - drm_format_plane_height(fb->height, - fb->format->format, 0); + drm_format_info_plane_height(fb->format, + fb->height, 0); DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n", priv->viu.vd1_addr0, priv->viu.vd1_stride0, diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 6b5a82b31bc4..4ef8ccb5d236 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -277,6 +277,50 @@ int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane) return info->cpp[plane]; } +/** + * drm_format_info_plane_width - width of the plane given the first plane + * @format: pixel format info + * @width: width of the first plane + * @plane: plane index + * + * Returns: + * The width of @plane, given that the width of the first plane is @width. + */ +static inline +int drm_format_info_plane_width(const struct drm_format_info *info, int width, + int plane) +{ + if (!info || plane >= info->num_planes) + return 0; + + if (plane == 0) + return width; + + return width / info->hsub; +} + +/** + * drm_format_info_plane_height - height of the plane given the first plane + * @format: pixel format info + * @height: height of the first plane + * @plane: plane index + * + * Returns: + * The height of @plane, given that the height of the first plane is @height. + */ +static inline +int drm_format_info_plane_height(const struct drm_format_info *info, int height, + int plane) +{ + if (!info || plane >= info->num_planes) + return 0; + + if (plane == 0) + return height; + + return height / info->vsub; +} + const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); const struct drm_format_info * @@ -285,8 +329,6 @@ drm_get_format_info(struct drm_device *dev, uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth); -int drm_format_plane_width(int width, uint32_t format, int plane); -int drm_format_plane_height(int height, uint32_t format, int plane); unsigned int drm_format_info_block_width(const struct drm_format_info *info, int plane); unsigned int drm_format_info_block_height(const struct drm_format_info *info, -- cgit v1.3-6-gb490 From b0f986b4b025c8036ab2c660460621c1d17656b5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 16 May 2019 12:31:52 +0200 Subject: drm: Remove users of drm_format_info_plane_cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_format_info_plane_cpp() basically just returns the cpp array content found in the drm_format_info structure. Since it's pretty trivial, let's remove the function and have the users use the array directly Suggested-by: Ville Syrjälä Reviewed-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/c0a78c87cd0410a1819edad2794ad06543c85bb5.1558002671.git-series.maxime.ripard@bootlin.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +- drivers/gpu/drm/arm/malidp_hw.c | 2 +- drivers/gpu/drm/arm/malidp_planes.c | 2 +- drivers/gpu/drm/drm_client.c | 2 +- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/drm_format_helper.c | 4 ++-- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_fb.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +- drivers/gpu/drm/msm/msm_fb.c | 2 +- drivers/gpu/drm/radeon/radeon_fb.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +- drivers/gpu/drm/stm/ltdc.c | 2 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/zte/zx_plane.c | 2 +- include/drm/drm_fourcc.h | 17 ----------------- 17 files changed, 17 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 6edae6458be8..2e2869299a84 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -133,7 +133,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, u32 cpp; info = drm_get_format_info(adev->ddev, mode_cmd); - cpp = drm_format_info_plane_cpp(info, 0); + cpp = info->cpp[0]; /* need to align pitch with crtc limits */ mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp, diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 1c9e869f4c52..53391c0f87eb 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -383,7 +383,7 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * int malidp_format_get_bpp(u32 fmt) { const struct drm_format_info *info = drm_format_info(fmt); - int bpp = drm_format_info_plane_cpp(info, 0) * 8; + int bpp = info->cpp[0] * 8; if (bpp == 0) { switch (fmt) { diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 361c02988375..07ceb4ee14e3 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -227,7 +227,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, if (modifier & AFBC_SPLIT) { if (!info->is_yuv) { - if (drm_format_info_plane_cpp(info, 0) <= 2) { + if (info->cpp[0] <= 2) { DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n"); return false; } diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 169d8eeaa662..5abcd83da6a6 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -259,7 +259,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u dumb_args.width = width; dumb_args.height = height; - dumb_args.bpp = drm_format_info_plane_cpp(info, 0) * 8; + dumb_args.bpp = info->cpp[0] * 8; ret = drm_mode_create_dumb(dev, &dumb_args, client->file); if (ret) goto err_delete; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e2d9a6da14a5..302cf5f8bcce 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -813,7 +813,7 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper, struct drm_clip_rect *clip) { struct drm_framebuffer *fb = fb_helper->fb; - unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); + unsigned int cpp = fb->format->cpp[0]; size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp; void *src = fb_helper->fbdev->screen_buffer + offset; void *dst = fb_helper->buffer->vaddr + offset; diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 8ad66aa1362a..0897cb9aeaff 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -36,7 +36,7 @@ static unsigned int clip_offset(struct drm_rect *clip, void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { - unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); + unsigned int cpp = fb->format->cpp[0]; size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; @@ -63,7 +63,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { - unsigned int cpp = drm_format_info_plane_cpp(fb->format, 0); + unsigned int cpp = fb->format->cpp[0]; unsigned int offset = clip_offset(clip, fb->pitches[0], cpp); size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index e35601b1f878..c1647c0cc217 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -326,7 +326,7 @@ skl_plane_max_stride(struct intel_plane *plane, unsigned int rotation) { const struct drm_format_info *info = drm_format_info(pixel_format); - int cpp = drm_format_info_plane_cpp(info, 0); + int cpp = info->cpp[0]; /* * "The stride in bytes must not exceed the diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index 0d5334a5a9a7..b5e2f230da00 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -104,7 +104,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, if (!gem) return ERR_PTR(-ENOENT); - bpp = drm_format_info_plane_cpp(info, 0); + bpp = info->cpp[0]; size = (height - 1) * cmd->pitches[0] + width * bpp; size += cmd->offsets[0]; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 59b24e0c5070..c3751c95b452 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -801,7 +801,7 @@ static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) width = mdp5_crtc->cursor.width; height = mdp5_crtc->cursor.height; - stride = width * drm_format_info_plane_cpp(info, 0); + stride = width * info->cpp[0]; get_roi(crtc, &roi_w, &roi_h); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 1ca294694597..2834837f4d3e 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -158,7 +158,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, for (i = 0; i < nplanes; i++) { int n, fetch_stride, cpp; - cpp = drm_format_info_plane_cpp(info, i); + cpp = info->cpp[i]; fetch_stride = width * cpp / (i ? hsub : 1); n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size); diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 29e45f2144b5..68fa2c8f61e6 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -181,7 +181,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, unsigned int min_size; min_size = (height - 1) * mode_cmd->pitches[i] - + width * drm_format_info_plane_cpp(info, i) + + width * info->cpp[i] + mode_cmd->offsets[i]; if (bos[i]->size < min_size) { diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index dbf596fc4339..287e3f92102a 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -137,7 +137,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, u32 cpp; info = drm_get_format_info(rdev->ddev, mode_cmd); - cpp = drm_format_info_plane_cpp(info, 0); + cpp = info->cpp[0]; /* need to align pitch with crtc limits */ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 57873c99ae29..31030cf81bc9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -98,7 +98,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, min_size = (height - 1) * mode_cmd->pitches[i] + mode_cmd->offsets[i] + - width * drm_format_info_plane_cpp(info, i); + width * info->cpp[i]; if (obj->size < min_size) { drm_gem_object_put_unlocked(obj); diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index e7abe54b9746..14eb8c40953b 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -784,7 +784,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, /* Configures the color frame buffer pitch in bytes & line length */ pitch_in_bytes = fb->pitches[0]; - line_length = drm_format_info_plane_cpp(fb->format, 0) * + line_length = fb->format->cpp[0] * (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; val = ((pitch_in_bytes << 16) | line_length); reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index d1042196a30f..57cc26e1da01 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -149,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, goto unreference; } - bpp = drm_format_info_plane_cpp(info, i); + bpp = info->cpp[i]; size = (height - 1) * cmd->pitches[i] + width * bpp + cmd->offsets[i]; diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index d97a4dff515d..706452f9b276 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -222,7 +222,7 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, cma_obj = drm_fb_cma_get_gem_obj(fb, i); paddr = cma_obj->paddr + fb->offsets[i]; paddr += src_y * fb->pitches[i]; - paddr += src_x * drm_format_info_plane_cpp(fb->format, i); + paddr += src_x * fb->format->cpp[i]; zx_writel(paddr_reg, paddr); paddr_reg += 4; } diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 4ef8ccb5d236..405466692bd2 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -260,23 +260,6 @@ drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info) return info->is_yuv && info->hsub == 1 && info->vsub == 1; } -/** - * drm_format_info_plane_cpp - determine the bytes per pixel value - * @format: pixel format info - * @plane: plane index - * - * Returns: - * The bytes per pixel value for the specified plane. - */ -static inline -int drm_format_info_plane_cpp(const struct drm_format_info *info, int plane) -{ - if (!info || plane >= info->num_planes) - return 0; - - return info->cpp[plane]; -} - /** * drm_format_info_plane_width - width of the plane given the first plane * @format: pixel format info -- cgit v1.3-6-gb490 From 7793a108964924dd2802ee8c5dff2e9f3a9cd54a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 21 May 2019 13:09:06 +0200 Subject: drm/fourcc: Fix the parameters name in the documentation We introduced new functions in the commit bf39607c1614 ("drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height") based on previous ones but with a slightly different prototype. However, the documentation wasn't changed to reflect that change. Fixes: bf39607c1614 ("drm/fourcc: Pass the format_info pointer to drm_format_plane_width/height") Reported-by: kbuild test robot Reviewed-by: Daniel Vetter Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20190521110906.15268-1-maxime.ripard@bootlin.com --- include/drm/drm_fourcc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 405466692bd2..306d1efeb5e0 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -262,7 +262,7 @@ drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info) /** * drm_format_info_plane_width - width of the plane given the first plane - * @format: pixel format info + * @info: pixel format info * @width: width of the first plane * @plane: plane index * @@ -284,7 +284,7 @@ int drm_format_info_plane_width(const struct drm_format_info *info, int width, /** * drm_format_info_plane_height - height of the plane given the first plane - * @format: pixel format info + * @info: pixel format info * @height: height of the first plane * @plane: plane index * -- cgit v1.3-6-gb490 From 81da87f63a1edebcf8cbb811d387e353d9f89c7a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 21 May 2019 13:08:29 +0200 Subject: drm: Replace drm_gem_vram_push_to_system() with kunmap + unpin The push-to-system function forces a buffer out of video RAM. This decision should rather be made by the memory manager. By replacing the function with calls to the kunmap and unpin functions, the buffer's memory becomes available, but the buffer remains in VRAM until it's evicted by a pin operation. This patch replaces the remaining instances of drm_gem_vram_push_to_system() in ast and mgag200, and removes the function from DRM. Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20190521110831.20200-2-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/ast/ast_mode.c | 14 ++++++--- drivers/gpu/drm/drm_gem_vram_helper.c | 50 -------------------------------- drivers/gpu/drm/drm_vram_helper_common.c | 2 -- drivers/gpu/drm/mgag200/mgag200_mode.c | 15 ++++++---- include/drm/drm_gem_vram_helper.h | 1 - 5 files changed, 20 insertions(+), 62 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 9aca9135a5cc..fbafe3994654 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -521,7 +521,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) } } -/* ast is different - we will force move buffers out of VRAM */ static int ast_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic) @@ -534,12 +533,15 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, s64 gpu_addr; void *base; - /* push the previous fb to system ram */ if (!atomic && fb) { ast_fb = to_ast_framebuffer(fb); obj = ast_fb->obj; gbo = drm_gem_vram_of_gem(obj); - drm_gem_vram_push_to_system(gbo); + + /* unmap if console */ + if (&ast->fbdev->afb == ast_fb) + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); } ast_fb = to_ast_framebuffer(crtc->primary->fb); @@ -622,11 +624,15 @@ static void ast_crtc_disable(struct drm_crtc *crtc) DRM_DEBUG_KMS("\n"); ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (crtc->primary->fb) { + struct ast_private *ast = crtc->dev->dev_private; struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb); struct drm_gem_object *obj = ast_fb->obj; struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); - drm_gem_vram_push_to_system(gbo); + /* unmap if console */ + if (&ast->fbdev->afb == ast_fb) + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); } crtc->primary->fb = NULL; } diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index bde8237e8021..b341b70832be 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -379,56 +379,6 @@ int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo) } EXPORT_SYMBOL(drm_gem_vram_unpin_reserved); -/** - * drm_gem_vram_push_to_system() - \ - Unpins a GEM VRAM object and moves it to system memory - * @gbo: the GEM VRAM object - * - * This operation only works if the caller holds the final pin on the - * buffer object. - * - * Returns: - * 0 on success, or - * a negative error code otherwise. - */ -int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo) -{ - int i, ret; - struct ttm_operation_ctx ctx = { false, false }; - - ret = ttm_bo_reserve(&gbo->bo, true, false, NULL); - if (ret < 0) - return ret; - - if (WARN_ON_ONCE(!gbo->pin_count)) - goto out; - - --gbo->pin_count; - if (gbo->pin_count) - goto out; - - if (gbo->kmap.virtual) - ttm_bo_kunmap(&gbo->kmap); - - drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); - for (i = 0; i < gbo->placement.num_placement ; ++i) - gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); - if (ret) - goto err_ttm_bo_unreserve; - -out: - ttm_bo_unreserve(&gbo->bo); - - return 0; - -err_ttm_bo_unreserve: - ttm_bo_unreserve(&gbo->bo); - return ret; -} -EXPORT_SYMBOL(drm_gem_vram_push_to_system); - /** * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space * @gbo: the GEM VRAM object diff --git a/drivers/gpu/drm/drm_vram_helper_common.c b/drivers/gpu/drm/drm_vram_helper_common.c index 3b47f7002115..e9c9f9a80ba3 100644 --- a/drivers/gpu/drm/drm_vram_helper_common.c +++ b/drivers/gpu/drm/drm_vram_helper_common.c @@ -79,8 +79,6 @@ * RAM. Call drm_gem_vram_pin() with &DRM_GEM_VRAM_PL_FLAG_VRAM or * &DRM_GEM_VRAM_PL_FLAG_SYSTEM to pin a buffer object in video RAM or system * memory. Call drm_gem_vram_unpin() to release the pinned object afterwards. - * If you have to evict a buffer object from video RAM (e.g., for freeing up - * memory), unpin the buffer and call drm_gem_vram_push_to_system(). * * A buffer object that is pinned in video RAM has a fixed address within that * memory region. Call drm_gem_vram_offset() to retrieve this value. Typically diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index e79872c968bf..1c8e0bfac015 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -858,8 +858,6 @@ static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0); } - -/* ast is different - we will force move buffers out of VRAM */ static int mga_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic) @@ -872,12 +870,15 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, s64 gpu_addr; void *base; - /* push the previous fb to system ram */ if (!atomic && fb) { mga_fb = to_mga_framebuffer(fb); obj = mga_fb->obj; gbo = drm_gem_vram_of_gem(obj); - drm_gem_vram_push_to_system(gbo); + + /* unmap if console */ + if (&mdev->mfbdev->mfb == mga_fb) + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); } mga_fb = to_mga_framebuffer(crtc->primary->fb); @@ -1425,11 +1426,15 @@ static void mga_crtc_disable(struct drm_crtc *crtc) DRM_DEBUG_KMS("\n"); mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (crtc->primary->fb) { + struct mga_device *mdev = crtc->dev->dev_private; struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb); struct drm_gem_object *obj = mga_fb->obj; struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); - drm_gem_vram_push_to_system(gbo); + /* unmap if console */ + if (&mdev->mfbdev->mfb == mga_fb) + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); } crtc->primary->fb = NULL; } diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index ff1a81761543..22e52d7dfbb7 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -86,7 +86,6 @@ int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, unsigned long pl_flag); int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo); -int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo); void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, bool *is_iomem, struct ttm_bo_kmap_obj *kmap); void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, -- cgit v1.3-6-gb490 From cb1f8814bbfcc2d0d7c499530e3d878ba04e4af2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 21 May 2019 13:08:30 +0200 Subject: drm: Rename reserve/unreserve to lock/unlock in GEM VRAM helpers To align with the rest of DRM terminology, the GEM VRAM helpers now use lock and unlock in places where reserve and unreserve where used before. All callers have been adapted. Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20190521110831.20200-3-tzimmermann@suse.de Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/ast/ast_fb.c | 11 ++++----- drivers/gpu/drm/ast/ast_mode.c | 12 +++++----- drivers/gpu/drm/drm_gem_vram_helper.c | 32 ++++++++++++------------- drivers/gpu/drm/mgag200/mgag200_cursor.c | 40 ++++++++++++++++---------------- drivers/gpu/drm/mgag200/mgag200_fb.c | 11 ++++----- include/drm/drm_gem_vram_helper.h | 8 +++---- 6 files changed, 56 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 505e602855c0..05f45222b702 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -62,13 +62,12 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, obj = afbdev->afb.obj; gbo = drm_gem_vram_of_gem(obj); - /* - * try and reserve the BO, if we fail with busy - * then the BO is being moved and we should - * store up the damage until later. + /* Try to lock the BO. If we fail with -EBUSY then + * the BO is being moved and we should store up the + * damage until later. */ if (drm_can_sleep()) - ret = drm_gem_vram_reserve(gbo, true); + ret = drm_gem_vram_lock(gbo, true); if (ret) { if (ret != -EBUSY) return; @@ -127,7 +126,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, drm_gem_vram_kunmap(gbo); out: - drm_gem_vram_unreserve(gbo); + drm_gem_vram_unlock(gbo); } static void ast_fillrect(struct fb_info *info, diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fbafe3994654..fb700d620b64 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1201,7 +1201,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, } gbo = drm_gem_vram_of_gem(obj); - ret = drm_gem_vram_reserve(gbo, false); + ret = drm_gem_vram_lock(gbo, false); if (ret) goto fail; @@ -1209,7 +1209,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, src = drm_gem_vram_kmap_at(gbo, true, &src_isiomem, &uobj_map); if (IS_ERR(src)) { ret = PTR_ERR(src); - goto fail_unreserve; + goto fail_unlock; } if (src_isiomem == true) DRM_ERROR("src cursor bo should be in main memory\n"); @@ -1218,7 +1218,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, false, &dst_isiomem, &ast->cache_kmap); if (IS_ERR(dst)) { ret = PTR_ERR(dst); - goto fail_unreserve; + goto fail_unlock; } if (dst_isiomem == false) DRM_ERROR("dst bo should be in VRAM\n"); @@ -1229,7 +1229,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, csum = copy_cursor_image(src, dst, width, height); drm_gem_vram_kunmap_at(gbo, &uobj_map); - drm_gem_vram_unreserve(gbo); + drm_gem_vram_unlock(gbo); /* write checksum + signature */ { @@ -1262,8 +1262,8 @@ static int ast_cursor_set(struct drm_crtc *crtc, drm_gem_object_put_unlocked(obj); return 0; -fail_unreserve: - drm_gem_vram_unreserve(gbo); +fail_unlock: + drm_gem_vram_unlock(gbo); fail: drm_gem_object_put_unlocked(obj); return ret; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index b341b70832be..aefb0c361486 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -152,7 +152,7 @@ void drm_gem_vram_put(struct drm_gem_vram_object *gbo) EXPORT_SYMBOL(drm_gem_vram_put); /** - * drm_gem_vram_reserve() - Reserves a VRAM-backed GEM object + * drm_gem_vram_lock() - Locks a VRAM-backed GEM object * @gbo: the GEM VRAM object * @no_wait: don't wait for buffer object to become available * @@ -162,24 +162,24 @@ EXPORT_SYMBOL(drm_gem_vram_put); * 0 on success, or * a negative error code otherwise */ -int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait) +int drm_gem_vram_lock(struct drm_gem_vram_object *gbo, bool no_wait) { return ttm_bo_reserve(&gbo->bo, true, no_wait, NULL); } -EXPORT_SYMBOL(drm_gem_vram_reserve); +EXPORT_SYMBOL(drm_gem_vram_lock); /** - * drm_gem_vram_unreserve() - \ - Release a reservation acquired by drm_gem_vram_reserve() + * drm_gem_vram_unlock() - \ + Release a reservation acquired by drm_gem_vram_lock() * @gbo: the GEM VRAM object * * See ttm_bo_unreserve() for more information. */ -void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo) +void drm_gem_vram_unlock(struct drm_gem_vram_object *gbo) { ttm_bo_unreserve(&gbo->bo); } -EXPORT_SYMBOL(drm_gem_vram_unreserve); +EXPORT_SYMBOL(drm_gem_vram_unlock); /** * drm_gem_vram_mmap_offset() - Returns a GEM VRAM object's mmap offset @@ -263,7 +263,7 @@ err_ttm_bo_unreserve: EXPORT_SYMBOL(drm_gem_vram_pin); /** - * drm_gem_vram_pin_reserved() - Pins a GEM VRAM object in a region. + * drm_gem_vram_pin_locked() - Pins a GEM VRAM object in a region. * @gbo: the GEM VRAM object * @pl_flag: a bitmask of possible memory regions * @@ -272,14 +272,14 @@ EXPORT_SYMBOL(drm_gem_vram_pin); * it can be pinned to another region. * * This function pins a GEM VRAM object that has already been - * reserved. Use drm_gem_vram_pin() if possible. + * locked. Use drm_gem_vram_pin() if possible. * * Returns: * 0 on success, or * a negative error code otherwise. */ -int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, - unsigned long pl_flag) +int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo, + unsigned long pl_flag) { int i, ret; struct ttm_operation_ctx ctx = { false, false }; @@ -301,7 +301,7 @@ int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, return 0; } -EXPORT_SYMBOL(drm_gem_vram_pin_reserved); +EXPORT_SYMBOL(drm_gem_vram_pin_locked); /** * drm_gem_vram_unpin() - Unpins a GEM VRAM object @@ -346,17 +346,17 @@ err_ttm_bo_unreserve: EXPORT_SYMBOL(drm_gem_vram_unpin); /** - * drm_gem_vram_unpin_reserved() - Unpins a GEM VRAM object + * drm_gem_vram_unpin_locked() - Unpins a GEM VRAM object * @gbo: the GEM VRAM object * * This function unpins a GEM VRAM object that has already been - * reserved. Use drm_gem_vram_unpin() if possible. + * locked. Use drm_gem_vram_unpin() if possible. * * Returns: * 0 on success, or * a negative error code otherwise. */ -int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo) +int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo) { int i, ret; struct ttm_operation_ctx ctx = { false, false }; @@ -377,7 +377,7 @@ int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo) return 0; } -EXPORT_SYMBOL(drm_gem_vram_unpin_reserved); +EXPORT_SYMBOL(drm_gem_vram_unpin_locked); /** * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index 1c4fc85315a0..06a8c076cb33 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -23,9 +23,9 @@ static void mga_hide_cursor(struct mga_device *mdev) WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); if (mdev->cursor.pixels_1->pin_count) - drm_gem_vram_unpin_reserved(mdev->cursor.pixels_1); + drm_gem_vram_unpin_locked(mdev->cursor.pixels_1); if (mdev->cursor.pixels_2->pin_count) - drm_gem_vram_unpin_reserved(mdev->cursor.pixels_2); + drm_gem_vram_unpin_locked(mdev->cursor.pixels_2); } int mga_crtc_cursor_set(struct drm_crtc *crtc, @@ -80,53 +80,53 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, if (!obj) return -ENOENT; - ret = drm_gem_vram_reserve(pixels_1, true); + ret = drm_gem_vram_lock(pixels_1, true); if (ret) { WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); goto out_unref; } - ret = drm_gem_vram_reserve(pixels_2, true); + ret = drm_gem_vram_lock(pixels_2, true); if (ret) { WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); - drm_gem_vram_unreserve(pixels_1); - goto out_unreserve1; + drm_gem_vram_unlock(pixels_1); + goto out_unlock1; } /* Move cursor buffers into VRAM if they aren't already */ if (!pixels_1->pin_count) { - ret = drm_gem_vram_pin_reserved(pixels_1, - DRM_GEM_VRAM_PL_FLAG_VRAM); + ret = drm_gem_vram_pin_locked(pixels_1, + DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) goto out1; gpu_addr = drm_gem_vram_offset(pixels_1); if (gpu_addr < 0) { - drm_gem_vram_unpin_reserved(pixels_1); + drm_gem_vram_unpin_locked(pixels_1); goto out1; } mdev->cursor.pixels_1_gpu_addr = gpu_addr; } if (!pixels_2->pin_count) { - ret = drm_gem_vram_pin_reserved(pixels_2, - DRM_GEM_VRAM_PL_FLAG_VRAM); + ret = drm_gem_vram_pin_locked(pixels_2, + DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) { - drm_gem_vram_unpin_reserved(pixels_1); + drm_gem_vram_unpin_locked(pixels_1); goto out1; } gpu_addr = drm_gem_vram_offset(pixels_2); if (gpu_addr < 0) { - drm_gem_vram_unpin_reserved(pixels_1); - drm_gem_vram_unpin_reserved(pixels_2); + drm_gem_vram_unpin_locked(pixels_1); + drm_gem_vram_unpin_locked(pixels_2); goto out1; } mdev->cursor.pixels_2_gpu_addr = gpu_addr; } gbo = drm_gem_vram_of_gem(obj); - ret = drm_gem_vram_reserve(gbo, true); + ret = drm_gem_vram_lock(gbo, true); if (ret) { - dev_err(&dev->pdev->dev, "failed to reserve user bo\n"); + dev_err(&dev->pdev->dev, "failed to lock user bo\n"); goto out1; } src = drm_gem_vram_kmap(gbo, true, NULL); @@ -250,13 +250,13 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, out3: drm_gem_vram_kunmap(gbo); out2: - drm_gem_vram_unreserve(gbo); + drm_gem_vram_unlock(gbo); out1: if (ret) mga_hide_cursor(mdev); - drm_gem_vram_unreserve(pixels_1); -out_unreserve1: - drm_gem_vram_unreserve(pixels_2); + drm_gem_vram_unlock(pixels_1); +out_unlock1: + drm_gem_vram_unlock(pixels_2); out_unref: drm_gem_object_put_unlocked(obj); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 87217bdce9f8..97c575a9a86f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -36,13 +36,12 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, obj = mfbdev->mfb.obj; gbo = drm_gem_vram_of_gem(obj); - /* - * try and reserve the BO, if we fail with busy - * then the BO is being moved and we should - * store up the damage until later. + /* Try to lock the BO. If we fail with -EBUSY then + * the BO is being moved and we should store up the + * damage until later. */ if (drm_can_sleep()) - ret = drm_gem_vram_reserve(gbo, true); + ret = drm_gem_vram_lock(gbo, true); if (ret) { if (ret != -EBUSY) return; @@ -101,7 +100,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, drm_gem_vram_kunmap(gbo); out: - drm_gem_vram_unreserve(gbo); + drm_gem_vram_unlock(gbo); } static void mga_fillrect(struct fb_info *info, diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 22e52d7dfbb7..4d1d2c1bf32b 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -77,15 +77,15 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, unsigned long pg_align, bool interruptible); void drm_gem_vram_put(struct drm_gem_vram_object *gbo); -int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait); -void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo); +int drm_gem_vram_lock(struct drm_gem_vram_object *gbo, bool no_wait); +void drm_gem_vram_unlock(struct drm_gem_vram_object *gbo); u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); -int drm_gem_vram_pin_reserved(struct drm_gem_vram_object *gbo, +int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo, unsigned long pl_flag); int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); -int drm_gem_vram_unpin_reserved(struct drm_gem_vram_object *gbo); +int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo); void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, bool *is_iomem, struct ttm_bo_kmap_obj *kmap); void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, -- cgit v1.3-6-gb490 From d825c565304f33d5f717a35f74d5109ff4820cae Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 19 May 2019 21:55:22 +0200 Subject: drm/gma500: remove empty gma_drm.h header file The header file gma_drm.h is empty so remove it and drop all uses of the file. Signed-off-by: Sam Ravnborg Cc: Patrik Jakobsson Cc: David Airlie Cc: Daniel Vetter Acked-by: Daniel Vetter Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20190519195526.3422-2-sam@ravnborg.org --- drivers/gpu/drm/gma500/cdv_device.c | 2 +- drivers/gpu/drm/gma500/gem.c | 2 +- drivers/gpu/drm/gma500/intel_bios.c | 2 +- drivers/gpu/drm/gma500/intel_gmbus.c | 2 +- drivers/gpu/drm/gma500/mid_bios.c | 2 +- drivers/gpu/drm/gma500/oaktrail_device.c | 2 +- drivers/gpu/drm/gma500/psb_device.c | 2 +- drivers/gpu/drm/gma500/psb_drv.h | 2 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2 +- include/drm/gma_drm.h | 25 ------------------------- 10 files changed, 9 insertions(+), 34 deletions(-) delete mode 100644 include/drm/gma_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 34b85767e4da..6ba605ac7123 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -20,7 +20,7 @@ #include #include #include -#include + #include "psb_drv.h" #include "psb_reg.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 576f1b272f23..cfc5b559c77b 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -25,8 +25,8 @@ #include #include -#include #include + #include "psb_drv.h" void psb_gem_free_object(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 63bde4e86c6a..45c17c6f58f8 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -20,7 +20,7 @@ */ #include #include -#include + #include "psb_drv.h" #include "psb_intel_drv.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c index e7e22187c539..b1bf314ab150 100644 --- a/drivers/gpu/drm/gma500/intel_gmbus.c +++ b/drivers/gpu/drm/gma500/intel_gmbus.c @@ -30,8 +30,8 @@ #include #include #include + #include "psb_intel_drv.h" -#include #include "psb_drv.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index 237041a37532..e00778b002ec 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -25,7 +25,7 @@ #include #include -#include + #include "psb_drv.h" #include "mid_bios.h" diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index ba30b43a3412..f0872e2c22d5 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -22,7 +22,7 @@ #include #include #include -#include + #include "psb_drv.h" #include "psb_reg.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index dc0f8527570c..9fd418985d70 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -20,7 +20,7 @@ #include #include #include -#include + #include "psb_drv.h" #include "psb_reg.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 941b238bdcc9..fbccf2abdad7 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -24,7 +24,7 @@ #include #include -#include + #include "psb_reg.h" #include "psb_intel_drv.h" #include "gma_display.h" diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index dd3cec0e3190..5090ef5f348d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -32,8 +32,8 @@ #include #include #include + #include "psb_intel_drv.h" -#include #include "psb_drv.h" #include "psb_intel_sdvo_regs.h" #include "psb_intel_reg.h" diff --git a/include/drm/gma_drm.h b/include/drm/gma_drm.h deleted file mode 100644 index 87ac5e6ca551..000000000000 --- a/include/drm/gma_drm.h +++ /dev/null @@ -1,25 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#ifndef _GMA_DRM_H_ -#define _GMA_DRM_H_ - -#endif -- cgit v1.3-6-gb490 From f13e143e7444bffc53f5c2904aeed76646da69d6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 3 Jul 2018 16:42:26 +0200 Subject: dma-buf: start caching of sg_table objects v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To allow a smooth transition from pinning buffer objects to dynamic invalidation we first start to cache the sg_table for an attachment. v2: keep closer to the DRM implementation Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.kernel.org/patch/10943053/ --- drivers/dma-buf/dma-buf.c | 27 +++++++++++++++++++++++++-- include/linux/dma-buf.h | 13 +++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 3ae6c0c2cc02..f4104a21b069 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -576,6 +576,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, list_add(&attach->node, &dmabuf->attachments); mutex_unlock(&dmabuf->lock); + return attach; err_attach: @@ -598,6 +599,9 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) if (WARN_ON(!dmabuf || !attach)) return; + if (attach->sgt) + dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir); + mutex_lock(&dmabuf->lock); list_del(&attach->node); if (dmabuf->ops->detach) @@ -633,10 +637,27 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, if (WARN_ON(!attach || !attach->dmabuf)) return ERR_PTR(-EINVAL); + if (attach->sgt) { + /* + * Two mappings with different directions for the same + * attachment are not allowed. + */ + if (attach->dir != direction && + attach->dir != DMA_BIDIRECTIONAL) + return ERR_PTR(-EBUSY); + + return attach->sgt; + } + sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); if (!sg_table) sg_table = ERR_PTR(-ENOMEM); + if (!IS_ERR(sg_table) && attach->dmabuf->ops->cache_sgt_mapping) { + attach->sgt = sg_table; + attach->dir = direction; + } + return sg_table; } EXPORT_SYMBOL_GPL(dma_buf_map_attachment); @@ -660,8 +681,10 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, if (WARN_ON(!attach || !attach->dmabuf || !sg_table)) return; - attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, - direction); + if (attach->sgt == sg_table) + return; + + attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction); } EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index a0bd071466fc..8a327566d7f4 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -44,6 +44,15 @@ struct dma_buf_attachment; * @vunmap: [optional] unmaps a vmap from the buffer */ struct dma_buf_ops { + /** + * @cache_sgt_mapping: + * + * If true the framework will cache the first mapping made for each + * attachment. This avoids creating mappings for attachments multiple + * times. + */ + bool cache_sgt_mapping; + /** * @attach: * @@ -323,6 +332,8 @@ struct dma_buf { * @dmabuf: buffer for this attachment. * @dev: device attached to the buffer. * @node: list of dma_buf_attachment. + * @sgt: cached mapping. + * @dir: direction of cached mapping. * @priv: exporter specific attachment data. * * This structure holds the attachment information between the dma_buf buffer @@ -338,6 +349,8 @@ struct dma_buf_attachment { struct dma_buf *dmabuf; struct device *dev; struct list_head node; + struct sg_table *sgt; + enum dma_data_direction dir; void *priv; }; -- cgit v1.3-6-gb490 From fbb5d0353c62d10c3699ec844d2d015a762952d7 Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Thu, 16 May 2019 19:40:06 +0530 Subject: drm: Add HDR source metadata property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a blob property to get HDR metadata information from userspace. This will be send as part of AVI Infoframe to panel. It also implements get() and set() functions for HDR output metadata property.The blob data is received from userspace and saved in connector state, the same is returned as blob in get property call to userspace. v2: Rebase and modified the metadata structure elements as per Ville's POC changes. v3: No Change v4: Addressed Shashank's review comments v5: Rebase. v6: Addressed Brian Starkey's review comments, defined new structure with header for dynamic metadata scalability. Merge get/set property functions for metadata in this patch. v7: Addressed Jonas Karlman review comments and defined separate structure for infoframe to better align with CTA 861.G spec. Added Shashank's RB. v8: Addressed Ville's review comments. Moved sink metadata structure out of uapi headers as suggested by Jonas Karlman. v9: Rebase and addressed Jonas Karlman review comments. v10: Addressed Ville's review comments, dropped the metdata_changed state variable as its not needed anymore. Signed-off-by: Uma Shankar Reviewed-by: Shashank Sharma Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/1558015817-12025-2-git-send-email-uma.shankar@intel.com --- drivers/gpu/drm/drm_atomic_uapi.c | 12 ++++++++++++ drivers/gpu/drm/drm_connector.c | 6 ++++++ include/drm/drm_connector.h | 10 ++++++++++ include/drm/drm_mode_config.h | 7 +++++++ include/linux/hdmi.h | 26 ++++++++++++++++++++++++++ include/uapi/drm/drm_mode.h | 23 +++++++++++++++++++++++ 6 files changed, 84 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 428d82662dc4..125605ff45af 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -676,6 +676,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, { struct drm_device *dev = connector->dev; struct drm_mode_config *config = &dev->mode_config; + bool replaced = false; + int ret; if (property == config->prop_crtc_id) { struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val); @@ -726,6 +728,13 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, */ if (state->link_status != DRM_LINK_STATUS_GOOD) state->link_status = val; + } else if (property == config->hdr_output_metadata_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + &state->hdr_output_metadata, + val, + sizeof(struct hdr_output_metadata), -1, + &replaced); + return ret; } else if (property == config->aspect_ratio_property) { state->picture_aspect_ratio = val; } else if (property == config->content_type_property) { @@ -814,6 +823,9 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->colorspace; } else if (property == connector->scaling_mode_property) { *val = state->scaling_mode; + } else if (property == config->hdr_output_metadata_property) { + *val = state->hdr_output_metadata ? + state->hdr_output_metadata->base.id : 0; } else if (property == connector->content_protection_property) { *val = state->content_protection; } else if (property == config->writeback_fb_id_property) { diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b34c3d38bf15..365ace0c0c9e 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1058,6 +1058,12 @@ int drm_connector_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.non_desktop_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "HDR_OUTPUT_METADATA", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.hdr_output_metadata_property = prop; + return 0; } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index f43f40d5888a..f0e987df4c1e 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -603,6 +603,12 @@ struct drm_connector_state { * and the connector bpc limitations obtained from edid. */ u8 max_bpc; + + /** + * @hdr_output_metadata: + * DRM blob property for HDR output metadata + */ + struct drm_property_blob *hdr_output_metadata; }; /** @@ -1243,6 +1249,10 @@ struct drm_connector { * &drm_mode_config.connector_free_work. */ struct llist_node free_node; + + /* HDR metdata */ + struct hdr_output_metadata hdr_output_metadata; + struct hdr_sink_metadata hdr_sink_metadata; }; #define obj_to_connector(x) container_of(x, struct drm_connector, base) diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 7f60e8eb269a..c031b5a9d8d1 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -836,6 +836,13 @@ struct drm_mode_config { */ struct drm_property *writeback_out_fence_ptr_property; + /** + * hdr_output_metadata_property: Connector property containing hdr + * metatda. This will be provided by userspace compositors based + * on HDR content + */ + struct drm_property *hdr_output_metadata_property; + /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 927ad6451105..6780476dcbff 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -152,6 +152,16 @@ enum hdmi_content_type { HDMI_CONTENT_TYPE_GAME, }; +enum hdmi_metadata_type { + HDMI_STATIC_METADATA_TYPE1 = 1, +}; + +enum hdmi_eotf { + HDMI_EOTF_TRADITIONAL_GAMMA_SDR, + HDMI_EOTF_TRADITIONAL_GAMMA_HDR, + HDMI_EOTF_SMPTE_ST2084, +}; + struct hdmi_avi_infoframe { enum hdmi_infoframe_type type; unsigned char version; @@ -320,6 +330,22 @@ struct hdmi_vendor_infoframe { unsigned int s3d_ext_data; }; +/* HDR Metadata as per 861.G spec */ +struct hdr_static_metadata { + __u8 eotf; + __u8 metadata_type; + __u16 max_cll; + __u16 max_fall; + __u16 min_cll; +}; + +struct hdr_sink_metadata { + __u32 metadata_type; + union { + struct hdr_static_metadata hdmi_type1; + }; +}; + int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, void *buffer, size_t size); diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 83cd1636b9be..997a7e05c0c6 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -630,6 +630,29 @@ struct drm_color_lut { __u16 reserved; }; +/* HDR Metadata Infoframe as per 861.G spec */ +struct hdr_metadata_infoframe { + __u8 eotf; + __u8 metadata_type; + struct { + __u16 x, y; + } display_primaries[3]; + struct { + __u16 x, y; + } white_point; + __u16 max_display_mastering_luminance; + __u16 min_display_mastering_luminance; + __u16 max_cll; + __u16 max_fall; +}; + +struct hdr_output_metadata { + __u32 metadata_type; + union { + struct hdr_metadata_infoframe hdmi_metadata_type1; + }; +}; + #define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 -- cgit v1.3-6-gb490 From 2cdbfd66a82969770ce1a7032fb1e2155a08cee8 Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Thu, 16 May 2019 19:40:09 +0530 Subject: drm: Enable HDR infoframe support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable Dynamic Range and Mastering Infoframe for HDR content, which is defined in CEA 861.3 spec. The metadata will be computed based on blending policy in userspace compositors and passed as a connector property blob to driver. The same will be sent as infoframe to panel which support HDR. Added the const version of infoframe for DRM metadata for HDR. v2: Rebase and added Ville's POC changes. v3: No Change v4: Addressed Shashank's review comments and merged the patch making drm infoframe function arguments as constant. v5: Rebase v6: Fixed checkpatch warnings with --strict option. Addressed Shashank's review comments and added his RB. v7: Addressed Brian Starkey's review comments. Merged 2 patches into one. v8: Addressed Jonas Karlman review comments. v9: Addressed Jonas Karlman review comments. v10: Addressed Ville's review comments. v11: Added BUILD_BUG_ON and sizeof instead of magic numbers as per Ville's comments. Signed-off-by: Uma Shankar Reviewed-by: Shashank Sharma Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/1558015817-12025-5-git-send-email-uma.shankar@intel.com --- drivers/gpu/drm/drm_edid.c | 72 +++++++++++++++++ drivers/video/hdmi.c | 190 +++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_edid.h | 5 ++ include/linux/hdmi.h | 28 +++++++ 4 files changed, 295 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a5ef9f45fee0..73560c9437cd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4904,6 +4904,78 @@ static bool is_hdmi2_sink(struct drm_connector *connector) connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420; } +static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf) +{ + return sink_eotf & BIT(output_eotf); +} + +/** + * drm_hdmi_infoframe_set_hdr_metadata() - fill an HDMI DRM infoframe with + * HDR metadata from userspace + * @frame: HDMI DRM infoframe + * @hdr_metadata: hdr_source_metadata info from userspace + * + * Return: 0 on success or a negative error code on failure. + */ +int +drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + const struct drm_connector_state *conn_state) +{ + struct drm_connector *connector; + struct hdr_output_metadata *hdr_metadata; + int err; + + if (!frame || !conn_state) + return -EINVAL; + + connector = conn_state->connector; + + if (!conn_state->hdr_output_metadata) + return -EINVAL; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + if (!hdr_metadata || !connector) + return -EINVAL; + + /* Sink EOTF is Bit map while infoframe is absolute values */ + if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf, + connector->hdr_sink_metadata.hdmi_type1.eotf)) { + DRM_DEBUG_KMS("EOTF Not Supported\n"); + return -EINVAL; + } + + err = hdmi_drm_infoframe_init(frame); + if (err < 0) + return err; + + frame->eotf = hdr_metadata->hdmi_metadata_type1.eotf; + frame->metadata_type = hdr_metadata->hdmi_metadata_type1.metadata_type; + + BUILD_BUG_ON(sizeof(frame->display_primaries) != + sizeof(hdr_metadata->hdmi_metadata_type1.display_primaries)); + BUILD_BUG_ON(sizeof(frame->white_point) != + sizeof(hdr_metadata->hdmi_metadata_type1.white_point)); + + memcpy(&frame->display_primaries, + &hdr_metadata->hdmi_metadata_type1.display_primaries, + sizeof(frame->display_primaries)); + + memcpy(&frame->white_point, + &hdr_metadata->hdmi_metadata_type1.white_point, + sizeof(frame->white_point)); + + frame->max_display_mastering_luminance = + hdr_metadata->hdmi_metadata_type1.max_display_mastering_luminance; + frame->min_display_mastering_luminance = + hdr_metadata->hdmi_metadata_type1.min_display_mastering_luminance; + frame->max_fall = hdr_metadata->hdmi_metadata_type1.max_fall; + frame->max_cll = hdr_metadata->hdmi_metadata_type1.max_cll; + + return 0; +} +EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata); + /** * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with * data from a DRM display mode diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 799ae49774f5..481f0367dfd3 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -650,6 +650,150 @@ hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *fram return 0; } +/** + * hdmi_drm_infoframe_init() - initialize an HDMI Dynaminc Range and + * mastering infoframe + * @frame: HDMI DRM infoframe + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_DRM; + frame->version = 1; + frame->length = HDMI_DRM_INFOFRAME_SIZE; + + return 0; +} +EXPORT_SYMBOL(hdmi_drm_infoframe_init); + +static int hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe *frame) +{ + if (frame->type != HDMI_INFOFRAME_TYPE_DRM || + frame->version != 1) + return -EINVAL; + + if (frame->length != HDMI_DRM_INFOFRAME_SIZE) + return -EINVAL; + + return 0; +} + +/** + * hdmi_drm_infoframe_check() - check a HDMI DRM infoframe + * @frame: HDMI DRM infoframe + * + * Validates that the infoframe is consistent. + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame) +{ + return hdmi_drm_infoframe_check_only(frame); +} +EXPORT_SYMBOL(hdmi_drm_infoframe_check); + +/** + * hdmi_drm_infoframe_pack_only() - write HDMI DRM infoframe to binary buffer + * @frame: HDMI DRM infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, + void *buffer, size_t size) +{ + u8 *ptr = buffer; + size_t length; + int i; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* start infoframe payload */ + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + *ptr++ = frame->eotf; + *ptr++ = frame->metadata_type; + + for (i = 0; i < 3; i++) { + *ptr++ = frame->display_primaries[i].x; + *ptr++ = frame->display_primaries[i].x >> 8; + *ptr++ = frame->display_primaries[i].y; + *ptr++ = frame->display_primaries[i].y >> 8; + } + + *ptr++ = frame->white_point.x; + *ptr++ = frame->white_point.x >> 8; + + *ptr++ = frame->white_point.y; + *ptr++ = frame->white_point.y >> 8; + + *ptr++ = frame->max_display_mastering_luminance; + *ptr++ = frame->max_display_mastering_luminance >> 8; + + *ptr++ = frame->min_display_mastering_luminance; + *ptr++ = frame->min_display_mastering_luminance >> 8; + + *ptr++ = frame->max_cll; + *ptr++ = frame->max_cll >> 8; + + *ptr++ = frame->max_fall; + *ptr++ = frame->max_fall >> 8; + + hdmi_infoframe_set_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_drm_infoframe_pack_only); + +/** + * hdmi_drm_infoframe_pack() - check a HDMI DRM infoframe, + * and write it to binary buffer + * @frame: HDMI DRM infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Validates that the infoframe is consistent and updates derived fields + * (eg. length) based on other fields, after which it packs the information + * contained in the @frame structure into a binary representation that + * can be written into the corresponding controller registers. This function + * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, + void *buffer, size_t size) +{ + int ret; + + ret = hdmi_drm_infoframe_check(frame); + if (ret) + return ret; + + return hdmi_drm_infoframe_pack_only(frame, buffer, size); +} +EXPORT_SYMBOL(hdmi_drm_infoframe_pack); + /* * hdmi_vendor_any_infoframe_check() - check a vendor infoframe */ @@ -758,6 +902,10 @@ hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t length = hdmi_avi_infoframe_pack_only(&frame->avi, buffer, size); break; + case HDMI_INFOFRAME_TYPE_DRM: + length = hdmi_drm_infoframe_pack_only(&frame->drm, + buffer, size); + break; case HDMI_INFOFRAME_TYPE_SPD: length = hdmi_spd_infoframe_pack_only(&frame->spd, buffer, size); @@ -806,6 +954,9 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, case HDMI_INFOFRAME_TYPE_AVI: length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size); break; + case HDMI_INFOFRAME_TYPE_DRM: + length = hdmi_drm_infoframe_pack(&frame->drm, buffer, size); + break; case HDMI_INFOFRAME_TYPE_SPD: length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size); break; @@ -838,6 +989,8 @@ static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type) return "Source Product Description (SPD)"; case HDMI_INFOFRAME_TYPE_AUDIO: return "Audio"; + case HDMI_INFOFRAME_TYPE_DRM: + return "Dynamic Range and Mastering"; } return "Reserved"; } @@ -1284,6 +1437,40 @@ static void hdmi_audio_infoframe_log(const char *level, frame->downmix_inhibit ? "Yes" : "No"); } +/** + * hdmi_drm_infoframe_log() - log info of HDMI DRM infoframe + * @level: logging level + * @dev: device + * @frame: HDMI DRM infoframe + */ +static void hdmi_drm_infoframe_log(const char *level, + struct device *dev, + const struct hdmi_drm_infoframe *frame) +{ + int i; + + hdmi_infoframe_log_header(level, dev, + (struct hdmi_any_infoframe *)frame); + hdmi_log("length: %d\n", frame->length); + hdmi_log("metadata type: %d\n", frame->metadata_type); + hdmi_log("eotf: %d\n", frame->eotf); + for (i = 0; i < 3; i++) { + hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x); + hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y); + } + + hdmi_log("white point x: %d\n", frame->white_point.x); + hdmi_log("white point y: %d\n", frame->white_point.y); + + hdmi_log("max_display_mastering_luminance: %d\n", + frame->max_display_mastering_luminance); + hdmi_log("min_display_mastering_luminance: %d\n", + frame->min_display_mastering_luminance); + + hdmi_log("max_cll: %d\n", frame->max_cll); + hdmi_log("max_fall: %d\n", frame->max_fall); +} + static const char * hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct) { @@ -1372,6 +1559,9 @@ void hdmi_infoframe_log(const char *level, case HDMI_INFOFRAME_TYPE_VENDOR: hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor); break; + case HDMI_INFOFRAME_TYPE_DRM: + hdmi_drm_infoframe_log(level, dev, &frame->drm); + break; } } EXPORT_SYMBOL(hdmi_infoframe_log); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 9d3b5b93102c..0e21e91c4314 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -25,6 +25,7 @@ #include #include +#include struct drm_device; struct i2c_adapter; @@ -370,6 +371,10 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, const struct drm_display_mode *mode, enum hdmi_quantization_range rgb_quant_range); +int +drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + const struct drm_connector_state *conn_state); + /** * drm_eld_mnl - Get ELD monitor name length in bytes. * @eld: pointer to an eld memory structure with mnl set diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 6780476dcbff..bcf3c6c3499e 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -47,6 +47,7 @@ enum hdmi_infoframe_type { HDMI_INFOFRAME_TYPE_AVI = 0x82, HDMI_INFOFRAME_TYPE_SPD = 0x83, HDMI_INFOFRAME_TYPE_AUDIO = 0x84, + HDMI_INFOFRAME_TYPE_DRM = 0x87, }; #define HDMI_IEEE_OUI 0x000c03 @@ -55,6 +56,7 @@ enum hdmi_infoframe_type { #define HDMI_AVI_INFOFRAME_SIZE 13 #define HDMI_SPD_INFOFRAME_SIZE 25 #define HDMI_AUDIO_INFOFRAME_SIZE 10 +#define HDMI_DRM_INFOFRAME_SIZE 26 #define HDMI_INFOFRAME_SIZE(type) \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) @@ -185,12 +187,37 @@ struct hdmi_avi_infoframe { unsigned short right_bar; }; +/* DRM Infoframe as per CTA 861.G spec */ +struct hdmi_drm_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + enum hdmi_eotf eotf; + enum hdmi_metadata_type metadata_type; + struct { + u16 x, y; + } display_primaries[3]; + struct { + u16 x, y; + } white_point; + u16 max_display_mastering_luminance; + u16 min_display_mastering_luminance; + u16 max_cll; + u16 max_fall; +}; + int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, size_t size); ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame, void *buffer, size_t size); int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame); +int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame); +ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, + void *buffer, size_t size); +int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame); enum hdmi_spd_sdi { HDMI_SPD_SDI_UNKNOWN, @@ -381,6 +408,7 @@ union hdmi_infoframe { struct hdmi_spd_infoframe spd; union hdmi_vendor_any_infoframe vendor; struct hdmi_audio_infoframe audio; + struct hdmi_drm_infoframe drm; }; ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, -- cgit v1.3-6-gb490 From b5e3eed1eeb363c148e2935d9d3c12c30a280de6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 May 2019 19:40:12 +0530 Subject: drm: Add HLG EOTF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADD HLG EOTF to the list of EOTF transfer functions supported. Hybrid Log-Gamma (HLG) is a high dynamic range (HDR) standard. HLG defines a nonlinear transfer function in which the lower half of the signal values use a gamma curve and the upper half of the signal values use a logarithmic curve. v2: Rebase v3: Fixed a warning message v4: Addressed Shashank's review comments v5: Addressed Jonas Karlman's review comment and dropped the i915 tag from header. Signed-off-by: Ville Syrjälä Signed-off-by: Uma Shankar Reviewed-by: Shashank Sharma Link: https://patchwork.freedesktop.org/patch/msgid/1558015817-12025-8-git-send-email-uma.shankar@intel.com --- drivers/gpu/drm/drm_edid.c | 3 ++- include/linux/hdmi.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 73560c9437cd..262510c2a670 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3854,7 +3854,8 @@ static uint8_t eotf_supported(const u8 *edid_ext) return edid_ext[2] & (BIT(HDMI_EOTF_TRADITIONAL_GAMMA_SDR) | BIT(HDMI_EOTF_TRADITIONAL_GAMMA_HDR) | - BIT(HDMI_EOTF_SMPTE_ST2084)); + BIT(HDMI_EOTF_SMPTE_ST2084) | + BIT(HDMI_EOTF_BT_2100_HLG)); } static uint8_t hdr_metadata_type(const u8 *edid_ext) diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index bcf3c6c3499e..ee55ba589cdc 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -162,6 +162,7 @@ enum hdmi_eotf { HDMI_EOTF_TRADITIONAL_GAMMA_SDR, HDMI_EOTF_TRADITIONAL_GAMMA_HDR, HDMI_EOTF_SMPTE_ST2084, + HDMI_EOTF_BT_2100_HLG, }; struct hdmi_avi_infoframe { -- cgit v1.3-6-gb490