From 3d0ccae6f22fc05cbb2aa9f49363d35dd7338f29 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Mon, 29 Nov 2021 14:33:46 +0800 Subject: drm/tidss: Fix warning: unused variable 'tidss_pm_ops' Mark 'tidss_pm_ops' as __maybe_unused to avoid the warning: unused variable 'tidss_pm_ops' Fixes: 6e120594631f ("drm/tidss: Make use of the helper macro SET_RUNTIME_PM_OPS()") Signed-off-by: Cai Huoqing Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211129063347.404-1-caihuoqing@baidu.com --- drivers/gpu/drm/tidss/tidss_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c index 4366b5c798e0..7c784e90e40e 100644 --- a/drivers/gpu/drm/tidss/tidss_drv.c +++ b/drivers/gpu/drm/tidss/tidss_drv.c @@ -88,7 +88,7 @@ static int __maybe_unused tidss_resume(struct device *dev) return drm_mode_config_helper_resume(&tidss->ddev); } -static const struct dev_pm_ops tidss_pm_ops = { +static __maybe_unused const struct dev_pm_ops tidss_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tidss_suspend, tidss_resume) SET_RUNTIME_PM_OPS(tidss_pm_runtime_suspend, tidss_pm_runtime_resume, NULL) }; -- cgit v1.2.3 From 2985c96485b7ef4e015d13dc3081fb0479260951 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 29 Nov 2021 10:48:40 +0100 Subject: drm/vmwgfx: Copy DRM hash-table code into driver Besides some legacy code, vmwgfx is the only user of DRM's hash- table implementation. Copy the code into the driver, so that the core code can be retired. No functional changes. However, the real solution for vmwgfx is to use Linux' generic hash-table functions. v2: * add TODO item for updating vmwgfx (Sam) Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Acked-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20211129094841.22499-3-tzimmermann@suse.de --- Documentation/gpu/todo.rst | 11 ++ drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/ttm_object.c | 52 ++++---- drivers/gpu/drm/vmwgfx/ttm_object.h | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c | 24 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c | 199 +++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h | 83 ++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 22 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 7 +- 12 files changed, 353 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h (limited to 'drivers') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index f504d363fef5..da138dd39883 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -646,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks. Contact: Harry Wentland, Alex Deucher +vmwgfx: Replace hashtable with Linux' implementation +---------------------------------------------------- + +The vmwgfx driver uses its own hashtable implementation. Replace the +code with Linux' implementation and update the callers. It's mostly a +refactoring task, but the interfaces are different. + +Contact: Zack Rusin, Thomas Zimmermann + +Level: Intermediate + Bootsplash ========== diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index bc323f7d4032..e6a6a1edb058 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ +vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \ diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c index 899945f54dc7..22b3385d0c37 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.c +++ b/drivers/gpu/drm/vmwgfx/ttm_object.c @@ -73,7 +73,7 @@ struct ttm_object_file { struct ttm_object_device *tdev; spinlock_t lock; struct list_head ref_list; - struct drm_open_hash ref_hash[TTM_REF_NUM]; + struct vmwgfx_open_hash ref_hash[TTM_REF_NUM]; struct kref refcount; }; @@ -91,7 +91,7 @@ struct ttm_object_file { struct ttm_object_device { spinlock_t object_lock; - struct drm_open_hash object_hash; + struct vmwgfx_open_hash object_hash; atomic_t object_count; struct ttm_mem_global *mem_glob; struct dma_buf_ops ops; @@ -123,7 +123,7 @@ struct ttm_object_device { struct ttm_ref_object { struct rcu_head rcu_head; - struct drm_hash_item hash; + struct vmwgfx_hash_item hash; struct list_head head; struct kref kref; enum ttm_ref_type ref_type; @@ -247,12 +247,12 @@ void ttm_base_object_unref(struct ttm_base_object **p_base) struct ttm_base_object * ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key) { - struct drm_hash_item *hash; - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; + struct vmwgfx_hash_item *hash; + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; int ret; rcu_read_lock(); - ret = drm_ht_find_item_rcu(ht, key, &hash); + ret = vmwgfx_ht_find_item_rcu(ht, key, &hash); if (ret) { rcu_read_unlock(); return NULL; @@ -267,12 +267,12 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, uint32_t key) { struct ttm_base_object *base = NULL; - struct drm_hash_item *hash; - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; + struct vmwgfx_hash_item *hash; + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; int ret; rcu_read_lock(); - ret = drm_ht_find_item_rcu(ht, key, &hash); + ret = vmwgfx_ht_find_item_rcu(ht, key, &hash); if (likely(ret == 0)) { base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj; @@ -312,12 +312,12 @@ ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key) bool ttm_ref_object_exists(struct ttm_object_file *tfile, struct ttm_base_object *base) { - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; - struct drm_hash_item *hash; + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; + struct vmwgfx_hash_item *hash; struct ttm_ref_object *ref; rcu_read_lock(); - if (unlikely(drm_ht_find_item_rcu(ht, base->handle, &hash) != 0)) + if (unlikely(vmwgfx_ht_find_item_rcu(ht, base->handle, &hash) != 0)) goto out_false; /* @@ -349,9 +349,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, enum ttm_ref_type ref_type, bool *existed, bool require_existed) { - struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; + struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type]; struct ttm_ref_object *ref; - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; struct ttm_operation_ctx ctx = { .interruptible = false, @@ -367,7 +367,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, while (ret == -EINVAL) { rcu_read_lock(); - ret = drm_ht_find_item_rcu(ht, base->handle, &hash); + ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash); if (ret == 0) { ref = drm_hash_entry(hash, struct ttm_ref_object, hash); @@ -398,7 +398,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, kref_init(&ref->kref); spin_lock(&tfile->lock); - ret = drm_ht_insert_item_rcu(ht, &ref->hash); + ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash); if (likely(ret == 0)) { list_add_tail(&ref->head, &tfile->ref_list); @@ -426,11 +426,11 @@ ttm_ref_object_release(struct kref *kref) container_of(kref, struct ttm_ref_object, kref); struct ttm_base_object *base = ref->obj; struct ttm_object_file *tfile = ref->tfile; - struct drm_open_hash *ht; + struct vmwgfx_open_hash *ht; struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; ht = &tfile->ref_hash[ref->ref_type]; - (void)drm_ht_remove_item_rcu(ht, &ref->hash); + (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash); list_del(&ref->head); spin_unlock(&tfile->lock); @@ -446,13 +446,13 @@ ttm_ref_object_release(struct kref *kref) int ttm_ref_object_base_unref(struct ttm_object_file *tfile, unsigned long key, enum ttm_ref_type ref_type) { - struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; + struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type]; struct ttm_ref_object *ref; - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; int ret; spin_lock(&tfile->lock); - ret = drm_ht_find_item(ht, key, &hash); + ret = vmwgfx_ht_find_item(ht, key, &hash); if (unlikely(ret != 0)) { spin_unlock(&tfile->lock); return -EINVAL; @@ -486,7 +486,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile) spin_unlock(&tfile->lock); for (i = 0; i < TTM_REF_NUM; ++i) - drm_ht_remove(&tfile->ref_hash[i]); + vmwgfx_ht_remove(&tfile->ref_hash[i]); ttm_object_file_unref(&tfile); } @@ -508,7 +508,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, INIT_LIST_HEAD(&tfile->ref_list); for (i = 0; i < TTM_REF_NUM; ++i) { - ret = drm_ht_create(&tfile->ref_hash[i], hash_order); + ret = vmwgfx_ht_create(&tfile->ref_hash[i], hash_order); if (ret) { j = i; goto out_err; @@ -518,7 +518,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, return tfile; out_err: for (i = 0; i < j; ++i) - drm_ht_remove(&tfile->ref_hash[i]); + vmwgfx_ht_remove(&tfile->ref_hash[i]); kfree(tfile); @@ -539,7 +539,7 @@ ttm_object_device_init(struct ttm_mem_global *mem_glob, tdev->mem_glob = mem_glob; spin_lock_init(&tdev->object_lock); atomic_set(&tdev->object_count, 0); - ret = drm_ht_create(&tdev->object_hash, hash_order); + ret = vmwgfx_ht_create(&tdev->object_hash, hash_order); if (ret != 0) goto out_no_object_hash; @@ -564,7 +564,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev) WARN_ON_ONCE(!idr_is_empty(&tdev->idr)); idr_destroy(&tdev->idr); - drm_ht_remove(&tdev->object_hash); + vmwgfx_ht_remove(&tdev->object_hash); kfree(tdev); } diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h index 49b064f0cb19..6885ccbeec7a 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.h +++ b/drivers/gpu/drm/vmwgfx/ttm_object.h @@ -42,9 +42,8 @@ #include #include -#include - #include "ttm_memory.h" +#include "vmwgfx_hashtab.h" /** * enum ttm_ref_type diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 8381750db81b..494cb98061f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -42,7 +42,7 @@ */ struct vmw_cmdbuf_res { struct vmw_resource *res; - struct drm_hash_item hash; + struct vmwgfx_hash_item hash; struct list_head head; enum vmw_cmdbuf_res_state state; struct vmw_cmdbuf_res_manager *man; @@ -59,7 +59,7 @@ struct vmw_cmdbuf_res { * @resources and @list are protected by the cmdbuf mutex for now. */ struct vmw_cmdbuf_res_manager { - struct drm_open_hash resources; + struct vmwgfx_open_hash resources; struct list_head list; struct vmw_private *dev_priv; }; @@ -81,11 +81,11 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man, enum vmw_cmdbuf_res_type res_type, u32 user_key) { - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; int ret; unsigned long key = user_key | (res_type << 24); - ret = drm_ht_find_item(&man->resources, key, &hash); + ret = vmwgfx_ht_find_item(&man->resources, key, &hash); if (unlikely(ret != 0)) return ERR_PTR(ret); @@ -105,7 +105,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man, struct vmw_cmdbuf_res *entry) { list_del(&entry->head); - WARN_ON(drm_ht_remove_item(&man->resources, &entry->hash)); + WARN_ON(vmwgfx_ht_remove_item(&man->resources, &entry->hash)); vmw_resource_unreference(&entry->res); kfree(entry); } @@ -167,7 +167,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list) vmw_cmdbuf_res_free(entry->man, entry); break; case VMW_CMDBUF_RES_DEL: - ret = drm_ht_insert_item(&entry->man->resources, &entry->hash); + ret = vmwgfx_ht_insert_item(&entry->man->resources, &entry->hash); BUG_ON(ret); list_move_tail(&entry->head, &entry->man->list); entry->state = VMW_CMDBUF_RES_COMMITTED; @@ -206,7 +206,7 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man, return -ENOMEM; cres->hash.key = user_key | (res_type << 24); - ret = drm_ht_insert_item(&man->resources, &cres->hash); + ret = vmwgfx_ht_insert_item(&man->resources, &cres->hash); if (unlikely(ret != 0)) { kfree(cres); goto out_invalid_key; @@ -244,10 +244,10 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, struct vmw_resource **res_p) { struct vmw_cmdbuf_res *entry; - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; int ret; - ret = drm_ht_find_item(&man->resources, user_key | (res_type << 24), + ret = vmwgfx_ht_find_item(&man->resources, user_key | (res_type << 24), &hash); if (likely(ret != 0)) return -EINVAL; @@ -260,7 +260,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, *res_p = NULL; break; case VMW_CMDBUF_RES_COMMITTED: - (void) drm_ht_remove_item(&man->resources, &entry->hash); + (void) vmwgfx_ht_remove_item(&man->resources, &entry->hash); list_del(&entry->head); entry->state = VMW_CMDBUF_RES_DEL; list_add_tail(&entry->head, list); @@ -295,7 +295,7 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv) man->dev_priv = dev_priv; INIT_LIST_HEAD(&man->list); - ret = drm_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER); + ret = vmwgfx_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER); if (ret == 0) return man; @@ -320,7 +320,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man) list_for_each_entry_safe(entry, next, &man->list, head) vmw_cmdbuf_res_free(man, entry); - drm_ht_remove(&man->resources); + vmwgfx_ht_remove(&man->resources); kfree(man); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 75d1e032cf16..d10933a16bc4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1155,7 +1155,7 @@ static void vmw_driver_unload(struct drm_device *dev) unregister_pm_notifier(&dev_priv->pm_nb); if (dev_priv->ctx.res_ht_initialized) - drm_ht_remove(&dev_priv->ctx.res_ht); + vmwgfx_ht_remove(&dev_priv->ctx.res_ht); vfree(dev_priv->ctx.cmd_bounce); if (dev_priv->enable_fb) { vmw_fb_off(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 858aff99a3fe..530ac1b557f9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -43,6 +42,7 @@ #include "ttm_object.h" #include "vmwgfx_fence.h" +#include "vmwgfx_hashtab.h" #include "vmwgfx_reg.h" #include "vmwgfx_validation.h" @@ -133,7 +133,7 @@ struct vmw_buffer_object { */ struct vmw_validate_buffer { struct ttm_validate_buffer base; - struct drm_hash_item hash; + struct vmwgfx_hash_item hash; bool validate_as_mob; }; @@ -406,7 +406,7 @@ struct vmw_ctx_validation_info; * @ctx: The validation context */ struct vmw_sw_context{ - struct drm_open_hash res_ht; + struct vmwgfx_open_hash res_ht; bool res_ht_initialized; bool kernel; struct vmw_fpriv *fp; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 5f2ffa9de5c8..986e85b7e616 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -4117,7 +4117,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, vmw_binding_state_reset(sw_context->staged_bindings); if (!sw_context->res_ht_initialized) { - ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); + ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); if (unlikely(ret != 0)) goto out_unlock; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c new file mode 100644 index 000000000000..06aebc12774e --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c @@ -0,0 +1,199 @@ +/* + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Simple open hash tab implementation. + * + * Authors: + * Thomas Hellström + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "vmwgfx_hashtab.h" + +int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order) +{ + unsigned int size = 1 << order; + + ht->order = order; + ht->table = NULL; + if (size <= PAGE_SIZE / sizeof(*ht->table)) + ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL); + else + ht->table = vzalloc(array_size(size, sizeof(*ht->table))); + if (!ht->table) { + DRM_ERROR("Out of memory for hash table\n"); + return -ENOMEM; + } + return 0; +} + +void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key) +{ + struct vmwgfx_hash_item *entry; + struct hlist_head *h_list; + unsigned int hashed_key; + int count = 0; + + hashed_key = hash_long(key, ht->order); + DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); + h_list = &ht->table[hashed_key]; + hlist_for_each_entry(entry, h_list, head) + DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); +} + +static struct hlist_node *vmwgfx_ht_find_key(struct vmwgfx_open_hash *ht, unsigned long key) +{ + struct vmwgfx_hash_item *entry; + struct hlist_head *h_list; + unsigned int hashed_key; + + hashed_key = hash_long(key, ht->order); + h_list = &ht->table[hashed_key]; + hlist_for_each_entry(entry, h_list, head) { + if (entry->key == key) + return &entry->head; + if (entry->key > key) + break; + } + return NULL; +} + +static struct hlist_node *vmwgfx_ht_find_key_rcu(struct vmwgfx_open_hash *ht, unsigned long key) +{ + struct vmwgfx_hash_item *entry; + struct hlist_head *h_list; + unsigned int hashed_key; + + hashed_key = hash_long(key, ht->order); + h_list = &ht->table[hashed_key]; + hlist_for_each_entry_rcu(entry, h_list, head) { + if (entry->key == key) + return &entry->head; + if (entry->key > key) + break; + } + return NULL; +} + +int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item) +{ + struct vmwgfx_hash_item *entry; + struct hlist_head *h_list; + struct hlist_node *parent; + unsigned int hashed_key; + unsigned long key = item->key; + + hashed_key = hash_long(key, ht->order); + h_list = &ht->table[hashed_key]; + parent = NULL; + hlist_for_each_entry(entry, h_list, head) { + if (entry->key == key) + return -EINVAL; + if (entry->key > key) + break; + parent = &entry->head; + } + if (parent) + hlist_add_behind_rcu(&item->head, parent); + else + hlist_add_head_rcu(&item->head, h_list); + return 0; +} + +/* + * Just insert an item and return any "bits" bit key that hasn't been + * used before. + */ +int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item, + unsigned long seed, int bits, int shift, + unsigned long add) +{ + int ret; + unsigned long mask = (1UL << bits) - 1; + unsigned long first, unshifted_key; + + unshifted_key = hash_long(seed, bits); + first = unshifted_key; + do { + item->key = (unshifted_key << shift) + add; + ret = vmwgfx_ht_insert_item(ht, item); + if (ret) + unshifted_key = (unshifted_key + 1) & mask; + } while (ret && (unshifted_key != first)); + + if (ret) { + DRM_ERROR("Available key bit space exhausted\n"); + return -EINVAL; + } + return 0; +} + +int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key, + struct vmwgfx_hash_item **item) +{ + struct hlist_node *list; + + list = vmwgfx_ht_find_key_rcu(ht, key); + if (!list) + return -EINVAL; + + *item = hlist_entry(list, struct vmwgfx_hash_item, head); + return 0; +} + +int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key) +{ + struct hlist_node *list; + + list = vmwgfx_ht_find_key(ht, key); + if (list) { + hlist_del_init_rcu(list); + return 0; + } + return -EINVAL; +} + +int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item) +{ + hlist_del_init_rcu(&item->head); + return 0; +} + +void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht) +{ + if (ht->table) { + kvfree(ht->table); + ht->table = NULL; + } +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h new file mode 100644 index 000000000000..a9ce12922e21 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h @@ -0,0 +1,83 @@ +/* + * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Simple open hash tab implementation. + * + * Authors: + * Thomas Hellström + */ + +/* + * TODO: Replace this hashtable with Linux' generic implementation + * from . + */ + +#ifndef VMWGFX_HASHTAB_H +#define VMWGFX_HASHTAB_H + +#include + +#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) + +struct vmwgfx_hash_item { + struct hlist_node head; + unsigned long key; +}; + +struct vmwgfx_open_hash { + struct hlist_head *table; + u8 order; +}; + +int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order); +int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item); +int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item, + unsigned long seed, int bits, int shift, + unsigned long add); +int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key, + struct vmwgfx_hash_item **item); + +void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key); +int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key); +int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item); +void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht); + +/* + * RCU-safe interface + * + * The user of this API needs to make sure that two or more instances of the + * hash table manipulation functions are never run simultaneously. + * The lookup function vmwgfx_ht_find_item_rcu may, however, run simultaneously + * with any of the manipulation functions as long as it's called from within + * an RCU read-locked section. + */ +#define vmwgfx_ht_insert_item_rcu vmwgfx_ht_insert_item +#define vmwgfx_ht_just_insert_please_rcu vmwgfx_ht_just_insert_please +#define vmwgfx_ht_remove_key_rcu vmwgfx_ht_remove_key +#define vmwgfx_ht_remove_item_rcu vmwgfx_ht_remove_item +#define vmwgfx_ht_find_item_rcu vmwgfx_ht_find_item + +#endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c index b09094b50c5d..41b7417cb5d3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c @@ -43,7 +43,7 @@ */ struct vmw_validation_bo_node { struct ttm_validate_buffer base; - struct drm_hash_item hash; + struct vmwgfx_hash_item hash; unsigned int coherent_count; u32 as_mob : 1; u32 cpu_blit : 1; @@ -72,7 +72,7 @@ struct vmw_validation_bo_node { */ struct vmw_validation_res_node { struct list_head head; - struct drm_hash_item hash; + struct vmwgfx_hash_item hash; struct vmw_resource *res; struct vmw_buffer_object *new_backup; unsigned long new_backup_offset; @@ -184,9 +184,9 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, return NULL; if (ctx->ht) { - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; - if (!drm_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) + if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) bo_node = container_of(hash, typeof(*bo_node), hash); } else { struct vmw_validation_bo_node *entry; @@ -221,9 +221,9 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, return NULL; if (ctx->ht) { - struct drm_hash_item *hash; + struct vmwgfx_hash_item *hash; - if (!drm_ht_find_item(ctx->ht, (unsigned long) res, &hash)) + if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash)) res_node = container_of(hash, typeof(*res_node), hash); } else { struct vmw_validation_res_node *entry; @@ -280,7 +280,7 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, if (ctx->ht) { bo_node->hash.key = (unsigned long) vbo; - ret = drm_ht_insert_item(ctx->ht, &bo_node->hash); + ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash); if (ret) { DRM_ERROR("Failed to initialize a buffer " "validation entry.\n"); @@ -335,7 +335,7 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx, if (ctx->ht) { node->hash.key = (unsigned long) res; - ret = drm_ht_insert_item(ctx->ht, &node->hash); + ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash); if (ret) { DRM_ERROR("Failed to initialize a resource validation " "entry.\n"); @@ -688,13 +688,13 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx) return; list_for_each_entry(entry, &ctx->bo_list, base.head) - (void) drm_ht_remove_item(ctx->ht, &entry->hash); + (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash); list_for_each_entry(val, &ctx->resource_list, head) - (void) drm_ht_remove_item(ctx->ht, &val->hash); + (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash); list_for_each_entry(val, &ctx->resource_ctx_list, head) - (void) drm_ht_remove_item(ctx->ht, &val->hash); + (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash); ctx->ht = NULL; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h index 739906d1b3eb..495fd504b8c6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h @@ -31,9 +31,10 @@ #include #include -#include #include +#include "vmwgfx_hashtab.h" + #define VMW_RES_DIRTY_NONE 0 #define VMW_RES_DIRTY_SET BIT(0) #define VMW_RES_DIRTY_CLEAR BIT(1) @@ -73,7 +74,7 @@ struct vmw_validation_mem { * @total_mem: Amount of reserved memory. */ struct vmw_validation_context { - struct drm_open_hash *ht; + struct vmwgfx_open_hash *ht; struct list_head resource_list; struct list_head resource_ctx_list; struct list_head bo_list; @@ -151,7 +152,7 @@ vmw_validation_set_val_mem(struct vmw_validation_context *ctx, * available at validation context declaration time */ static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, - struct drm_open_hash *ht) + struct vmwgfx_open_hash *ht) { ctx->ht = ht; } -- cgit v1.2.3 From a21800bced7cbaf7bb8f5281db17a5d7ef6e197a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 29 Nov 2021 10:48:41 +0100 Subject: drm: Declare hashtable as legacy The DRM hashtable code is only used by internal functions for legacy UMS drivers. Move the implementation behind CONFIG_DRM_LEGACY and the declarations into legacy header files. Unexport the symbols. Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Acked-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20211129094841.22499-4-tzimmermann@suse.de --- drivers/gpu/drm/Makefile | 6 ++-- drivers/gpu/drm/drm_hashtab.c | 10 ++---- drivers/gpu/drm/drm_legacy.h | 40 +++++++++++++++++++++- include/drm/drm_device.h | 5 +-- include/drm/drm_hashtab.h | 79 ------------------------------------------- include/drm/drm_legacy.h | 15 +++++++- 6 files changed, 59 insertions(+), 96 deletions(-) delete mode 100644 include/drm/drm_hashtab.h (limited to 'drivers') diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index fa16d3e0bbdc..9dbf91399343 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -6,7 +6,7 @@ drm-y := drm_aperture.o drm_auth.o drm_cache.o \ drm_file.o drm_gem.o drm_ioctl.o \ drm_drv.o \ - drm_sysfs.o drm_hashtab.o drm_mm.o \ + drm_sysfs.o drm_mm.o \ drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \ drm_trace_points.o drm_prime.o \ drm_vma_manager.o \ @@ -20,8 +20,8 @@ drm-y := drm_aperture.o drm_auth.o drm_cache.o \ drm_managed.o drm_vblank_work.o drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \ - drm_irq.o drm_legacy_misc.o drm_lock.o drm_memory.o \ - drm_scatter.o drm_vm.o + drm_hashtab.o drm_irq.o drm_legacy_misc.o drm_lock.o \ + drm_memory.o drm_scatter.o drm_vm.o drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_PANEL) += drm_panel.o diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index c50fa6f0709f..60afa1865559 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c @@ -32,16 +32,16 @@ * Thomas Hellström */ -#include #include #include #include #include #include -#include #include +#include "drm_legacy.h" + int drm_ht_create(struct drm_open_hash *ht, unsigned int order) { unsigned int size = 1 << order; @@ -58,7 +58,6 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order) } return 0; } -EXPORT_SYMBOL(drm_ht_create); void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) { @@ -135,7 +134,6 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) } return 0; } -EXPORT_SYMBOL(drm_ht_insert_item); /* * Just insert an item and return any "bits" bit key that hasn't been @@ -164,7 +162,6 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it } return 0; } -EXPORT_SYMBOL(drm_ht_just_insert_please); int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item) @@ -178,7 +175,6 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, *item = hlist_entry(list, struct drm_hash_item, head); return 0; } -EXPORT_SYMBOL(drm_ht_find_item); int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) { @@ -197,7 +193,6 @@ int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) hlist_del_init_rcu(&item->head); return 0; } -EXPORT_SYMBOL(drm_ht_remove_item); void drm_ht_remove(struct drm_open_hash *ht) { @@ -206,4 +201,3 @@ void drm_ht_remove(struct drm_open_hash *ht) ht->table = NULL; } } -EXPORT_SYMBOL(drm_ht_remove); diff --git a/drivers/gpu/drm/drm_legacy.h b/drivers/gpu/drm/drm_legacy.h index c9206840c87f..70c9dba114a6 100644 --- a/drivers/gpu/drm/drm_legacy.h +++ b/drivers/gpu/drm/drm_legacy.h @@ -35,9 +35,47 @@ #include struct agp_memory; +struct drm_buf_desc; struct drm_device; struct drm_file; -struct drm_buf_desc; +struct drm_hash_item; +struct drm_open_hash; + +/* + * Hash-table Support + */ + +#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) + +/* drm_hashtab.c */ +#if IS_ENABLED(CONFIG_DRM_LEGACY) +int drm_ht_create(struct drm_open_hash *ht, unsigned int order); +int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item); +int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, + unsigned long seed, int bits, int shift, + unsigned long add); +int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item); + +void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key); +int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); +int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); +void drm_ht_remove(struct drm_open_hash *ht); +#endif + +/* + * RCU-safe interface + * + * The user of this API needs to make sure that two or more instances of the + * hash table manipulation functions are never run simultaneously. + * The lookup function drm_ht_find_item_rcu may, however, run simultaneously + * with any of the manipulation functions as long as it's called from within + * an RCU read-locked section. + */ +#define drm_ht_insert_item_rcu drm_ht_insert_item +#define drm_ht_just_insert_please_rcu drm_ht_just_insert_please +#define drm_ht_remove_key_rcu drm_ht_remove_key +#define drm_ht_remove_item_rcu drm_ht_remove_item +#define drm_ht_find_item_rcu drm_ht_find_item /* * Generic DRM Contexts diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 604b1d1b2d72..9923c7a6885e 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -6,16 +6,13 @@ #include #include -#include +#include #include struct drm_driver; struct drm_minor; struct drm_master; -struct drm_device_dma; 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; diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h deleted file mode 100644 index bb95ff011baf..000000000000 --- a/include/drm/drm_hashtab.h +++ /dev/null @@ -1,79 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * - **************************************************************************/ -/* - * Simple open hash tab implementation. - * - * Authors: - * Thomas Hellström - */ - -#ifndef DRM_HASHTAB_H -#define DRM_HASHTAB_H - -#include - -#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) - -struct drm_hash_item { - struct hlist_node head; - unsigned long key; -}; - -struct drm_open_hash { - struct hlist_head *table; - u8 order; -}; - -int drm_ht_create(struct drm_open_hash *ht, unsigned int order); -int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item); -int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, - unsigned long seed, int bits, int shift, - unsigned long add); -int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item); - -void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key); -int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); -int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); -void drm_ht_remove(struct drm_open_hash *ht); - -/* - * RCU-safe interface - * - * The user of this API needs to make sure that two or more instances of the - * hash table manipulation functions are never run simultaneously. - * The lookup function drm_ht_find_item_rcu may, however, run simultaneously - * with any of the manipulation functions as long as it's called from within - * an RCU read-locked section. - */ -#define drm_ht_insert_item_rcu drm_ht_insert_item -#define drm_ht_just_insert_please_rcu drm_ht_just_insert_please -#define drm_ht_remove_key_rcu drm_ht_remove_key -#define drm_ht_remove_item_rcu drm_ht_remove_item -#define drm_ht_find_item_rcu drm_ht_find_item - -#endif diff --git a/include/drm/drm_legacy.h b/include/drm/drm_legacy.h index 58dc8d8cc907..0fc85418aad8 100644 --- a/include/drm/drm_legacy.h +++ b/include/drm/drm_legacy.h @@ -37,7 +37,6 @@ #include #include -#include struct drm_device; struct drm_driver; @@ -51,6 +50,20 @@ struct pci_driver; * you're doing it terribly wrong. */ +/* + * Hash-table Support + */ + +struct drm_hash_item { + struct hlist_node head; + unsigned long key; +}; + +struct drm_open_hash { + struct hlist_head *table; + u8 order; +}; + /** * DMA buffer. */ -- cgit v1.2.3 From 05b1de51df077a2089e3d8ceec68aa687cff15db Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 15 Nov 2021 13:01:47 +0100 Subject: drm/cma-helper: Export dedicated wrappers for GEM object functions Wrap GEM CMA functions for struct drm_gem_object_funcs and update all callers. This will allow for an update of the public interfaces of the GEM CMA helper library. Signed-off-by: Thomas Zimmermann Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20211115120148.21766-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_cma_helper.c | 23 ++++------- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 10 ++--- drivers/gpu/drm/vc4/vc4_bo.c | 4 +- include/drm/drm_gem_cma_helper.h | 78 +++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index 2a34241fee02..fcd7d2eb90ab 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -35,11 +35,11 @@ */ static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = { - .free = drm_gem_cma_free_object, - .print_info = drm_gem_cma_print_info, - .get_sg_table = drm_gem_cma_get_sg_table, - .vmap = drm_gem_cma_vmap, - .mmap = drm_gem_cma_mmap, + .free = drm_gem_cma_object_free, + .print_info = drm_gem_cma_object_print_info, + .get_sg_table = drm_gem_cma_object_get_sg_table, + .vmap = drm_gem_cma_object_vmap, + .mmap = drm_gem_cma_object_mmap, .vm_ops = &drm_gem_cma_vm_ops, }; @@ -198,8 +198,6 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, * This function frees the backing memory of the CMA GEM object, cleans up the * GEM object state and frees the memory used to store the object itself. * If the buffer is imported and the virtual address is set, it is released. - * Drivers using the CMA helpers should set this as their - * &drm_gem_object_funcs.free callback. */ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) { @@ -388,9 +386,8 @@ EXPORT_SYMBOL(drm_gem_cma_print_info); * pages for a CMA GEM object * @obj: GEM object * - * This function exports a scatter/gather table by - * calling the standard DMA mapping API. Drivers using the CMA helpers should - * set this as their &drm_gem_object_funcs.get_sg_table callback. + * This function exports a scatter/gather table by calling the standard + * DMA mapping API. * * Returns: * A pointer to the scatter/gather table of pinned pages or NULL on failure. @@ -470,8 +467,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table); * This function maps a buffer into the kernel's * virtual address space. Since the CMA buffers are already mapped into the * kernel virtual address space this simply returns the cached virtual - * address. Drivers using the CMA helpers should set this as their DRM - * driver's &drm_gem_object_funcs.vmap callback. + * address. * * Returns: * 0 on success, or a negative error code otherwise. @@ -493,8 +489,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); * * This function maps a buffer into a userspace process's address space. * In addition to the usual GEM VMA setup it immediately faults in the entire - * object instead of using on-demand faulting. Drivers that use the CMA - * helpers should set this as their &drm_gem_object_funcs.mmap callback. + * object instead of using on-demand faulting. * * Returns: * 0 on success or a negative error code on failure. diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index eacb1f17f747..190dbb7f15dd 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -327,11 +327,11 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc) */ static const struct drm_gem_object_funcs rcar_du_gem_funcs = { - .free = drm_gem_cma_free_object, - .print_info = drm_gem_cma_print_info, - .get_sg_table = drm_gem_cma_get_sg_table, - .vmap = drm_gem_cma_vmap, - .mmap = drm_gem_cma_mmap, + .free = drm_gem_cma_object_free, + .print_info = drm_gem_cma_object_print_info, + .get_sg_table = drm_gem_cma_object_get_sg_table, + .vmap = drm_gem_cma_object_vmap, + .mmap = drm_gem_cma_object_mmap, .vm_ops = &drm_gem_cma_vm_ops, }; diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index fddaeb0b09c1..830756b3159e 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -732,8 +732,8 @@ static const struct vm_operations_struct vc4_vm_ops = { static const struct drm_gem_object_funcs vc4_gem_object_funcs = { .free = vc4_free_object, .export = vc4_prime_export, - .get_sg_table = drm_gem_cma_get_sg_table, - .vmap = drm_gem_cma_vmap, + .get_sg_table = drm_gem_cma_object_get_sg_table, + .vmap = drm_gem_cma_object_vmap, .mmap = vc4_gem_object_mmap, .vm_ops = &vc4_vm_ops, }; diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h index e0fb7a0cf03f..56d2f9fdf9ac 100644 --- a/include/drm/drm_gem_cma_helper.h +++ b/include/drm/drm_gem_cma_helper.h @@ -48,6 +48,84 @@ struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_object *obj); int drm_gem_cma_vmap(struct drm_gem_object *obj, struct dma_buf_map *map); int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); +/* + * GEM object functions + */ + +/** + * drm_gem_cma_object_free - GEM object function for drm_gem_cma_free_object() + * @obj: GEM object to free + * + * This function wraps drm_gem_cma_free_object(). Drivers that employ the CMA helpers + * should use it as their &drm_gem_object_funcs.free handler. + */ +static inline void drm_gem_cma_object_free(struct drm_gem_object *obj) +{ + drm_gem_cma_free_object(obj); +} + +/** + * drm_gem_cma_object_print_info() - Print &drm_gem_cma_object info for debugfs + * @p: DRM printer + * @indent: Tab indentation level + * @obj: GEM object + * + * This function wraps drm_gem_cma_print_info(). Drivers that employ the CMA helpers + * should use this function as their &drm_gem_object_funcs.print_info handler. + */ +static inline void drm_gem_cma_object_print_info(struct drm_printer *p, unsigned int indent, + const struct drm_gem_object *obj) +{ + drm_gem_cma_print_info(p, indent, obj); +} + +/** + * drm_gem_cma_object_get_sg_table - GEM object function for drm_gem_cma_get_sg_table() + * @obj: GEM object + * + * This function wraps drm_gem_cma_get_sg_table(). Drivers that employ the CMA helpers should + * use it as their &drm_gem_object_funcs.get_sg_table handler. + * + * Returns: + * A pointer to the scatter/gather table of pinned pages or NULL on failure. + */ +static inline struct sg_table *drm_gem_cma_object_get_sg_table(struct drm_gem_object *obj) +{ + return drm_gem_cma_get_sg_table(obj); +} + +/* + * drm_gem_cma_object_vmap - GEM object function for drm_gem_cma_vmap() + * @obj: GEM object + * @map: Returns the kernel virtual address of the CMA GEM object's backing store. + * + * This function wraps drm_gem_cma_vmap(). Drivers that employ the CMA helpers should + * use it as their &drm_gem_object_funcs.vmap handler. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +static inline int drm_gem_cma_object_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) +{ + return drm_gem_cma_vmap(obj, map); +} + +/** + * drm_gem_cma_object_mmap - GEM object function for drm_gem_cma_mmap() + * @obj: GEM object + * @vma: VMA for the area to be mapped + * + * This function wraps drm_gem_cma_mmap(). Drivers that employ the cma helpers should + * use it as their &drm_gem_object_funcs.mmap handler. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +static inline int drm_gem_cma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + return drm_gem_cma_mmap(obj, vma); +} + /* * Driver ops */ -- cgit v1.2.3 From e580ea25c08d9e89593bcf80640e29108f0542cb Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 15 Nov 2021 13:01:48 +0100 Subject: drm/cma-helper: Pass GEM CMA object in public interfaces Change all GEM CMA object functions that receive a GEM object of type struct drm_gem_object to expect an object of type struct drm_gem_cma_object instead. This change reduces the number of upcasts from struct drm_gem_object by moving them into callers. The C compiler can now verify that the GEM CMA functions are called with the correct type. For consistency, the patch also renames drm_gem_cma_free_object to drm_gem_cma_free. It further updates documentation for a number of functions. Signed-off-by: Thomas Zimmermann Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20211115120148.21766-4-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_cma_helper.c | 52 +++++++++++++++++------------------- drivers/gpu/drm/vc4/vc4_bo.c | 4 +-- include/drm/drm_gem_cma_helper.h | 39 +++++++++++++++------------ 3 files changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index fcd7d2eb90ab..5f42e44b2ab3 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -32,6 +32,10 @@ * The DRM GEM/CMA helpers use this allocator as a means to provide buffer * objects that are physically contiguous in memory. This is useful for * display drivers that are unable to map scattered buffers via an IOMMU. + * + * For GEM callback helpers in struct &drm_gem_object functions, see likewise + * named functions with an _object_ infix (e.g., drm_gem_cma_object_vmap() wraps + * drm_gem_cma_vmap()). These helpers perform the necessary type conversion. */ static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = { @@ -192,16 +196,16 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, } /** - * drm_gem_cma_free_object - free resources associated with a CMA GEM object - * @gem_obj: GEM object to free + * drm_gem_cma_free - free resources associated with a CMA GEM object + * @cma_obj: CMA GEM object to free * * This function frees the backing memory of the CMA GEM object, cleans up the * GEM object state and frees the memory used to store the object itself. * If the buffer is imported and the virtual address is set, it is released. */ -void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) +void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem_obj); + struct drm_gem_object *gem_obj = &cma_obj->base; struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(cma_obj->vaddr); if (gem_obj->import_attach) { @@ -217,7 +221,7 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) kfree(cma_obj); } -EXPORT_SYMBOL_GPL(drm_gem_cma_free_object); +EXPORT_SYMBOL_GPL(drm_gem_cma_free); /** * drm_gem_cma_dumb_create_internal - create a dumb buffer object @@ -364,18 +368,15 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area); /** * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs + * @cma_obj: CMA GEM object * @p: DRM printer * @indent: Tab indentation level - * @obj: GEM object * - * This function can be used as the &drm_driver->gem_print_info callback. - * It prints paddr and vaddr for use in e.g. debugfs output. + * This function prints paddr and vaddr for use in e.g. debugfs output. */ -void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent, - const struct drm_gem_object *obj) +void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj, + struct drm_printer *p, unsigned int indent) { - const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); - drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr); drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr); } @@ -384,7 +385,7 @@ EXPORT_SYMBOL(drm_gem_cma_print_info); /** * drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned * pages for a CMA GEM object - * @obj: GEM object + * @cma_obj: CMA GEM object * * This function exports a scatter/gather table by calling the standard * DMA mapping API. @@ -392,9 +393,9 @@ EXPORT_SYMBOL(drm_gem_cma_print_info); * Returns: * A pointer to the scatter/gather table of pinned pages or NULL on failure. */ -struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_object *obj) +struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct drm_gem_object *obj = &cma_obj->base; struct sg_table *sgt; int ret; @@ -460,22 +461,19 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table); /** * drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual * address space - * @obj: GEM object + * @cma_obj: CMA GEM object * @map: Returns the kernel virtual address of the CMA GEM object's backing * store. * - * This function maps a buffer into the kernel's - * virtual address space. Since the CMA buffers are already mapped into the - * kernel virtual address space this simply returns the cached virtual - * address. + * This function maps a buffer into the kernel's virtual address space. + * Since the CMA buffers are already mapped into the kernel virtual address + * space this simply returns the cached virtual address. * * Returns: * 0 on success, or a negative error code otherwise. */ -int drm_gem_cma_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) +int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj, struct dma_buf_map *map) { - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); - dma_buf_map_set_vaddr(map, cma_obj->vaddr); return 0; @@ -484,7 +482,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); /** * drm_gem_cma_mmap - memory-map an exported CMA GEM object - * @obj: GEM object + * @cma_obj: CMA GEM object * @vma: VMA for the area to be mapped * * This function maps a buffer into a userspace process's address space. @@ -494,9 +492,9 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); * Returns: * 0 on success or a negative error code on failure. */ -int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma) { - struct drm_gem_cma_object *cma_obj; + struct drm_gem_object *obj = &cma_obj->base; int ret; /* @@ -507,8 +505,6 @@ int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); vma->vm_flags &= ~VM_PFNMAP; - cma_obj = to_drm_gem_cma_obj(obj); - if (cma_obj->map_noncoherent) { vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 830756b3159e..6d1281a343e9 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -177,7 +177,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo) bo->validated_shader = NULL; } - drm_gem_cma_free_object(obj); + drm_gem_cma_free(&bo->base); } static void vc4_bo_remove_from_cache(struct vc4_bo *bo) @@ -720,7 +720,7 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct return -EINVAL; } - return drm_gem_cma_mmap(obj, vma); + return drm_gem_cma_mmap(&bo->base, vma); } static const struct vm_operations_struct vc4_vm_ops = { diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h index 56d2f9fdf9ac..adb507a9dbf0 100644 --- a/include/drm/drm_gem_cma_helper.h +++ b/include/drm/drm_gem_cma_helper.h @@ -32,28 +32,23 @@ struct drm_gem_cma_object { #define to_drm_gem_cma_obj(gem_obj) \ container_of(gem_obj, struct drm_gem_cma_object, base) -/* free GEM object */ -void drm_gem_cma_free_object(struct drm_gem_object *gem_obj); - -/* allocate physical memory */ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, size_t size); +void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj); +void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj, + struct drm_printer *p, unsigned int indent); +struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj); +int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj, struct dma_buf_map *map); +int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma); extern const struct vm_operations_struct drm_gem_cma_vm_ops; -void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent, - const struct drm_gem_object *obj); - -struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_object *obj); -int drm_gem_cma_vmap(struct drm_gem_object *obj, struct dma_buf_map *map); -int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); - /* * GEM object functions */ /** - * drm_gem_cma_object_free - GEM object function for drm_gem_cma_free_object() + * drm_gem_cma_object_free - GEM object function for drm_gem_cma_free() * @obj: GEM object to free * * This function wraps drm_gem_cma_free_object(). Drivers that employ the CMA helpers @@ -61,7 +56,9 @@ int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); */ static inline void drm_gem_cma_object_free(struct drm_gem_object *obj) { - drm_gem_cma_free_object(obj); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + + drm_gem_cma_free(cma_obj); } /** @@ -76,7 +73,9 @@ static inline void drm_gem_cma_object_free(struct drm_gem_object *obj) static inline void drm_gem_cma_object_print_info(struct drm_printer *p, unsigned int indent, const struct drm_gem_object *obj) { - drm_gem_cma_print_info(p, indent, obj); + const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + + drm_gem_cma_print_info(cma_obj, p, indent); } /** @@ -91,7 +90,9 @@ static inline void drm_gem_cma_object_print_info(struct drm_printer *p, unsigned */ static inline struct sg_table *drm_gem_cma_object_get_sg_table(struct drm_gem_object *obj) { - return drm_gem_cma_get_sg_table(obj); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + + return drm_gem_cma_get_sg_table(cma_obj); } /* @@ -107,7 +108,9 @@ static inline struct sg_table *drm_gem_cma_object_get_sg_table(struct drm_gem_ob */ static inline int drm_gem_cma_object_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) { - return drm_gem_cma_vmap(obj, map); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + + return drm_gem_cma_vmap(cma_obj, map); } /** @@ -123,7 +126,9 @@ static inline int drm_gem_cma_object_vmap(struct drm_gem_object *obj, struct dma */ static inline int drm_gem_cma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { - return drm_gem_cma_mmap(obj, vma); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + + return drm_gem_cma_mmap(cma_obj, vma); } /* -- cgit v1.2.3 From c47160d8edcdb4d9fb2b333569a3fc13fca5db43 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Sat, 6 Nov 2021 20:35:08 +0100 Subject: drm/mipi-dbi: Remove dependency on GEM CMA helper library The MIPI DBI helpers access struct drm_gem_cma_object.vaddr in a few places. Replace all instances with the correct generic GEM functions. Use drm_gem_fb_vmap() for mapping a framebuffer's GEM objects and drm_gem_fb_vunmap() for unmapping them. This removes the dependency on CMA helpers within MIPI DBI. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211106193509.17472-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index b75403f3251a..ded8968b3e8a 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -15,9 +15,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -200,13 +201,19 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_rect *clip, bool swap) { struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem); - void *src = cma_obj->vaddr; + struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; + void *src; int ret; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) return ret; + src = data[0].vaddr; /* TODO: Use mapping abstraction properly */ + + ret = drm_gem_fb_vmap(fb, map, data); + if (ret) + goto out_drm_gem_fb_end_cpu_access; switch (fb->format->format) { case DRM_FORMAT_RGB565: @@ -221,9 +228,11 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, default: drm_err_once(fb->dev, "Format is not supported: %p4cc\n", &fb->format->format); - return -EINVAL; + ret = -EINVAL; } + drm_gem_fb_vunmap(fb, map); +out_drm_gem_fb_end_cpu_access: drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); return ret; @@ -249,8 +258,8 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev, static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem); + struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; @@ -266,6 +275,10 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) if (!drm_dev_enter(fb->dev, &idx)) return; + ret = drm_gem_fb_vmap(fb, map, data); + if (ret) + goto err_drm_dev_exit; + full = width == fb->width && height == fb->height; DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); @@ -277,7 +290,7 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) if (ret) goto err_msg; } else { - tr = cma_obj->vaddr; + tr = data[0].vaddr; /* TODO: Use mapping abstraction properly */ } mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1, @@ -289,6 +302,9 @@ err_msg: if (ret) drm_err_once(fb->dev, "Failed to update display %d\n", ret); + drm_gem_fb_vunmap(fb, map); + +err_drm_dev_exit: drm_dev_exit(idx); } @@ -1117,8 +1133,8 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, /* * Even though it's not the SPI device that does DMA (the master does), - * the dma mask is necessary for the dma_alloc_wc() in - * drm_gem_cma_create(). The dma_addr returned will be a physical + * the dma mask is necessary for the dma_alloc_wc() in the GEM code + * (e.g., drm_gem_cma_create()). The dma_addr returned will be a physical * address which might be different from the bus address, but this is * not a problem since the address will not be used. * The virtual address is used in the transfer and the SPI core -- cgit v1.2.3 From 09717af7d13d63df141ae6e71686289989d17efd Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Sat, 6 Nov 2021 20:35:09 +0100 Subject: drm: Remove CONFIG_DRM_KMS_CMA_HELPER option Link drm_fb_cma_helper.o into drm_cma_helper.ko if CONFIG_DRM_KMS_HELPER has been set. Remove CONFIG_DRM_KMS_CMA_HELPER config option. Selecting KMS helpers and CMA will now automatically enable CMA KMS helpers. Some drivers' Kconfig files did not correctly select KMS or CMA helpers. Fix this as part of the change. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211106193509.17472-3-tzimmermann@suse.de --- drivers/gpu/drm/Kconfig | 7 ------- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/arm/Kconfig | 2 -- drivers/gpu/drm/arm/display/Kconfig | 1 - drivers/gpu/drm/aspeed/Kconfig | 1 - drivers/gpu/drm/atmel-hlcdc/Kconfig | 1 - drivers/gpu/drm/fsl-dcu/Kconfig | 1 - drivers/gpu/drm/hisilicon/kirin/Kconfig | 1 - drivers/gpu/drm/imx/Kconfig | 2 +- drivers/gpu/drm/imx/dcss/Kconfig | 2 +- drivers/gpu/drm/ingenic/Kconfig | 1 - drivers/gpu/drm/kmb/Kconfig | 1 - drivers/gpu/drm/mcde/Kconfig | 1 - drivers/gpu/drm/meson/Kconfig | 1 - drivers/gpu/drm/mxsfb/Kconfig | 2 +- drivers/gpu/drm/panel/Kconfig | 2 +- drivers/gpu/drm/pl111/Kconfig | 1 - drivers/gpu/drm/rcar-du/Kconfig | 1 - drivers/gpu/drm/shmobile/Kconfig | 1 - drivers/gpu/drm/sti/Kconfig | 1 - drivers/gpu/drm/stm/Kconfig | 1 - drivers/gpu/drm/sun4i/Kconfig | 1 - drivers/gpu/drm/tidss/Kconfig | 1 - drivers/gpu/drm/tilcdc/Kconfig | 1 - drivers/gpu/drm/tiny/Kconfig | 20 ++++++++++---------- drivers/gpu/drm/tve200/Kconfig | 1 - drivers/gpu/drm/vc4/Kconfig | 1 - drivers/gpu/drm/xlnx/Kconfig | 1 - 28 files changed, 15 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ae29fcba9e19..b2148919b593 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -217,13 +217,6 @@ config DRM_GEM_CMA_HELPER help Choose this if you need the GEM CMA helper functions -config DRM_KMS_CMA_HELPER - bool - depends on DRM - select DRM_GEM_CMA_HELPER - help - Choose this if you need the KMS CMA helper functions - config DRM_GEM_SHMEM_HELPER tristate depends on DRM && MMU diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9dbf91399343..5b49ede0a134 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o drm_cma_helper-y := drm_gem_cma_helper.o +drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o @@ -60,7 +61,6 @@ drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o -drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index 3a9e966e0e78..58a242871b28 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -6,7 +6,6 @@ config DRM_HDLCD depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER help Choose this option if you have an ARM High Definition Colour LCD controller. @@ -27,7 +26,6 @@ config DRM_MALI_DISPLAY depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VIDEOMODE_HELPERS help diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig index cec0639e3aa1..e91598b60781 100644 --- a/drivers/gpu/drm/arm/display/Kconfig +++ b/drivers/gpu/drm/arm/display/Kconfig @@ -4,7 +4,6 @@ config DRM_KOMEDA depends on DRM && OF depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VIDEOMODE_HELPERS help diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig index 5e95bcea43e9..36c4a7e86981 100644 --- a/drivers/gpu/drm/aspeed/Kconfig +++ b/drivers/gpu/drm/aspeed/Kconfig @@ -5,7 +5,6 @@ config DRM_ASPEED_GFX depends on (COMPILE_TEST || ARCH_ASPEED) depends on MMU select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DMA_CMA if HAVE_DMA_CONTIGUOUS select CMA if HAVE_DMA_CONTIGUOUS select MFD_SYSCON diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig index 5f67f001553b..8ae679f1a518 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Kconfig +++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig @@ -4,7 +4,6 @@ config DRM_ATMEL_HLCDC depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_PANEL help Choose this option if you have an ATMEL SoC with an HLCDC display diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig index d7dd8ba90e3a..2a13ea5c8539 100644 --- a/drivers/gpu/drm/fsl-dcu/Kconfig +++ b/drivers/gpu/drm/fsl-dcu/Kconfig @@ -4,7 +4,6 @@ config DRM_FSL_DCU depends on DRM && OF && ARM && COMMON_CLK select BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_PANEL select REGMAP_MMIO select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig index 290553e2f6b4..b770f7662830 100644 --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig @@ -4,7 +4,6 @@ config DRM_HISI_KIRIN depends on DRM && OF && ARM64 select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER select DRM_MIPI_DSI help Choose this option if you have a hisilicon Kirin chipsets(hi6220). diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index b5fa0e45a839..bb9738c7c825 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -4,7 +4,7 @@ config DRM_IMX select DRM_KMS_HELPER select VIDEOMODE_HELPERS select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER + select DRM_KMS_HELPER depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST) depends on IMX_IPUV3_CORE help diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 2b17a964ff05..7374f1952762 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -1,7 +1,7 @@ config DRM_IMX_DCSS tristate "i.MX8MQ DCSS" select IMX_IRQSTEER - select DRM_KMS_CMA_HELPER + select DRM_KMS_HELPER select VIDEOMODE_HELPERS depends on DRM && ARCH_MXC && ARM64 help diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig index 3b57f8be007c..001f59fb06d5 100644 --- a/drivers/gpu/drm/ingenic/Kconfig +++ b/drivers/gpu/drm/ingenic/Kconfig @@ -8,7 +8,6 @@ config DRM_INGENIC select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help diff --git a/drivers/gpu/drm/kmb/Kconfig b/drivers/gpu/drm/kmb/Kconfig index bc4cb5e1cd8a..5fdd43dad507 100644 --- a/drivers/gpu/drm/kmb/Kconfig +++ b/drivers/gpu/drm/kmb/Kconfig @@ -3,7 +3,6 @@ config DRM_KMB_DISPLAY depends on DRM depends on ARCH_KEEMBAY || COMPILE_TEST select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select DRM_MIPI_DSI help diff --git a/drivers/gpu/drm/mcde/Kconfig b/drivers/gpu/drm/mcde/Kconfig index 71c689b573c9..d0bf1bc8da3f 100644 --- a/drivers/gpu/drm/mcde/Kconfig +++ b/drivers/gpu/drm/mcde/Kconfig @@ -10,7 +10,6 @@ config DRM_MCDE select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig index a4e1ed96e5e8..6c70fc3214af 100644 --- a/drivers/gpu/drm/meson/Kconfig +++ b/drivers/gpu/drm/meson/Kconfig @@ -4,7 +4,6 @@ config DRM_MESON depends on DRM && OF && (ARM || ARM64) depends on ARCH_MESON || COMPILE_TEST select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select DRM_DISPLAY_CONNECTOR select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index ee22cd25d3e3..987170e16ebd 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -10,7 +10,7 @@ config DRM_MXSFB depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE help diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7770b1802291..434c2861bb40 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -152,7 +152,7 @@ config DRM_PANEL_ILITEK_ILI9341 tristate "Ilitek ILI9341 240x320 QVGA panels" depends on OF && SPI depends on DRM_KMS_HELPER - depends on DRM_KMS_CMA_HELPER + depends on DRM_GEM_CMA_HELPER depends on BACKLIGHT_CLASS_DEVICE select DRM_MIPI_DBI help diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index 3aae387a96af..91ee05b01303 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -6,7 +6,6 @@ config DRM_PL111 depends on VEXPRESS_CONFIG || VEXPRESS_CONFIG=n depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select DRM_BRIDGE select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index b47e74421e34..71a4611e1557 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -7,7 +7,6 @@ config DRM_RCAR_DU imply DRM_RCAR_CMM imply DRM_RCAR_LVDS select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VIDEOMODE_HELPERS help diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/shmobile/Kconfig index e2a6c82c8252..288b838a904a 100644 --- a/drivers/gpu/drm/shmobile/Kconfig +++ b/drivers/gpu/drm/shmobile/Kconfig @@ -5,7 +5,6 @@ config DRM_SHMOBILE depends on ARCH_SHMOBILE || COMPILE_TEST select BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER help Choose this option if you have an SH Mobile chipset. diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index d0cfdd36b38f..246a94afbe74 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -5,7 +5,6 @@ config DRM_STI select RESET_CONTROLLER select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER select DRM_PANEL select FW_LOADER select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig index b7d66915a2be..e0379488cd0d 100644 --- a/drivers/gpu/drm/stm/Kconfig +++ b/drivers/gpu/drm/stm/Kconfig @@ -4,7 +4,6 @@ config DRM_STM depends on DRM && (ARCH_STM32 || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS select FB_PROVIDE_GET_FB_UNMAPPED_AREA if FB diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 5755f0432e77..92651f6a9e7d 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -5,7 +5,6 @@ config DRM_SUN4I depends on ARCH_SUNXI || COMPILE_TEST select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_PANEL select REGMAP_MMIO select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/tidss/Kconfig b/drivers/gpu/drm/tidss/Kconfig index f790a5215302..bc4fa59b6fa9 100644 --- a/drivers/gpu/drm/tidss/Kconfig +++ b/drivers/gpu/drm/tidss/Kconfig @@ -3,7 +3,6 @@ config DRM_TIDSS depends on DRM && OF depends on ARM || ARM64 || COMPILE_TEST select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER help The TI Keystone family SoCs introduced a new generation of diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index 9f505a149990..e315591eb36b 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -3,7 +3,6 @@ config DRM_TILCDC tristate "DRM Support for TI LCDC Display Controller" depends on DRM && OF && ARM select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select DRM_BRIDGE select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 4ca309f80dee..712e0004e96e 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -3,7 +3,7 @@ config DRM_ARCPGU tristate "ARC PGU" depends on DRM && OF - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER help Choose this option if you have an ARC PGU controller. @@ -71,7 +71,7 @@ config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -84,7 +84,7 @@ config TINYDRM_ILI9163 tristate "DRM support for ILI9163 display panels" depends on DRM && SPI select BACKLIGHT_CLASS_DEVICE - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DBI help @@ -97,7 +97,7 @@ config TINYDRM_ILI9225 tristate "DRM support for ILI9225 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI help DRM driver for the following Ilitek ILI9225 panels: @@ -109,7 +109,7 @@ config TINYDRM_ILI9341 tristate "DRM support for ILI9341 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -122,7 +122,7 @@ config TINYDRM_ILI9486 tristate "DRM support for ILI9486 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -136,7 +136,7 @@ config TINYDRM_MI0283QT tristate "DRM support for MI0283QT" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help @@ -147,7 +147,7 @@ config TINYDRM_REPAPER tristate "DRM support for Pervasive Displays RePaper panels (V231)" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER help DRM driver for the following Pervasive Displays panels: 1.44" TFT EPD Panel (E1144CS021) @@ -161,7 +161,7 @@ config TINYDRM_ST7586 tristate "DRM support for Sitronix ST7586 display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI help DRM driver for the following Sitronix ST7586 panels: @@ -173,7 +173,7 @@ config TINYDRM_ST7735R tristate "DRM support for Sitronix ST7715R/ST7735R display panels" depends on DRM && SPI select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER select DRM_MIPI_DBI select BACKLIGHT_CLASS_DEVICE help diff --git a/drivers/gpu/drm/tve200/Kconfig b/drivers/gpu/drm/tve200/Kconfig index e2d163c74ed6..47a7dbe6c114 100644 --- a/drivers/gpu/drm/tve200/Kconfig +++ b/drivers/gpu/drm/tve200/Kconfig @@ -8,7 +8,6 @@ config DRM_TVE200 select DRM_BRIDGE select DRM_PANEL_BRIDGE select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 345a5570a3da..de3424fed2fc 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -6,7 +6,6 @@ config DRM_VC4 depends on SND && SND_SOC depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select DRM_PANEL_BRIDGE select SND_PCM diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig index c3d08269faa9..d8d38d86d5c6 100644 --- a/drivers/gpu/drm/xlnx/Kconfig +++ b/drivers/gpu/drm/xlnx/Kconfig @@ -7,7 +7,6 @@ config DRM_ZYNQMP_DPSUB depends on XILINX_ZYNQMP_DPDMA select DMA_ENGINE select DRM_GEM_CMA_HELPER - select DRM_KMS_CMA_HELPER select DRM_KMS_HELPER select GENERIC_PHY help -- cgit v1.2.3 From 19cf41b64e3b150cf64fa01dec13f20dc86d95b2 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 16 Nov 2021 18:07:24 -0800 Subject: lontium-lt9611: check a different register bit for HDMI sensing It has been observed that with certain monitors such as the HP Z27n, the register 0x825e reads a value of 0x79 when the HDMI cable is connected and 0x78 when it is disconnected, i.e. bit 0 appears to correspond to the HDMI connection status and bit 2 is never set. Therefore, change the driver to check bit 0 instead of bit 2. Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/I7e76411127e1ce4988a3f6d0c8ba5f1c3d880c23 Reviewed-by: Vinod Koul Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20211117020724.2647769-1-pcc@google.com --- drivers/gpu/drm/bridge/lontium-lt9611.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index d2f45a0f79c8..dafb1b47c15f 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -586,7 +586,7 @@ lt9611_connector_detect(struct drm_connector *connector, bool force) int connected = 0; regmap_read(lt9611->regmap, 0x825e, ®_val); - connected = (reg_val & BIT(2)); + connected = (reg_val & BIT(0)); lt9611->status = connected ? connector_status_connected : connector_status_disconnected; @@ -892,7 +892,7 @@ static enum drm_connector_status lt9611_bridge_detect(struct drm_bridge *bridge) int connected; regmap_read(lt9611->regmap, 0x825e, ®_val); - connected = reg_val & BIT(2); + connected = reg_val & BIT(0); lt9611->status = connected ? connector_status_connected : connector_status_disconnected; -- cgit v1.2.3 From 86baad1941702aa9b6fb44d6f150a34e9e4e1fae Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 24 Sep 2021 10:04:00 +0200 Subject: drm/qxl: use iterator instead of dma_resv_shared_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not sure why it is useful to know the number of fences in the reservation object, but we try to avoid exposing the dma_resv_shared_list() function. So use the iterator instead. If more information is desired we could use dma_resv_describe() as well. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211129120659.1815-5-christian.koenig@amd.com --- drivers/gpu/drm/qxl/qxl_debugfs.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 1f9a59601bb1..6a36b0fd845c 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -57,13 +57,16 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data) struct qxl_bo *bo; list_for_each_entry(bo, &qdev->gem.objects, list) { - struct dma_resv_list *fobj; - int rel; - - rcu_read_lock(); - fobj = dma_resv_shared_list(bo->tbo.base.resv); - rel = fobj ? fobj->shared_count : 0; - rcu_read_unlock(); + struct dma_resv_iter cursor; + struct dma_fence *fence; + int rel = 0; + + dma_resv_iter_begin(&cursor, bo->tbo.base.resv, true); + dma_resv_for_each_fence_unlocked(&cursor, fence) { + if (dma_resv_iter_is_restarted(&cursor)) + rel = 0; + ++rel; + } seq_printf(m, "size %ld, pc %d, num releases %d\n", (unsigned long)bo->tbo.base.size, -- cgit v1.2.3 From f7fd7814f34c97a6c3388b25db18643309cff43c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 21 Oct 2021 12:35:40 +0200 Subject: drm/i915: Remove dma_resv_prune MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The signaled bit is already used for quick testing if a fence is signaled. Signed-off-by: Maarten Lankhorst Acked-by: Christian König Link: https://patchwork.freedesktop.org/patch/460722/ Signed-off-by: Christian König --- drivers/gpu/drm/i915/Makefile | 1 - drivers/gpu/drm/i915/dma_resv_utils.c | 17 ----------------- drivers/gpu/drm/i915/dma_resv_utils.h | 13 ------------- drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 3 --- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 8 -------- 5 files changed, 42 deletions(-) delete mode 100644 drivers/gpu/drm/i915/dma_resv_utils.c delete mode 100644 drivers/gpu/drm/i915/dma_resv_utils.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 660bb03de6fc..5c1af130cb6d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -60,7 +60,6 @@ i915-y += i915_drv.o \ # core library code i915-y += \ - dma_resv_utils.o \ i915_memcpy.o \ i915_mm.o \ i915_sw_fence.o \ diff --git a/drivers/gpu/drm/i915/dma_resv_utils.c b/drivers/gpu/drm/i915/dma_resv_utils.c deleted file mode 100644 index 7df91b7e4ca8..000000000000 --- a/drivers/gpu/drm/i915/dma_resv_utils.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2020 Intel Corporation - */ - -#include - -#include "dma_resv_utils.h" - -void dma_resv_prune(struct dma_resv *resv) -{ - if (dma_resv_trylock(resv)) { - if (dma_resv_test_signaled(resv, true)) - dma_resv_add_excl_fence(resv, NULL); - dma_resv_unlock(resv); - } -} diff --git a/drivers/gpu/drm/i915/dma_resv_utils.h b/drivers/gpu/drm/i915/dma_resv_utils.h deleted file mode 100644 index b9d8fb5f8367..000000000000 --- a/drivers/gpu/drm/i915/dma_resv_utils.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2020 Intel Corporation - */ - -#ifndef DMA_RESV_UTILS_H -#define DMA_RESV_UTILS_H - -struct dma_resv; - -void dma_resv_prune(struct dma_resv *resv); - -#endif /* DMA_RESV_UTILS_H */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index 5ab136ffdeb2..af3eb7fd951d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -15,7 +15,6 @@ #include "gt/intel_gt_requests.h" -#include "dma_resv_utils.h" #include "i915_trace.h" static bool swap_available(void) @@ -229,8 +228,6 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, i915_gem_object_unlock(obj); } - dma_resv_prune(obj->base.resv); - scanned += obj->base.size >> PAGE_SHIFT; skip: i915_gem_object_put(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index f11325484110..cd149aa99364 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -10,7 +10,6 @@ #include "gt/intel_engine.h" -#include "dma_resv_utils.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" @@ -52,13 +51,6 @@ i915_gem_object_wait_reservation(struct dma_resv *resv, } dma_resv_iter_end(&cursor); - /* - * Opportunistically prune the fences iff we know they have *all* been - * signaled. - */ - if (timeout > 0) - dma_resv_prune(resv); - return ret; } -- cgit v1.2.3 From f8be2c5971f48dacbd0e6daa44184dbb6f283dc4 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 26 Nov 2021 17:11:21 +0100 Subject: drm/ttm: stop pruning fences after wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is just abusing internals of the dma_resv object. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211129120659.1815-3-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e4a20a3a5d16..fc124457ba2f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1086,7 +1086,6 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, if (timeout == 0) return -EBUSY; - dma_resv_add_excl_fence(bo->base.resv, NULL); return 0; } EXPORT_SYMBOL(ttm_bo_wait); -- cgit v1.2.3 From c99907c723c6f3f6cae63201ddfac610be13f997 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 11 Nov 2021 10:46:46 +0100 Subject: dma-buf: make fence mandatory for dma_resv_add_excl_fence v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling dma_resv_add_excl_fence() with the fence as NULL and expecting that that this frees up the fences is simply abuse of the internals of the dma_resv object. v2: drop the fence pruning completely. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20211129120659.1815-4-christian.koenig@amd.com --- drivers/dma-buf/dma-resv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index ff3c0558b3b8..4deea75c0b9c 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -305,8 +305,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) if (old) i = old->shared_count; - if (fence) - dma_fence_get(fence); + dma_fence_get(fence); write_seqcount_begin(&obj->seq); /* write_seqcount_begin provides the necessary memory barrier */ -- cgit v1.2.3 From 826c387d015247df396a91eadbaca94f0394853c Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 5 Nov 2021 15:38:42 -0400 Subject: drm/vmwgfx: Remove the deprecated lower mem limit TTM during the transition to the new page allocator lost the ability to constrain the allocations via the lower_mem_limit. The code has been unused since the change: 256dd44bd897 ("drm/ttm: nuke old page allocator") and there's no reason to keep it. Fixes: 256dd44bd897 ("drm/ttm: nuke old page allocator") Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20211105193845.258816-2-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/ttm_memory.c | 99 +------------------------------------ drivers/gpu/drm/vmwgfx/ttm_memory.h | 6 +-- 2 files changed, 2 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.c b/drivers/gpu/drm/vmwgfx/ttm_memory.c index 7f7fe35fc21d..326d2d177c8b 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_memory.c +++ b/drivers/gpu/drm/vmwgfx/ttm_memory.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -173,69 +172,7 @@ static struct kobj_type ttm_mem_zone_kobj_type = { .sysfs_ops = &ttm_mem_zone_ops, .default_attrs = ttm_mem_zone_attrs, }; - -static struct attribute ttm_mem_global_lower_mem_limit = { - .name = "lower_mem_limit", - .mode = S_IRUGO | S_IWUSR -}; - -static ssize_t ttm_mem_global_show(struct kobject *kobj, - struct attribute *attr, - char *buffer) -{ - struct ttm_mem_global *glob = - container_of(kobj, struct ttm_mem_global, kobj); - uint64_t val = 0; - - spin_lock(&glob->lock); - val = glob->lower_mem_limit; - spin_unlock(&glob->lock); - /* convert from number of pages to KB */ - val <<= (PAGE_SHIFT - 10); - return snprintf(buffer, PAGE_SIZE, "%llu\n", - (unsigned long long) val); -} - -static ssize_t ttm_mem_global_store(struct kobject *kobj, - struct attribute *attr, - const char *buffer, - size_t size) -{ - int chars; - uint64_t val64; - unsigned long val; - struct ttm_mem_global *glob = - container_of(kobj, struct ttm_mem_global, kobj); - - chars = sscanf(buffer, "%lu", &val); - if (chars == 0) - return size; - - val64 = val; - /* convert from KB to number of pages */ - val64 >>= (PAGE_SHIFT - 10); - - spin_lock(&glob->lock); - glob->lower_mem_limit = val64; - spin_unlock(&glob->lock); - - return size; -} - -static struct attribute *ttm_mem_global_attrs[] = { - &ttm_mem_global_lower_mem_limit, - NULL -}; - -static const struct sysfs_ops ttm_mem_global_ops = { - .show = &ttm_mem_global_show, - .store = &ttm_mem_global_store, -}; - -static struct kobj_type ttm_mem_glob_kobj_type = { - .sysfs_ops = &ttm_mem_global_ops, - .default_attrs = ttm_mem_global_attrs, -}; +static struct kobj_type ttm_mem_glob_kobj_type = {0}; static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob, bool from_wq, uint64_t extra) @@ -435,11 +372,6 @@ int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev) si_meminfo(&si); - spin_lock(&glob->lock); - /* set it as 0 by default to keep original behavior of OOM */ - glob->lower_mem_limit = 0; - spin_unlock(&glob->lock); - ret = ttm_mem_init_kernel_zone(glob, &si); if (unlikely(ret != 0)) goto out_no_zone; @@ -526,35 +458,6 @@ void ttm_mem_global_free(struct ttm_mem_global *glob, } EXPORT_SYMBOL(ttm_mem_global_free); -/* - * check if the available mem is under lower memory limit - * - * a. if no swap disk at all or free swap space is under swap_mem_limit - * but available system mem is bigger than sys_mem_limit, allow TTM - * allocation; - * - * b. if the available system mem is less than sys_mem_limit but free - * swap disk is bigger than swap_mem_limit, allow TTM allocation. - */ -bool -ttm_check_under_lowerlimit(struct ttm_mem_global *glob, - uint64_t num_pages, - struct ttm_operation_ctx *ctx) -{ - int64_t available; - - /* We allow over commit during suspend */ - if (ctx->force_alloc) - return false; - - available = get_nr_swap_pages() + si_mem_available(); - available -= num_pages; - if (available < glob->lower_mem_limit) - return true; - - return false; -} - static int ttm_mem_global_reserve(struct ttm_mem_global *glob, struct ttm_mem_zone *single_zone, uint64_t amount, bool reserve) diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.h b/drivers/gpu/drm/vmwgfx/ttm_memory.h index c50dba774485..7b0d617ebcb1 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_memory.h +++ b/drivers/gpu/drm/vmwgfx/ttm_memory.h @@ -50,8 +50,6 @@ * @work: The workqueue callback for the shrink queue. * @lock: Lock to protect the @shrink - and the memory accounting members, * that is, essentially the whole structure with some exceptions. - * @lower_mem_limit: include lower limit of swap space and lower limit of - * system memory. * @zones: Array of pointers to accounting zones. * @num_zones: Number of populated entries in the @zones array. * @zone_kernel: Pointer to the kernel zone. @@ -69,7 +67,6 @@ extern struct ttm_mem_global { struct workqueue_struct *swap_queue; struct work_struct work; spinlock_t lock; - uint64_t lower_mem_limit; struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES]; unsigned int num_zones; struct ttm_mem_zone *zone_kernel; @@ -91,6 +88,5 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page, uint64_t size); size_t ttm_round_pot(size_t size); -bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, uint64_t num_pages, - struct ttm_operation_ctx *ctx); + #endif -- cgit v1.2.3 From 28b5f3b6121b7db2a44be499cfca0b6b801588b6 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 5 Nov 2021 15:38:43 -0400 Subject: drm/vmwgfx: Release ttm memory if probe fails The ttm mem global state was leaking if the vmwgfx driver load failed. In case of a driver load failure we have to make sure we also release the ttm mem global state. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20211105193845.258816-3-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index d10933a16bc4..279769a9fce6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1616,34 +1616,40 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver); if (ret) - return ret; + goto out_error; ret = pcim_enable_device(pdev); if (ret) - return ret; + goto out_error; vmw = devm_drm_dev_alloc(&pdev->dev, &driver, struct vmw_private, drm); - if (IS_ERR(vmw)) - return PTR_ERR(vmw); + if (IS_ERR(vmw)) { + ret = PTR_ERR(vmw); + goto out_error; + } pci_set_drvdata(pdev, &vmw->drm); ret = ttm_mem_global_init(&ttm_mem_glob, &pdev->dev); if (ret) - return ret; + goto out_error; ret = vmw_driver_load(vmw, ent->device); if (ret) - return ret; + goto out_release; ret = drm_dev_register(&vmw->drm, 0); - if (ret) { - vmw_driver_unload(&vmw->drm); - return ret; - } + if (ret) + goto out_unload; return 0; +out_unload: + vmw_driver_unload(&vmw->drm); +out_release: + ttm_mem_global_release(&ttm_mem_glob); +out_error: + return ret; } static int __init vmwgfx_init(void) -- cgit v1.2.3 From c451af78f301ff5156998d571c37cab329c10051 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 5 Nov 2021 15:38:44 -0400 Subject: drm/vmwgfx: Fail to initialize on broken configs Some of our hosts have a bug where rescaning a pci bus results in stale fifo memory being mapped on the host. This makes any fifo communication impossible resulting in various kernel crashes. Instead of unexpectedly crashing, predictably fail to load the driver which will preserve the system. Fixes: fb1d9738ca05 ("drm/vmwgfx: Add DRM driver for VMware Virtual GPU") Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20211105193845.258816-4-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c index 67db472d3493..a3bfbb6c3e14 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c @@ -145,6 +145,13 @@ struct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv) (unsigned int) max, (unsigned int) min, (unsigned int) fifo->capabilities); + + if (unlikely(min >= max)) { + drm_warn(&dev_priv->drm, + "FIFO memory is not usable. Driver failed to initialize."); + return ERR_PTR(-ENXIO); + } + return fifo; } -- cgit v1.2.3 From f6be23264bbac88d1e2bb39658e1b8a397e3f46d Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 5 Nov 2021 15:38:45 -0400 Subject: drm/vmwgfx: Introduce a new placement for MOB page tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For larger (bigger than a page) and noncontiguous mobs we have to create page tables that allow the host to find the memory. Those page tables just used regular system memory. Unfortunately in TTM those BO's are not allowed to be busy thus can't be fenced and we have to fence those bo's because we don't want to destroy the page tables while the host is still executing the command buffers which might be accessing them. To solve it we introduce a new placement VMW_PL_SYSTEM which is very similar to TTM_PL_SYSTEM except that it allows fencing. This fixes kernel oops'es during unloading of the driver (and pci hot remove/add) which were caused by busy BO's in TTM_PL_SYSTEM being present in the delayed deletion list in TTM (TTM_PL_SYSTEM manager is destroyed before the delayed deletions are executed) Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Cc: Christian König Cc: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20211105193845.258816-5-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 14 +++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 12 +++- drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c | 90 ++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 58 ++++++++--------- 5 files changed, 138 insertions(+), 38 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index e6a6a1edb058..e02780648a95 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -9,7 +9,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_d vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \ vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \ - vmwgfx_devcaps.o ttm_object.o ttm_memory.o + vmwgfx_devcaps.o ttm_object.o ttm_memory.o vmwgfx_system_manager.o vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o vmwgfx-$(CONFIG_TRANSPARENT_HUGEPAGE) += vmwgfx_thp.o diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 279769a9fce6..2846a0009633 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1070,6 +1070,12 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) "3D will be disabled.\n"); dev_priv->has_mob = false; } + if (vmw_sys_man_init(dev_priv) != 0) { + drm_info(&dev_priv->drm, + "No MOB page table memory available. " + "3D will be disabled.\n"); + dev_priv->has_mob = false; + } } if (dev_priv->has_mob && (dev_priv->capabilities & SVGA_CAP_DX)) { @@ -1120,8 +1126,10 @@ out_no_fifo: vmw_overlay_close(dev_priv); vmw_kms_close(dev_priv); out_no_kms: - if (dev_priv->has_mob) + if (dev_priv->has_mob) { vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); + vmw_sys_man_fini(dev_priv); + } if (dev_priv->has_gmr) vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); vmw_devcaps_destroy(dev_priv); @@ -1171,8 +1179,10 @@ static void vmw_driver_unload(struct drm_device *dev) vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); vmw_release_device_early(dev_priv); - if (dev_priv->has_mob) + if (dev_priv->has_mob) { vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); + vmw_sys_man_fini(dev_priv); + } vmw_devcaps_destroy(dev_priv); vmw_vram_manager_fini(dev_priv); ttm_device_fini(&dev_priv->bdev); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 530ac1b557f9..fbbbcdbe41e3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -82,8 +82,9 @@ VMWGFX_NUM_GB_SURFACE +\ VMWGFX_NUM_GB_SCREEN_TARGET) -#define VMW_PL_GMR (TTM_PL_PRIV + 0) -#define VMW_PL_MOB (TTM_PL_PRIV + 1) +#define VMW_PL_GMR (TTM_PL_PRIV + 0) +#define VMW_PL_MOB (TTM_PL_PRIV + 1) +#define VMW_PL_SYSTEM (TTM_PL_PRIV + 2) #define VMW_RES_CONTEXT ttm_driver_type0 #define VMW_RES_SURFACE ttm_driver_type1 @@ -1039,7 +1040,6 @@ extern struct ttm_placement vmw_vram_placement; extern struct ttm_placement vmw_vram_sys_placement; extern struct ttm_placement vmw_vram_gmr_placement; extern struct ttm_placement vmw_sys_placement; -extern struct ttm_placement vmw_evictable_placement; extern struct ttm_placement vmw_srf_placement; extern struct ttm_placement vmw_mob_placement; extern struct ttm_placement vmw_nonfixed_placement; @@ -1251,6 +1251,12 @@ int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); +/** + * System memory manager + */ +int vmw_sys_man_init(struct vmw_private *dev_priv); +void vmw_sys_man_fini(struct vmw_private *dev_priv); + /** * Prime - vmwgfx_prime.c */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c new file mode 100644 index 000000000000..b0005b03a617 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright 2021 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "vmwgfx_drv.h" + +#include +#include +#include +#include +#include + + +static int vmw_sys_man_alloc(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource **res) +{ + *res = kzalloc(sizeof(**res), GFP_KERNEL); + if (!*res) + return -ENOMEM; + + ttm_resource_init(bo, place, *res); + return 0; +} + +static void vmw_sys_man_free(struct ttm_resource_manager *man, + struct ttm_resource *res) +{ + kfree(res); +} + +static const struct ttm_resource_manager_func vmw_sys_manager_func = { + .alloc = vmw_sys_man_alloc, + .free = vmw_sys_man_free, +}; + +int vmw_sys_man_init(struct vmw_private *dev_priv) +{ + struct ttm_device *bdev = &dev_priv->bdev; + struct ttm_resource_manager *man = + kzalloc(sizeof(*man), GFP_KERNEL); + + if (!man) + return -ENOMEM; + + man->use_tt = true; + man->func = &vmw_sys_manager_func; + + ttm_resource_manager_init(man, 0); + ttm_set_driver_manager(bdev, VMW_PL_SYSTEM, man); + ttm_resource_manager_set_used(man, true); + return 0; +} + +void vmw_sys_man_fini(struct vmw_private *dev_priv) +{ + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, + VMW_PL_SYSTEM); + + ttm_resource_manager_evict_all(&dev_priv->bdev, man); + + ttm_resource_manager_set_used(man, false); + ttm_resource_manager_cleanup(man); + + ttm_set_driver_manager(&dev_priv->bdev, VMW_PL_SYSTEM, NULL); + kfree(man); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index e899a936a42a..b15228e7dbeb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -92,6 +92,13 @@ static const struct ttm_place gmr_vram_placement_flags[] = { } }; +static const struct ttm_place vmw_sys_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .mem_type = VMW_PL_SYSTEM, + .flags = 0 +}; + struct ttm_placement vmw_vram_gmr_placement = { .num_placement = 2, .placement = vram_gmr_placement_flags, @@ -113,28 +120,11 @@ struct ttm_placement vmw_sys_placement = { .busy_placement = &sys_placement_flags }; -static const struct ttm_place evictable_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .mem_type = TTM_PL_SYSTEM, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = TTM_PL_VRAM, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = VMW_PL_GMR, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = VMW_PL_MOB, - .flags = 0 - } +struct ttm_placement vmw_pt_sys_placement = { + .num_placement = 1, + .placement = &vmw_sys_placement_flags, + .num_busy_placement = 1, + .busy_placement = &vmw_sys_placement_flags }; static const struct ttm_place nonfixed_placement_flags[] = { @@ -156,13 +146,6 @@ static const struct ttm_place nonfixed_placement_flags[] = { } }; -struct ttm_placement vmw_evictable_placement = { - .num_placement = 4, - .placement = evictable_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - struct ttm_placement vmw_srf_placement = { .num_placement = 1, .num_busy_placement = 2, @@ -484,6 +467,9 @@ static int vmw_ttm_bind(struct ttm_device *bdev, &vmw_be->vsgt, ttm->num_pages, vmw_be->gmr_id); break; + case VMW_PL_SYSTEM: + /* Nothing to be done for a system bind */ + break; default: BUG(); } @@ -507,6 +493,8 @@ static void vmw_ttm_unbind(struct ttm_device *bdev, case VMW_PL_MOB: vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob); break; + case VMW_PL_SYSTEM: + break; default: BUG(); } @@ -624,6 +612,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource * switch (mem->mem_type) { case TTM_PL_SYSTEM: + case VMW_PL_SYSTEM: case VMW_PL_GMR: case VMW_PL_MOB: return 0; @@ -670,6 +659,11 @@ static void vmw_swap_notify(struct ttm_buffer_object *bo) (void) ttm_bo_wait(bo, false, false); } +static bool vmw_memtype_is_system(uint32_t mem_type) +{ + return mem_type == TTM_PL_SYSTEM || mem_type == VMW_PL_SYSTEM; +} + static int vmw_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, @@ -680,7 +674,7 @@ static int vmw_move(struct ttm_buffer_object *bo, struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type); int ret; - if (new_man->use_tt && new_mem->mem_type != TTM_PL_SYSTEM) { + if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) { ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem); if (ret) return ret; @@ -689,7 +683,7 @@ static int vmw_move(struct ttm_buffer_object *bo, vmw_move_notify(bo, bo->resource, new_mem); if (old_man->use_tt && new_man->use_tt) { - if (bo->resource->mem_type == TTM_PL_SYSTEM) { + if (vmw_memtype_is_system(bo->resource->mem_type)) { ttm_bo_move_null(bo, new_mem); return 0; } @@ -736,7 +730,7 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, int ret; ret = vmw_bo_create_kernel(dev_priv, bo_size, - &vmw_sys_placement, + &vmw_pt_sys_placement, &bo); if (unlikely(ret != 0)) return ret; -- cgit v1.2.3 From a85b1cb23091d3112492f30fd92308cf4dcc4fc6 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 5 Nov 2021 15:38:46 -0400 Subject: drm/vmwgfx: Switch the internal BO's to ttm_bo_type_kernel There's never a need to access our internal kernel bo's from user-space. Those objects are used exclusively for internal support to guest backed surfaces (in otable setup and mob page tables) and there's no need to have them be of device type, i.e. mmappable from user-space. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20211105193845.258816-6-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index fd007f1c1776..c97a3d5e90ce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -494,7 +494,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, drm_vma_node_reset(&bo->base.vma_node); ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, size, - ttm_bo_type_device, placement, 0, + ttm_bo_type_kernel, placement, 0, &ctx, NULL, NULL, NULL); if (unlikely(ret)) goto error_account; -- cgit v1.2.3 From 4ff22f487f8c26b99cbe1678344595734c001a39 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 30 Nov 2021 10:52:55 +0100 Subject: drm: Return error codes from struct drm_driver.gem_create_object GEM helper libraries use struct drm_driver.gem_create_object to let drivers override GEM object allocation. On failure, the call returns NULL. Change the semantics to make the calls return a pointer-encoded error. This aligns the callback with its callers. Fixes the ingenic driver, which already returns an error pointer. Also update the callers to handle the involved types more strictly. Signed-off-by: Thomas Zimmermann Reviewed-by: Steven Price Acked-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20211130095255.26710-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_cma_helper.c | 17 ++++++++++------- drivers/gpu/drm/drm_gem_shmem_helper.c | 17 ++++++++++------- drivers/gpu/drm/drm_gem_vram_helper.c | 4 ++-- drivers/gpu/drm/lima/lima_gem.c | 2 +- drivers/gpu/drm/panfrost/panfrost_gem.c | 2 +- drivers/gpu/drm/v3d/v3d_bo.c | 4 ++-- drivers/gpu/drm/vgem/vgem_drv.c | 2 +- drivers/gpu/drm/virtio/virtgpu_object.c | 2 +- include/drm/drm_drv.h | 5 +++-- 9 files changed, 31 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index 5f42e44b2ab3..6f18f143dd30 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -67,18 +67,21 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, bool private) struct drm_gem_object *gem_obj; int ret = 0; - if (drm->driver->gem_create_object) + if (drm->driver->gem_create_object) { gem_obj = drm->driver->gem_create_object(drm, size); - else - gem_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!gem_obj) - return ERR_PTR(-ENOMEM); + if (IS_ERR(gem_obj)) + return ERR_CAST(gem_obj); + cma_obj = to_drm_gem_cma_obj(gem_obj); + } else { + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); + if (!cma_obj) + return ERR_PTR(-ENOMEM); + gem_obj = &cma_obj->base; + } if (!gem_obj->funcs) gem_obj->funcs = &drm_gem_cma_default_funcs; - cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base); - if (private) { drm_gem_private_object_init(drm, gem_obj, size); diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 0eeda1012364..7915047cb041 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -56,14 +56,17 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private) size = PAGE_ALIGN(size); - if (dev->driver->gem_create_object) + if (dev->driver->gem_create_object) { obj = dev->driver->gem_create_object(dev, size); - else - obj = kzalloc(sizeof(*shmem), GFP_KERNEL); - if (!obj) - return ERR_PTR(-ENOMEM); - - shmem = to_drm_gem_shmem_obj(obj); + if (IS_ERR(obj)) + return ERR_CAST(obj); + shmem = to_drm_gem_shmem_obj(obj); + } else { + shmem = kzalloc(sizeof(*shmem), GFP_KERNEL); + if (!shmem) + return ERR_PTR(-ENOMEM); + obj = &shmem->base; + } if (!obj->funcs) obj->funcs = &drm_gem_shmem_funcs; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index bfa386b98134..3f00192215d1 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -197,8 +197,8 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, if (dev->driver->gem_create_object) { gem = dev->driver->gem_create_object(dev, size); - if (!gem) - return ERR_PTR(-ENOMEM); + if (IS_ERR(gem)) + return ERR_CAST(gem); gbo = drm_gem_vram_of_gem(gem); } else { gbo = kzalloc(sizeof(*gbo), GFP_KERNEL); diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c index 2723d333c608..f9a9198ef198 100644 --- a/drivers/gpu/drm/lima/lima_gem.c +++ b/drivers/gpu/drm/lima/lima_gem.c @@ -221,7 +221,7 @@ struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t siz bo = kzalloc(sizeof(*bo), GFP_KERNEL); if (!bo) - return NULL; + return ERR_PTR(-ENOMEM); mutex_init(&bo->lock); INIT_LIST_HEAD(&bo->va); diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 6d9bdb9180cb..ead65f5fa2bc 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -223,7 +223,7 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (!obj) - return NULL; + return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&obj->mappings.list); mutex_init(&obj->mappings.lock); diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c index 0d9af62f69ad..6e3113f419f4 100644 --- a/drivers/gpu/drm/v3d/v3d_bo.c +++ b/drivers/gpu/drm/v3d/v3d_bo.c @@ -70,11 +70,11 @@ struct drm_gem_object *v3d_create_object(struct drm_device *dev, size_t size) struct drm_gem_object *obj; if (size == 0) - return NULL; + return ERR_PTR(-EINVAL); bo = kzalloc(sizeof(*bo), GFP_KERNEL); if (!bo) - return NULL; + return ERR_PTR(-ENOMEM); obj = &bo->base.base; obj->funcs = &v3d_gem_funcs; diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index a87eafa89e9f..c5e3e5457737 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -97,7 +97,7 @@ static struct drm_gem_object *vgem_gem_create_object(struct drm_device *dev, siz obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (!obj) - return NULL; + return ERR_PTR(-ENOMEM); /* * vgem doesn't have any begin/end cpu access ioctls, therefore must use diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 187e10da2f17..baef2c5f2aaf 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -139,7 +139,7 @@ struct drm_gem_object *virtio_gpu_create_object(struct drm_device *dev, shmem = kzalloc(sizeof(*shmem), GFP_KERNEL); if (!shmem) - return NULL; + return ERR_PTR(-ENOMEM); dshmem = &shmem->base.base; dshmem->base.funcs = &virtio_gpu_shmem_funcs; diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index da0c836fe8e1..f6159acb8856 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -291,8 +291,9 @@ struct drm_driver { /** * @gem_create_object: constructor for gem objects * - * Hook for allocating the GEM object struct, for use by the CMA and - * SHMEM GEM helpers. + * Hook for allocating the GEM object struct, for use by the CMA + * and SHMEM GEM helpers. Returns a GEM object on success, or an + * ERR_PTR()-encoded error code otherwise. */ struct drm_gem_object *(*gem_create_object)(struct drm_device *dev, size_t size); -- cgit v1.2.3 From 9c65ab78bfc9e49d10f931f9997e165a10c39734 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Dec 2021 18:46:22 +0100 Subject: drm: fsl-dcu: select CONFIG_DRM_GEM_CMA_HELPER The fsl-dcu driver uses the gem_cma_helper code, but does noto enforce enabling this through Kconfig: arm-linux-gnueabi-ld: drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.o:(.rodata+0x32c): undefined reference to `drm_gem_cma_prime_import_sg_table' arm-linux-gnueabi-ld: drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.o:(.rodata+0x334): undefined reference to `drm_gem_cma_dumb_create' arm-linux-gnueabi-ld: drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.o: in function `fsl_dcu_drm_plane_atomic_update': fsl_dcu_drm_plane.c:(.text+0x144): undefined reference to `drm_fb_cma_get_gem_obj' Add the same 'select' that is used in other such drivers. Fixes: 09717af7d13d ("drm: Remove CONFIG_DRM_KMS_CMA_HELPER option") Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20211204174637.1160725-1-arnd@kernel.org --- drivers/gpu/drm/fsl-dcu/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig index 2a13ea5c8539..e95e96c565ba 100644 --- a/drivers/gpu/drm/fsl-dcu/Kconfig +++ b/drivers/gpu/drm/fsl-dcu/Kconfig @@ -3,6 +3,7 @@ config DRM_FSL_DCU tristate "DRM Support for Freescale DCU" depends on DRM && OF && ARM && COMMON_CLK select BACKLIGHT_CLASS_DEVICE + select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER select DRM_PANEL select REGMAP_MMIO -- cgit v1.2.3 From 8697c410457fbc50169d2c7db4a7eef9b58924a9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Dec 2021 18:46:23 +0100 Subject: drm: aspeed: select CONFIG_DRM_GEM_CMA_HELPER The aspeed driver uses the gem_cma_helper code, but does noto enforce enabling this through Kconfig: x86_64-linux-ld: drivers/gpu/drm/aspeed/aspeed_gfx_drv.o:(.rodata+0x2c8): undefined reference to `drm_gem_cma_prime_import_sg_table' x86_64-linux-ld: drivers/gpu/drm/aspeed/aspeed_gfx_drv.o:(.rodata+0x2d8): undefined reference to `drm_gem_cma_dumb_create' x86_64-linux-ld: drivers/gpu/drm/aspeed/aspeed_gfx_crtc.o: in function `aspeed_gfx_pipe_update': aspeed_gfx_crtc.c:(.text+0xe5): undefined reference to `drm_fb_cma_get_gem_obj' Add the same 'select' that is used in other such drivers. Fixes: 09717af7d13d ("drm: Remove CONFIG_DRM_KMS_CMA_HELPER option") Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20211204174637.1160725-2-arnd@kernel.org --- drivers/gpu/drm/aspeed/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig index 36c4a7e86981..024ccab14f88 100644 --- a/drivers/gpu/drm/aspeed/Kconfig +++ b/drivers/gpu/drm/aspeed/Kconfig @@ -5,6 +5,7 @@ config DRM_ASPEED_GFX depends on (COMPILE_TEST || ARCH_ASPEED) depends on MMU select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER select DMA_CMA if HAVE_DMA_CONTIGUOUS select CMA if HAVE_DMA_CONTIGUOUS select MFD_SYSCON -- cgit v1.2.3 From 24af7c34b290dc0da62349dfb050bb4a8e16c6c1 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Fri, 29 Oct 2021 12:50:13 +0100 Subject: drm/rockchip: use generic fbdev setup The Rockchip fbdev code does not add anything compared to drm_fbdev_generic_setup(); the one custom function for .fb_mmap does the same thing as gem_prime_mmap which is called by the helper. Signed-off-by: John Keeping Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20211029115014.264084-1-john@metanate.com --- drivers/gpu/drm/rockchip/Makefile | 1 - drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 10 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 - drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c | 164 -------------------------- drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h | 24 ---- 5 files changed, 2 insertions(+), 199 deletions(-) delete mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c delete mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index 17a9e7eb2130..1a56f696558c 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -5,7 +5,6 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o -rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 69c699459dce..20d81ae69828 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -26,7 +26,6 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" -#include "rockchip_drm_fbdev.h" #include "rockchip_drm_gem.h" #define DRIVER_NAME "rockchip" @@ -159,10 +158,6 @@ static int rockchip_drm_bind(struct device *dev) drm_mode_config_reset(drm_dev); - ret = rockchip_drm_fbdev_init(drm_dev); - if (ret) - goto err_unbind_all; - /* init kms poll for handling hpd */ drm_kms_helper_poll_init(drm_dev); @@ -170,10 +165,11 @@ static int rockchip_drm_bind(struct device *dev) if (ret) goto err_kms_helper_poll_fini; + drm_fbdev_generic_setup(drm_dev, 32); + return 0; err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); - rockchip_drm_fbdev_fini(drm_dev); err_unbind_all: component_unbind_all(dev, drm_dev); err_iommu_cleanup: @@ -189,7 +185,6 @@ static void rockchip_drm_unbind(struct device *dev) drm_dev_unregister(drm_dev); - rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); drm_atomic_helper_shutdown(drm_dev); @@ -203,7 +198,6 @@ DEFINE_DRM_GEM_FOPS(rockchip_drm_driver_fops); static const struct drm_driver rockchip_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - .lastclose = drm_fb_helper_lastclose, .dumb_create = rockchip_gem_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index aa0909e8edf9..143a48330f84 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -43,8 +43,6 @@ struct rockchip_crtc_state { * @mm_lock: protect drm_mm on multi-threads. */ struct rockchip_drm_private { - struct drm_fb_helper fbdev_helper; - struct drm_gem_object *fbdev_bo; struct iommu_domain *domain; struct mutex mm_lock; struct drm_mm mm; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c deleted file mode 100644 index d8418dd39d0e..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author:Mark Yao - */ - -#include -#include -#include -#include -#include - -#include "rockchip_drm_drv.h" -#include "rockchip_drm_gem.h" -#include "rockchip_drm_fb.h" -#include "rockchip_drm_fbdev.h" - -#define PREFERRED_BPP 32 -#define to_drm_private(x) \ - container_of(x, struct rockchip_drm_private, fbdev_helper) - -static int rockchip_fbdev_mmap(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct drm_fb_helper *helper = info->par; - struct rockchip_drm_private *private = to_drm_private(helper); - - return drm_gem_prime_mmap(private->fbdev_bo, vma); -} - -static const struct fb_ops rockchip_drm_fbdev_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_mmap = rockchip_fbdev_mmap, - .fb_fillrect = drm_fb_helper_cfb_fillrect, - .fb_copyarea = drm_fb_helper_cfb_copyarea, - .fb_imageblit = drm_fb_helper_cfb_imageblit, -}; - -static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct rockchip_drm_private *private = to_drm_private(helper); - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - struct drm_device *dev = helper->dev; - struct rockchip_gem_object *rk_obj; - struct drm_framebuffer *fb; - unsigned int bytes_per_pixel; - unsigned long offset; - struct fb_info *fbi; - size_t size; - int ret; - - bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; - - rk_obj = rockchip_gem_create_object(dev, size, true); - if (IS_ERR(rk_obj)) - return -ENOMEM; - - private->fbdev_bo = &rk_obj->base; - - fbi = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(fbi)) { - DRM_DEV_ERROR(dev->dev, "Failed to create framebuffer info.\n"); - ret = PTR_ERR(fbi); - goto out; - } - - helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd, - private->fbdev_bo); - if (IS_ERR(helper->fb)) { - DRM_DEV_ERROR(dev->dev, - "Failed to allocate DRM framebuffer.\n"); - ret = PTR_ERR(helper->fb); - goto out; - } - - fbi->fbops = &rockchip_drm_fbdev_ops; - - fb = helper->fb; - drm_fb_helper_fill_info(fbi, helper, sizes); - - offset = fbi->var.xoffset * bytes_per_pixel; - offset += fbi->var.yoffset * fb->pitches[0]; - - dev->mode_config.fb_base = 0; - fbi->screen_base = rk_obj->kvaddr + offset; - fbi->screen_size = rk_obj->base.size; - fbi->fix.smem_len = rk_obj->base.size; - - DRM_DEBUG_KMS("FB [%dx%d]-%d kvaddr=%p offset=%ld size=%zu\n", - fb->width, fb->height, fb->format->depth, - rk_obj->kvaddr, - offset, size); - - return 0; - -out: - rockchip_gem_free_object(&rk_obj->base); - return ret; -} - -static const struct drm_fb_helper_funcs rockchip_drm_fb_helper_funcs = { - .fb_probe = rockchip_drm_fbdev_create, -}; - -int rockchip_drm_fbdev_init(struct drm_device *dev) -{ - struct rockchip_drm_private *private = dev->dev_private; - struct drm_fb_helper *helper; - int ret; - - if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) - return -EINVAL; - - helper = &private->fbdev_helper; - - drm_fb_helper_prepare(dev, helper, &rockchip_drm_fb_helper_funcs); - - ret = drm_fb_helper_init(dev, helper); - if (ret < 0) { - DRM_DEV_ERROR(dev->dev, - "Failed to initialize drm fb helper - %d.\n", - ret); - return ret; - } - - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); - if (ret < 0) { - DRM_DEV_ERROR(dev->dev, - "Failed to set initial hw config - %d.\n", - ret); - goto err_drm_fb_helper_fini; - } - - return 0; - -err_drm_fb_helper_fini: - drm_fb_helper_fini(helper); - return ret; -} - -void rockchip_drm_fbdev_fini(struct drm_device *dev) -{ - struct rockchip_drm_private *private = dev->dev_private; - struct drm_fb_helper *helper; - - helper = &private->fbdev_helper; - - drm_fb_helper_unregister_fbi(helper); - - if (helper->fb) - drm_framebuffer_put(helper->fb); - - drm_fb_helper_fini(helper); -} diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h deleted file mode 100644 index 5fb7ac2371a8..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author:Mark Yao - */ - -#ifndef _ROCKCHIP_DRM_FBDEV_H -#define _ROCKCHIP_DRM_FBDEV_H - -#ifdef CONFIG_DRM_FBDEV_EMULATION -int rockchip_drm_fbdev_init(struct drm_device *dev); -void rockchip_drm_fbdev_fini(struct drm_device *dev); -#else -static inline int rockchip_drm_fbdev_init(struct drm_device *dev) -{ - return 0; -} - -static inline void rockchip_drm_fbdev_fini(struct drm_device *dev) -{ -} -#endif - -#endif /* _ROCKCHIP_DRM_FBDEV_H */ -- cgit v1.2.3 From f2ed93a4dc854981b399e884851e966194a18595 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 1 Nov 2021 11:46:22 +0000 Subject: drm/rockchip: pass 0 to drm_fbdev_generic_setup() Allow drm_fbdev_generic_setup() to pick the default bpp value for the framebuffer. This has no functional impact because the default is 32, given that mode_config.preferred_depth is not set for Rockchip. Suggested-by: Thomas Zimmermann Signed-off-by: John Keeping Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20211101114622.813536-1-john@metanate.com --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 20d81ae69828..bec207de4544 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -165,7 +165,7 @@ static int rockchip_drm_bind(struct device *dev) if (ret) goto err_kms_helper_poll_fini; - drm_fbdev_generic_setup(drm_dev, 32); + drm_fbdev_generic_setup(drm_dev, 0); return 0; err_kms_helper_poll_fini: -- cgit v1.2.3 From 42c632b0555ed0500ff26b329e194fe77d2b6123 Mon Sep 17 00:00:00 2001 From: yangcong Date: Wed, 1 Dec 2021 10:32:30 +0800 Subject: drm/panel: Update Boe-tv110c9m and Inx-hj110iz initial code At present, we have enough panel to confirm the effect, update the initial code to achieve the best effect. Such as gamma, Gop timing. They are all minor modifications and doesn't affect the lighting of the panel. a)Boe-tv110c9m panel Optimized touch horizontal grain. b)Inx-hj110iz panel Optimized GOP timing and gamma. Signed-off-by: yangcong Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20211201023230.344976-1-yangcong5@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 108 +++++++++++++++++-------- 1 file changed, 74 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index 529561b4fbbc..5fcbde789ddb 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -84,8 +84,8 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { _INIT_DCS_CMD(0x0D, 0x63), _INIT_DCS_CMD(0x0E, 0x91), _INIT_DCS_CMD(0x0F, 0x73), - _INIT_DCS_CMD(0x95, 0xEB), - _INIT_DCS_CMD(0x96, 0xEB), + _INIT_DCS_CMD(0x95, 0xE6), + _INIT_DCS_CMD(0x96, 0xF0), _INIT_DCS_CMD(0x30, 0x11), _INIT_DCS_CMD(0x6D, 0x66), _INIT_DCS_CMD(0x75, 0xA2), @@ -111,18 +111,18 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0), _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0), _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xF7), + _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0), _INIT_DCS_CMD(0xFF, 0x24), _INIT_DCS_CMD(0xFB, 0x01), @@ -225,6 +225,7 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { _INIT_DCS_CMD(0x7F, 0x3C), _INIT_DCS_CMD(0x82, 0x04), _INIT_DCS_CMD(0x97, 0xC0), + _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00), _INIT_DCS_CMD(0x91, 0x44), _INIT_DCS_CMD(0x92, 0xA9), @@ -332,12 +333,39 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { _INIT_DCS_CMD(0x34, 0x78), _INIT_DCS_CMD(0x35, 0x16), _INIT_DCS_CMD(0xC8, 0x04), - _INIT_DCS_CMD(0xC9, 0x80), + _INIT_DCS_CMD(0xC9, 0x9E), _INIT_DCS_CMD(0xCA, 0x4E), _INIT_DCS_CMD(0xCB, 0x00), - _INIT_DCS_CMD(0xA9, 0x4C), - _INIT_DCS_CMD(0xAA, 0x47), + _INIT_DCS_CMD(0xA9, 0x49), + _INIT_DCS_CMD(0xAA, 0x4B), + _INIT_DCS_CMD(0xAB, 0x48), + _INIT_DCS_CMD(0xAC, 0x43), + _INIT_DCS_CMD(0xAD, 0x40), + _INIT_DCS_CMD(0xAE, 0x50), + _INIT_DCS_CMD(0xAF, 0x44), + _INIT_DCS_CMD(0xB0, 0x54), + _INIT_DCS_CMD(0xB1, 0x4E), + _INIT_DCS_CMD(0xB2, 0x4D), + _INIT_DCS_CMD(0xB3, 0x4C), + _INIT_DCS_CMD(0xB4, 0x41), + _INIT_DCS_CMD(0xB5, 0x47), + _INIT_DCS_CMD(0xB6, 0x53), + _INIT_DCS_CMD(0xB7, 0x3E), + _INIT_DCS_CMD(0xB8, 0x51), + _INIT_DCS_CMD(0xB9, 0x3C), + _INIT_DCS_CMD(0xBA, 0x3B), + _INIT_DCS_CMD(0xBB, 0x46), + _INIT_DCS_CMD(0xBC, 0x45), + _INIT_DCS_CMD(0xBD, 0x55), + _INIT_DCS_CMD(0xBE, 0x3D), + _INIT_DCS_CMD(0xBF, 0x3F), + _INIT_DCS_CMD(0xC0, 0x52), + _INIT_DCS_CMD(0xC1, 0x4A), + _INIT_DCS_CMD(0xC2, 0x39), + _INIT_DCS_CMD(0xC3, 0x4F), + _INIT_DCS_CMD(0xC4, 0x3A), + _INIT_DCS_CMD(0xC5, 0x42), _INIT_DCS_CMD(0xFF, 0x27), _INIT_DCS_CMD(0xFB, 0x01), @@ -419,7 +447,7 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { {}, }; -static const struct panel_init_cmd inx_init_cmd[] = { +static const struct panel_init_cmd inx_hj110iz_init_cmd[] = { _INIT_DCS_CMD(0xFF, 0x20), _INIT_DCS_CMD(0xFB, 0x01), _INIT_DCS_CMD(0x05, 0xD1), @@ -428,10 +456,10 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0x08, 0x4B), _INIT_DCS_CMD(0x0E, 0x91), _INIT_DCS_CMD(0x0F, 0x69), - _INIT_DCS_CMD(0x95, 0xFF), - _INIT_DCS_CMD(0x96, 0xFF), - _INIT_DCS_CMD(0x9D, 0x0A), - _INIT_DCS_CMD(0x9E, 0x0A), + _INIT_DCS_CMD(0x95, 0xF5), + _INIT_DCS_CMD(0x96, 0xF5), + _INIT_DCS_CMD(0x9D, 0x00), + _INIT_DCS_CMD(0x9E, 0x00), _INIT_DCS_CMD(0x69, 0x98), _INIT_DCS_CMD(0x75, 0xA2), _INIT_DCS_CMD(0x77, 0xB3), @@ -493,17 +521,17 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0x2A, 0x03), _INIT_DCS_CMD(0x2B, 0x03), - _INIT_DCS_CMD(0x2F, 0x06), + _INIT_DCS_CMD(0x2F, 0x05), _INIT_DCS_CMD(0x30, 0x32), _INIT_DCS_CMD(0x31, 0x43), - _INIT_DCS_CMD(0x33, 0x06), + _INIT_DCS_CMD(0x33, 0x05), _INIT_DCS_CMD(0x34, 0x32), _INIT_DCS_CMD(0x35, 0x43), _INIT_DCS_CMD(0x37, 0x44), _INIT_DCS_CMD(0x38, 0x40), _INIT_DCS_CMD(0x39, 0x00), - _INIT_DCS_CMD(0x3A, 0x01), - _INIT_DCS_CMD(0x3B, 0x48), + _INIT_DCS_CMD(0x3A, 0x18), + _INIT_DCS_CMD(0x3B, 0x00), _INIT_DCS_CMD(0x3D, 0x93), _INIT_DCS_CMD(0xAB, 0x44), _INIT_DCS_CMD(0xAC, 0x40), @@ -520,8 +548,8 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0x56, 0x08), _INIT_DCS_CMD(0x58, 0x21), _INIT_DCS_CMD(0x59, 0x40), - _INIT_DCS_CMD(0x5A, 0x09), - _INIT_DCS_CMD(0x5B, 0x48), + _INIT_DCS_CMD(0x5A, 0x00), + _INIT_DCS_CMD(0x5B, 0x2C), _INIT_DCS_CMD(0x5E, 0x00, 0x10), _INIT_DCS_CMD(0x5F, 0x00), @@ -558,33 +586,36 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0xEF, 0x01), _INIT_DCS_CMD(0xF0, 0x7A), + _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00), _INIT_DCS_CMD(0xFF, 0x25), _INIT_DCS_CMD(0xFB, 0x01), _INIT_DCS_CMD(0x05, 0x00), + _INIT_DCS_CMD(0x13, 0x02), + _INIT_DCS_CMD(0x14, 0xDF), _INIT_DCS_CMD(0xF1, 0x10), _INIT_DCS_CMD(0x1E, 0x00), - _INIT_DCS_CMD(0x1F, 0x09), - _INIT_DCS_CMD(0x20, 0x46), + _INIT_DCS_CMD(0x1F, 0x00), + _INIT_DCS_CMD(0x20, 0x2C), _INIT_DCS_CMD(0x25, 0x00), - _INIT_DCS_CMD(0x26, 0x09), - _INIT_DCS_CMD(0x27, 0x46), + _INIT_DCS_CMD(0x26, 0x00), + _INIT_DCS_CMD(0x27, 0x2C), _INIT_DCS_CMD(0x3F, 0x80), _INIT_DCS_CMD(0x40, 0x00), _INIT_DCS_CMD(0x43, 0x00), - _INIT_DCS_CMD(0x44, 0x09), - _INIT_DCS_CMD(0x45, 0x46), + _INIT_DCS_CMD(0x44, 0x18), + _INIT_DCS_CMD(0x45, 0x00), - _INIT_DCS_CMD(0x48, 0x09), - _INIT_DCS_CMD(0x49, 0x46), + _INIT_DCS_CMD(0x48, 0x00), + _INIT_DCS_CMD(0x49, 0x2C), _INIT_DCS_CMD(0x5B, 0x80), _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x01), - _INIT_DCS_CMD(0x5E, 0x46), - _INIT_DCS_CMD(0x61, 0x01), - _INIT_DCS_CMD(0x62, 0x46), + _INIT_DCS_CMD(0x5D, 0x00), + _INIT_DCS_CMD(0x5E, 0x00), + _INIT_DCS_CMD(0x61, 0x00), + _INIT_DCS_CMD(0x62, 0x2C), _INIT_DCS_CMD(0x68, 0x10), _INIT_DCS_CMD(0xFF, 0x26), _INIT_DCS_CMD(0xFB, 0x01), @@ -700,16 +731,22 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0xA3, 0x30), _INIT_DCS_CMD(0xA4, 0xC0), _INIT_DCS_CMD(0xE8, 0x00), + _INIT_DCS_CMD(0x97, 0x3C), + _INIT_DCS_CMD(0x98, 0x02), + _INIT_DCS_CMD(0x99, 0x95), + _INIT_DCS_CMD(0x9A, 0x06), + _INIT_DCS_CMD(0x9B, 0x00), + _INIT_DCS_CMD(0x9C, 0x0B), + _INIT_DCS_CMD(0x9D, 0x0A), + _INIT_DCS_CMD(0x9E, 0x90), _INIT_DCS_CMD(0xFF, 0xF0), _INIT_DCS_CMD(0xFB, 0x01), _INIT_DCS_CMD(0x3A, 0x08), _INIT_DCS_CMD(0xFF, 0xD0), _INIT_DCS_CMD(0xFB, 0x01), _INIT_DCS_CMD(0x00, 0x33), - _INIT_DCS_CMD(0x02, 0x77), _INIT_DCS_CMD(0x08, 0x01), _INIT_DCS_CMD(0x09, 0xBF), - _INIT_DCS_CMD(0x28, 0x30), _INIT_DCS_CMD(0x2F, 0x33), _INIT_DCS_CMD(0xFF, 0x23), _INIT_DCS_CMD(0xFB, 0x01), @@ -718,6 +755,9 @@ static const struct panel_init_cmd inx_init_cmd[] = { _INIT_DCS_CMD(0xFF, 0x20), _INIT_DCS_CMD(0xFB, 0x01), _INIT_DCS_CMD(0x30, 0x00), + _INIT_DCS_CMD(0xFF, 0x24), + _INIT_DCS_CMD(0x5C, 0x88), + _INIT_DCS_CMD(0x5D, 0x08), _INIT_DCS_CMD(0xFF, 0x10), _INIT_DCS_CMD(0xB9, 0x01), _INIT_DCS_CMD(0xFF, 0x20), @@ -1312,7 +1352,7 @@ static const struct panel_desc inx_hj110iz_desc = { | MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_VIDEO_BURST, - .init_cmds = inx_init_cmd, + .init_cmds = inx_hj110iz_init_cmd, }; static const struct drm_display_mode boe_tv101wum_nl6_default_mode = { -- cgit v1.2.3 From f8378c0403813fd7cdf0eb5cb878b1ff290046c4 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 6 Dec 2021 16:29:16 -0800 Subject: drm/bridge: parade-ps8640: Add backpointer to drm_device in drm_dp_aux When we added the support for the AUX channel in commit 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel") we forgot to set "drm_dev" to avoid the warning splat at the beginning of drm_dp_aux_register(). Since everything was working I guess I never noticed the splat when testing against mainline. In any case, it's easy to fix. This is basically just like commit 6cba3fe43341 ("drm/dp: Add backpointer to drm_device in drm_dp_aux") but just for the parade-ps8640. Fixes: 13afcdd7277e ("drm/bridge: parade-ps8640: Add support for AUX channel") Signed-off-by: Douglas Anderson Reviewed-by: Philip Chen Link: https://patchwork.freedesktop.org/patch/msgid/20211206162907.1.I1f5d1eba741e4663050ec1b8e39a753f6e42e38b@changeid --- drivers/gpu/drm/bridge/parade-ps8640.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 26898042ba3d..818704bf5e86 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -449,6 +449,7 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) return -EINVAL; + ps_bridge->aux.drm_dev = bridge->dev; ret = drm_dp_aux_register(&ps_bridge->aux); if (ret) { dev_err(dev, "failed to register DP AUX channel: %d\n", ret); -- cgit v1.2.3 From fe4d0b6317e35a9a371d1107c9b753becc81e968 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Fri, 19 Nov 2021 10:06:20 +0200 Subject: drm: omapdrm: Export correct scatterlist for TILER backed BOs Memory of BOs backed by TILER is not contiguous, but omap_gem_map_dma_buf() exports it like it is. This leads to (possibly) invalid memory accesses if another device imports such a BO. Fix that by providing sg that correctly describes TILER memory layout. Align TILER allocations to page, so importer to be able to correctly set its MMU if have one. Set export size accounting for the alignment. Also, make sure to destroy sg on unpin, as it is no longer valid. Tested on Motorola Droid4 by using GPU (sgx540) to render. Suggested-by: Matthijs van Duin Signed-off-by: Ivaylo Dimitrov Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/1637309180-31032-1-git-send-email-ivo.g.dimitrov.75@gmail.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 79 ++++++++++++++++++++++++++++++- drivers/gpu/drm/omapdrm/omap_gem.h | 2 + drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 34 ++----------- 3 files changed, 85 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 38af6195d959..b0fa17409b66 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -789,7 +789,7 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) if (omap_obj->flags & OMAP_BO_TILED_MASK) { block = tiler_reserve_2d(fmt, omap_obj->width, - omap_obj->height, 0); + omap_obj->height, PAGE_SIZE); } else { block = tiler_reserve_1d(obj->size); } @@ -851,6 +851,11 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj) return; if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { + if (omap_obj->sgt) { + sg_free_table(omap_obj->sgt); + kfree(omap_obj->sgt); + omap_obj->sgt = NULL; + } ret = tiler_unpin(omap_obj->block); if (ret) { dev_err(obj->dev->dev, @@ -963,6 +968,78 @@ int omap_gem_put_pages(struct drm_gem_object *obj) return 0; } +struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + dma_addr_t addr; + struct sg_table *sgt; + struct scatterlist *sg; + unsigned int count, len, stride, i; + int ret; + + ret = omap_gem_pin(obj, &addr); + if (ret) + return ERR_PTR(ret); + + mutex_lock(&omap_obj->lock); + + sgt = omap_obj->sgt; + if (sgt) + goto out; + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + ret = -ENOMEM; + goto err_unpin; + } + + if (omap_obj->flags & OMAP_BO_TILED_MASK) { + enum tiler_fmt fmt = gem2fmt(omap_obj->flags); + + len = omap_obj->width << (int)fmt; + count = omap_obj->height; + stride = tiler_stride(fmt, 0); + } else { + len = obj->size; + count = 1; + stride = 0; + } + + ret = sg_alloc_table(sgt, count, GFP_KERNEL); + if (ret) + goto err_free; + + for_each_sg(sgt->sgl, sg, count, i) { + sg_set_page(sg, phys_to_page(addr), len, offset_in_page(addr)); + sg_dma_address(sg) = addr; + sg_dma_len(sg) = len; + + addr += stride; + } + + omap_obj->sgt = sgt; +out: + mutex_unlock(&omap_obj->lock); + return sgt; + +err_free: + kfree(sgt); +err_unpin: + mutex_unlock(&omap_obj->lock); + omap_gem_unpin(obj); + return ERR_PTR(ret); +} + +void omap_gem_put_sg(struct drm_gem_object *obj, struct sg_table *sgt) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + + if (WARN_ON(omap_obj->sgt != sgt)) + return; + + omap_gem_unpin(obj); +} + #ifdef CONFIG_DRM_FBDEV_EMULATION /* * Get kernel virtual address for CPU access.. this more or less only diff --git a/drivers/gpu/drm/omapdrm/omap_gem.h b/drivers/gpu/drm/omapdrm/omap_gem.h index eda9b4839c30..19209e319663 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.h +++ b/drivers/gpu/drm/omapdrm/omap_gem.h @@ -82,5 +82,7 @@ u32 omap_gem_flags(struct drm_gem_object *obj); int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, int x, int y, dma_addr_t *dma_addr); int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient); +struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj); +void omap_gem_put_sg(struct drm_gem_object *obj, struct sg_table *sgt); #endif /* __OMAPDRM_GEM_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index 809f86cfc540..57af3d97be77 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -23,45 +23,21 @@ static struct sg_table *omap_gem_map_dma_buf( { struct drm_gem_object *obj = attachment->dmabuf->priv; struct sg_table *sg; - dma_addr_t dma_addr; - int ret; - - sg = kzalloc(sizeof(*sg), GFP_KERNEL); - if (!sg) - return ERR_PTR(-ENOMEM); - - /* camera, etc, need physically contiguous.. but we need a - * better way to know this.. - */ - ret = omap_gem_pin(obj, &dma_addr); - if (ret) - goto out; - - ret = sg_alloc_table(sg, 1, GFP_KERNEL); - if (ret) - goto out; - - sg_init_table(sg->sgl, 1); - sg_dma_len(sg->sgl) = obj->size; - sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(dma_addr)), obj->size, 0); - sg_dma_address(sg->sgl) = dma_addr; + sg = omap_gem_get_sg(obj); + if (IS_ERR(sg)) + return sg; /* this must be after omap_gem_pin() to ensure we have pages attached */ omap_gem_dma_sync_buffer(obj, dir); return sg; -out: - kfree(sg); - return ERR_PTR(ret); } static void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *sg, enum dma_data_direction dir) { struct drm_gem_object *obj = attachment->dmabuf->priv; - omap_gem_unpin(obj); - sg_free_table(sg); - kfree(sg); + omap_gem_put_sg(obj, sg); } static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, @@ -114,7 +90,7 @@ struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags) DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &omap_dmabuf_ops; - exp_info.size = obj->size; + exp_info.size = omap_gem_mmap_size(obj); exp_info.flags = flags; exp_info.priv = obj; -- cgit v1.2.3 From c21134b042ef9eb1662fd856941f031eb76d77b1 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 17 Nov 2021 15:19:20 +0100 Subject: drm/omap: add sanity plane state check Call drm_atomic_helper_check_plane_state() from the plane atomic_check() callback in order to add plane state sanity checking. It will permit filtering out totally bad scaling factors, even if the real check are done later in the atomic commit. Calling drm_atomic_helper_check_plane_state() also sets plane_state->visible which will be useful when dynamically assigning hw overlays to planes. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-2-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_plane.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 512af976b7e9..c3de4f339387 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -104,12 +104,15 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, dispc_ovl_enable(priv->dispc, omap_plane->id, false); } +#define FRAC_16_16(mult, div) (((mult) << 16) / (div)) + static int omap_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); struct drm_crtc_state *crtc_state; + int ret; if (!new_plane_state->fb) return 0; @@ -127,6 +130,18 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (!crtc_state->enable) return 0; + /* + * Note: these are just sanity checks to filter out totally bad scaling + * factors. The real limits must be calculated case by case, and + * unfortunately we currently do those checks only at the commit + * phase in dispc. + */ + ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, + FRAC_16_16(1, 8), FRAC_16_16(8, 1), + true, true); + if (ret) + return ret; + if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0) return -EINVAL; -- cgit v1.2.3 From d484c20d7cb971b036b075112c9b7e7946e1aa96 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:21 +0100 Subject: drm/omap: Add ability to check if requested plane modes can be supported We currently assume that an overlay has the same maximum width and maximum height as the overlay manager. This assumption is incorrect. On some variants the overlay manager maximum width is twice the maximum width that the overlay can handle. We need to add the appropriate data per variant as well as export a helper function to retrieve the data so check can be made dynamically in omap_plane_atomic_check(). Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-3-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/omapdrm/dss/dss.h | 2 ++ drivers/gpu/drm/omapdrm/omap_plane.c | 14 ++++++++++++++ 3 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index b440147ae28b..d3cf9d9aef63 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -92,6 +92,8 @@ struct dispc_features { u8 mgr_height_start; u16 mgr_width_max; u16 mgr_height_max; + u16 ovl_width_max; + u16 ovl_height_max; unsigned long max_lcd_pclk; unsigned long max_tv_pclk; unsigned int max_downscale; @@ -2599,6 +2601,12 @@ static int dispc_ovl_calc_scaling(struct dispc_device *dispc, return 0; } +void dispc_ovl_get_max_size(struct dispc_device *dispc, u16 *width, u16 *height) +{ + *width = dispc->feat->ovl_width_max; + *height = dispc->feat->ovl_height_max; +} + static int dispc_ovl_setup_common(struct dispc_device *dispc, enum omap_plane_id plane, enum omap_overlay_caps caps, @@ -4240,6 +4248,8 @@ static const struct dispc_features omap24xx_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 66500000, .max_downscale = 2, /* @@ -4278,6 +4288,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, .max_downscale = 4, @@ -4313,6 +4325,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, .max_downscale = 4, @@ -4348,6 +4362,8 @@ static const struct dispc_features omap36xx_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, .max_downscale = 4, @@ -4383,6 +4399,8 @@ static const struct dispc_features am43xx_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, .max_downscale = 4, @@ -4418,6 +4436,8 @@ static const struct dispc_features omap44xx_dispc_feats = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .ovl_width_max = 2048, + .ovl_height_max = 2048, .max_lcd_pclk = 170000000, .max_tv_pclk = 185625000, .max_downscale = 4, @@ -4457,6 +4477,8 @@ static const struct dispc_features omap54xx_dispc_feats = { .mgr_height_start = 27, .mgr_width_max = 4096, .mgr_height_max = 4096, + .ovl_width_max = 2048, + .ovl_height_max = 4096, .max_lcd_pclk = 170000000, .max_tv_pclk = 192000000, .max_downscale = 4, diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index a547527bb2f3..14c39f7c3988 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -397,6 +397,8 @@ int dispc_get_num_mgrs(struct dispc_device *dispc); const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc, enum omap_plane_id plane); +void dispc_ovl_get_max_size(struct dispc_device *dispc, u16 *width, u16 *height); + u32 dispc_read_irqstatus(struct dispc_device *dispc); void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask); void dispc_write_irqenable(struct dispc_device *dispc, u32 mask); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index c3de4f339387..846698c21a4a 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -111,12 +111,19 @@ static int omap_plane_atomic_check(struct drm_plane *plane, { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct omap_drm_private *priv = plane->dev->dev_private; struct drm_crtc_state *crtc_state; + u32 max_width, max_height; + u16 width, height; int ret; if (!new_plane_state->fb) return 0; + dispc_ovl_get_max_size(priv->dispc, &width, &height); + max_width = width << 16; + max_height = height << 16; + /* crtc should only be NULL when disabling (i.e., !new_plane_state->fb) */ if (WARN_ON(!new_plane_state->crtc)) return 0; @@ -151,6 +158,13 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (new_plane_state->crtc_y + new_plane_state->crtc_h > crtc_state->adjusted_mode.vdisplay) return -EINVAL; + /* Make sure dimensions are within bounds. */ + if (new_plane_state->src_h > max_height || new_plane_state->crtc_h > height) + return -EINVAL; + + if (new_plane_state->src_w > max_width || new_plane_state->crtc_w > width) + return -EINVAL; + if (new_plane_state->rotation != DRM_MODE_ROTATE_0 && !omap_framebuffer_supports_rotation(new_plane_state->fb)) return -EINVAL; -- cgit v1.2.3 From 0b0f7282f0c81fcbbf300079eaeabd4dcef63c11 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:22 +0100 Subject: drm/omap: Add ovl checking funcs to dispc_ops In order to be able to dynamically assign overlays to planes we need to be able to asses the overlay capabilities. Add a helper function to be able to retrieve the supported capabilities of an overlay. And export the function to check if a fourcc is supported on a given overlay. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-4-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 9 +++++++-- drivers/gpu/drm/omapdrm/dss/dss.h | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index d3cf9d9aef63..2da4d36a3446 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -1281,8 +1281,8 @@ static u32 dispc_ovl_get_burst_size(struct dispc_device *dispc, return dispc->feat->burst_size_unit * 8; } -static bool dispc_ovl_color_mode_supported(struct dispc_device *dispc, - enum omap_plane_id plane, u32 fourcc) +bool dispc_ovl_color_mode_supported(struct dispc_device *dispc, + enum omap_plane_id plane, u32 fourcc) { const u32 *modes; unsigned int i; @@ -2489,6 +2489,11 @@ static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc, return 0; } +enum omap_overlay_caps dispc_ovl_get_caps(struct dispc_device *dispc, enum omap_plane_id plane) +{ + return dispc->feat->overlay_caps[plane]; +} + #define DIV_FRAC(dividend, divisor) \ ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100)) diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 14c39f7c3988..4ff02fbc0e71 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -398,6 +398,9 @@ const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc, enum omap_plane_id plane); void dispc_ovl_get_max_size(struct dispc_device *dispc, u16 *width, u16 *height); +bool dispc_ovl_color_mode_supported(struct dispc_device *dispc, + enum omap_plane_id plane, u32 fourcc); +enum omap_overlay_caps dispc_ovl_get_caps(struct dispc_device *dispc, enum omap_plane_id plane); u32 dispc_read_irqstatus(struct dispc_device *dispc); void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask); -- cgit v1.2.3 From c8fa1e733c597a7b11a22a3e49de5ea1362e9a7a Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:23 +0100 Subject: drm/omap: introduce omap_hw_overlay Split out the hardware overlay specifics from omap_plane. To start, the hw overlays are statically assigned to planes. The goal is to eventually assign hw overlays dynamically to planes during plane->atomic_check() based on requested caps (scaling, YUV, etc). And then perform hw overlay re-assignment if required. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-5-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/Makefile | 1 + drivers/gpu/drm/omapdrm/omap_drv.c | 9 +++- drivers/gpu/drm/omapdrm/omap_drv.h | 4 ++ drivers/gpu/drm/omapdrm/omap_overlay.c | 84 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_overlay.h | 30 ++++++++++++ drivers/gpu/drm/omapdrm/omap_plane.c | 54 +++++++++------------- 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 drivers/gpu/drm/omapdrm/omap_overlay.c create mode 100644 drivers/gpu/drm/omapdrm/omap_overlay.h (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/Makefile b/drivers/gpu/drm/omapdrm/Makefile index 21e8277ff88f..710b4e0abcf0 100644 --- a/drivers/gpu/drm/omapdrm/Makefile +++ b/drivers/gpu/drm/omapdrm/Makefile @@ -9,6 +9,7 @@ omapdrm-y := omap_drv.o \ omap_debugfs.o \ omap_crtc.o \ omap_plane.o \ + omap_overlay.o \ omap_encoder.o \ omap_fb.o \ omap_gem.o \ diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index c05d3975cb31..f17a72a4023e 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -583,10 +583,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) omap_gem_init(ddev); + ret = omap_hwoverlays_init(priv); + if (ret) + goto err_gem_deinit; + ret = omap_modeset_init(ddev); if (ret) { dev_err(priv->dev, "omap_modeset_init failed: ret=%d\n", ret); - goto err_gem_deinit; + goto err_free_overlays; } /* Initialize vblank handling, start with all CRTCs disabled. */ @@ -618,6 +622,8 @@ err_cleanup_helpers: omap_fbdev_fini(ddev); err_cleanup_modeset: omap_modeset_fini(ddev); +err_free_overlays: + omap_hwoverlays_destroy(priv); err_gem_deinit: omap_gem_deinit(ddev); destroy_workqueue(priv->wq); @@ -642,6 +648,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) drm_atomic_helper_shutdown(ddev); omap_modeset_fini(ddev); + omap_hwoverlays_destroy(priv); omap_gem_deinit(ddev); destroy_workqueue(priv->wq); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 591d4c273f02..b4d9c2062723 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -24,6 +24,7 @@ #include "omap_gem.h" #include "omap_irq.h" #include "omap_plane.h" +#include "omap_overlay.h" #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) /* verbose debug */ @@ -57,6 +58,9 @@ struct omap_drm_private { unsigned int num_planes; struct drm_plane *planes[8]; + unsigned int num_ovls; + struct omap_hw_overlay *overlays[8]; + struct drm_fb_helper *fbdev; struct workqueue_struct *wq; diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.c b/drivers/gpu/drm/omapdrm/omap_overlay.c new file mode 100644 index 000000000000..de67b39529bd --- /dev/null +++ b/drivers/gpu/drm/omapdrm/omap_overlay.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Benoit Parrot + */ + +#include +#include +#include + +#include "omap_dmm_tiler.h" +#include "omap_drv.h" + +/* + * overlay funcs + */ +static const char * const overlay_id_to_name[] = { + [OMAP_DSS_GFX] = "gfx", + [OMAP_DSS_VIDEO1] = "vid1", + [OMAP_DSS_VIDEO2] = "vid2", + [OMAP_DSS_VIDEO3] = "vid3", +}; + +static void omap_overlay_destroy(struct omap_hw_overlay *overlay) +{ + kfree(overlay); +} + +static struct omap_hw_overlay *omap_overlay_init(enum omap_plane_id overlay_id, + enum omap_overlay_caps caps) +{ + struct omap_hw_overlay *overlay; + + overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); + if (!overlay) + return ERR_PTR(-ENOMEM); + + overlay->name = overlay_id_to_name[overlay_id]; + overlay->id = overlay_id; + overlay->caps = caps; + + return overlay; +} + +int omap_hwoverlays_init(struct omap_drm_private *priv) +{ + static const enum omap_plane_id hw_plane_ids[] = { + OMAP_DSS_GFX, OMAP_DSS_VIDEO1, + OMAP_DSS_VIDEO2, OMAP_DSS_VIDEO3, + }; + u32 num_overlays = dispc_get_num_ovls(priv->dispc); + enum omap_overlay_caps caps; + int i, ret; + + for (i = 0; i < num_overlays; i++) { + struct omap_hw_overlay *overlay; + + caps = dispc_ovl_get_caps(priv->dispc, hw_plane_ids[i]); + overlay = omap_overlay_init(hw_plane_ids[i], caps); + if (IS_ERR(overlay)) { + ret = PTR_ERR(overlay); + dev_err(priv->dev, "failed to construct overlay for %s (%d)\n", + overlay_id_to_name[i], ret); + omap_hwoverlays_destroy(priv); + return ret; + } + overlay->idx = priv->num_ovls; + priv->overlays[priv->num_ovls++] = overlay; + } + + return 0; +} + +void omap_hwoverlays_destroy(struct omap_drm_private *priv) +{ + int i; + + for (i = 0; i < priv->num_ovls; i++) { + omap_overlay_destroy(priv->overlays[i]); + priv->overlays[i] = NULL; + } + + priv->num_ovls = 0; +} diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.h b/drivers/gpu/drm/omapdrm/omap_overlay.h new file mode 100644 index 000000000000..51d26aebf77d --- /dev/null +++ b/drivers/gpu/drm/omapdrm/omap_overlay.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Benoit Parrot + */ + +#ifndef __OMAPDRM_OVERLAY_H__ +#define __OMAPDRM_OVERLAY_H__ + +#include + +enum drm_plane_type; + +struct drm_device; +struct drm_mode_object; +struct drm_plane; + +/* Used to associate a HW overlay/plane to a plane */ +struct omap_hw_overlay { + unsigned int idx; + + const char *name; + enum omap_plane_id id; + + enum omap_overlay_caps caps; +}; + +int omap_hwoverlays_init(struct omap_drm_private *priv); +void omap_hwoverlays_destroy(struct omap_drm_private *priv); +#endif /* __OMAPDRM_OVERLAY_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 846698c21a4a..8cc2b899f20c 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -21,7 +21,8 @@ struct omap_plane { struct drm_plane base; enum omap_plane_id id; - const char *name; + + struct omap_hw_overlay *overlay; }; static int omap_plane_prepare_fb(struct drm_plane *plane, @@ -49,10 +50,11 @@ static void omap_plane_atomic_update(struct drm_plane *plane, struct omap_plane *omap_plane = to_omap_plane(plane); struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); + enum omap_plane_id ovl_id = omap_plane->overlay->id; struct omap_overlay_info info; int ret; - DBG("%s, crtc=%p fb=%p", omap_plane->name, new_state->crtc, + DBG("%s, crtc=%p fb=%p", plane->name, new_state->crtc, new_state->fb); memset(&info, 0, sizeof(info)); @@ -77,17 +79,17 @@ static void omap_plane_atomic_update(struct drm_plane *plane, &info.paddr, &info.p_uv_addr); /* and finally, update omapdss: */ - ret = dispc_ovl_setup(priv->dispc, omap_plane->id, &info, + ret = dispc_ovl_setup(priv->dispc, ovl_id, &info, omap_crtc_timings(new_state->crtc), false, omap_crtc_channel(new_state->crtc)); if (ret) { dev_err(plane->dev->dev, "Failed to setup plane %s\n", - omap_plane->name); - dispc_ovl_enable(priv->dispc, omap_plane->id, false); + plane->name); + dispc_ovl_enable(priv->dispc, ovl_id, false); return; } - dispc_ovl_enable(priv->dispc, omap_plane->id, true); + dispc_ovl_enable(priv->dispc, ovl_id, true); } static void omap_plane_atomic_disable(struct drm_plane *plane, @@ -97,11 +99,12 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, plane); struct omap_drm_private *priv = plane->dev->dev_private; struct omap_plane *omap_plane = to_omap_plane(plane); + enum omap_plane_id ovl_id = omap_plane->overlay->id; new_state->rotation = DRM_MODE_ROTATE_0; new_state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id; - dispc_ovl_enable(priv->dispc, omap_plane->id, false); + dispc_ovl_enable(priv->dispc, ovl_id, false); } #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) @@ -184,7 +187,7 @@ static void omap_plane_destroy(struct drm_plane *plane) { struct omap_plane *omap_plane = to_omap_plane(plane); - DBG("%s", omap_plane->name); + DBG("%s", plane->name); drm_plane_cleanup(plane); @@ -290,20 +293,6 @@ static bool omap_plane_supports_yuv(struct drm_plane *plane) return false; } -static const char *plane_id_to_name[] = { - [OMAP_DSS_GFX] = "gfx", - [OMAP_DSS_VIDEO1] = "vid1", - [OMAP_DSS_VIDEO2] = "vid2", - [OMAP_DSS_VIDEO3] = "vid3", -}; - -static const enum omap_plane_id plane_idx_to_id[] = { - OMAP_DSS_GFX, - OMAP_DSS_VIDEO1, - OMAP_DSS_VIDEO2, - OMAP_DSS_VIDEO3, -}; - /* initialize plane */ struct drm_plane *omap_plane_init(struct drm_device *dev, int idx, enum drm_plane_type type, @@ -313,27 +302,26 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, unsigned int num_planes = dispc_get_num_ovls(priv->dispc); struct drm_plane *plane; struct omap_plane *omap_plane; - enum omap_plane_id id; int ret; u32 nformats; const u32 *formats; - if (WARN_ON(idx >= ARRAY_SIZE(plane_idx_to_id))) + if (WARN_ON(idx >= num_planes)) return ERR_PTR(-EINVAL); - id = plane_idx_to_id[idx]; - - DBG("%s: type=%d", plane_id_to_name[id], type); - omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); if (!omap_plane) return ERR_PTR(-ENOMEM); - formats = dispc_ovl_get_color_modes(priv->dispc, id); + omap_plane->id = idx; + omap_plane->overlay = priv->overlays[idx]; + + DBG("%d: type=%d", omap_plane->id, type); + DBG(" crtc_mask: 0x%04x", possible_crtcs); + + formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->overlay->id); for (nformats = 0; formats[nformats]; ++nformats) ; - omap_plane->id = id; - omap_plane->name = plane_id_to_name[id]; plane = &omap_plane->base; @@ -363,8 +351,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, return plane; error: - dev_err(dev->dev, "%s(): could not create plane: %s\n", - __func__, plane_id_to_name[id]); + dev_err(dev->dev, "%s(): could not create plane: %d\n", + __func__, omap_plane->id); kfree(omap_plane); return NULL; -- cgit v1.2.3 From 3c265d928b85a0ec8aa4aea9aab89efd201bd2ae Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:24 +0100 Subject: drm/omap: omap_plane: subclass drm_plane_state In preparation to add omap plane state specific extensions we need to subclass drm_plane_state and add the relevant helpers. The addition of specific extension will be done separately. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-6-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_plane.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 8cc2b899f20c..72d5adbbadfa 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -16,6 +16,13 @@ * plane funcs */ +#define to_omap_plane_state(x) container_of(x, struct omap_plane_state, base) + +struct omap_plane_state { + /* Must be first. */ + struct drm_plane_state base; +}; + #define to_omap_plane(x) container_of(x, struct omap_plane, base) struct omap_plane { @@ -221,11 +228,17 @@ void omap_plane_install_properties(struct drm_plane *plane, static void omap_plane_reset(struct drm_plane *plane) { struct omap_plane *omap_plane = to_omap_plane(plane); + struct omap_plane_state *omap_state; - drm_atomic_helper_plane_reset(plane); - if (!plane->state) + if (plane->state) + drm_atomic_helper_plane_destroy_state(plane, plane->state); + + omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL); + if (!omap_state) return; + __drm_atomic_helper_plane_reset(plane, &omap_state->base); + /* * Set the zpos default depending on whether we are a primary or overlay * plane. @@ -236,6 +249,23 @@ static void omap_plane_reset(struct drm_plane *plane) plane->state->color_range = DRM_COLOR_YCBCR_FULL_RANGE; } +static struct drm_plane_state * +omap_plane_atomic_duplicate_state(struct drm_plane *plane) +{ + struct omap_plane_state *state; + + if (WARN_ON(!plane->state)) + return NULL; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, &state->base); + + return &state->base; +} + static int omap_plane_atomic_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, @@ -271,7 +301,7 @@ static const struct drm_plane_funcs omap_plane_funcs = { .disable_plane = drm_atomic_helper_disable_plane, .reset = omap_plane_reset, .destroy = omap_plane_destroy, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_duplicate_state = omap_plane_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_set_property = omap_plane_atomic_set_property, .atomic_get_property = omap_plane_atomic_get_property, -- cgit v1.2.3 From 6e42201b0ed5d3af66c107144fcd96c17afbc6f1 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:25 +0100 Subject: drm/omap: Add global state as a private atomic object Global shared resources (like hw overlays) for omapdrm are implemented as a part of atomic state using the drm_private_obj infrastructure available in the atomic core. omap_global_state is introduced as a drm atomic private object. The two funcs omap_get_global_state() and omap_get_existing_global_state() are the two variants that will be used to access omap_global_state. drm_mode_config_init() needs to be called earlier because it creates/initializes the private_obj link list maintained by the atomic framework. The private_obj link list has to exist prior to calling drm_atomic_private_obj_init(). Similarly the cleanup handler are reordered appropriately. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-7-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_drv.c | 91 ++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/omapdrm/omap_drv.h | 17 +++++++ 2 files changed, 105 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index f17a72a4023e..44a9dcb3100c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -128,6 +128,82 @@ static const struct drm_mode_config_funcs omap_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; +/* Global/shared object state funcs */ + +/* + * This is a helper that returns the private state currently in operation. + * Note that this would return the "old_state" if called in the atomic check + * path, and the "new_state" after the atomic swap has been done. + */ +struct omap_global_state * +omap_get_existing_global_state(struct omap_drm_private *priv) +{ + return to_omap_global_state(priv->glob_obj.state); +} + +/* + * This acquires the modeset lock set aside for global state, creates + * a new duplicated private object state. + */ +struct omap_global_state *__must_check +omap_get_global_state(struct drm_atomic_state *s) +{ + struct omap_drm_private *priv = s->dev->dev_private; + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(s, &priv->glob_obj); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_omap_global_state(priv_state); +} + +static struct drm_private_state * +omap_global_duplicate_state(struct drm_private_obj *obj) +{ + struct omap_global_state *state; + + state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); + + return &state->base; +} + +static void omap_global_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct omap_global_state *omap_state = to_omap_global_state(state); + + kfree(omap_state); +} + +static const struct drm_private_state_funcs omap_global_state_funcs = { + .atomic_duplicate_state = omap_global_duplicate_state, + .atomic_destroy_state = omap_global_destroy_state, +}; + +static int omap_global_obj_init(struct drm_device *dev) +{ + struct omap_drm_private *priv = dev->dev_private; + struct omap_global_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + drm_atomic_private_obj_init(dev, &priv->glob_obj, &state->base, + &omap_global_state_funcs); + return 0; +} + +static void omap_global_obj_fini(struct omap_drm_private *priv) +{ + drm_atomic_private_obj_fini(&priv->glob_obj); +} + static void omap_disconnect_pipelines(struct drm_device *ddev) { struct omap_drm_private *priv = ddev->dev_private; @@ -231,8 +307,6 @@ static int omap_modeset_init(struct drm_device *dev) if (!omapdss_stack_is_ready()) return -EPROBE_DEFER; - drm_mode_config_init(dev); - ret = omap_modeset_init_properties(dev); if (ret < 0) return ret; @@ -583,10 +657,16 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) omap_gem_init(ddev); - ret = omap_hwoverlays_init(priv); + drm_mode_config_init(ddev); + + ret = omap_global_obj_init(ddev); if (ret) goto err_gem_deinit; + ret = omap_hwoverlays_init(priv); + if (ret) + goto err_free_priv_obj; + ret = omap_modeset_init(ddev); if (ret) { dev_err(priv->dev, "omap_modeset_init failed: ret=%d\n", ret); @@ -624,7 +704,10 @@ err_cleanup_modeset: omap_modeset_fini(ddev); err_free_overlays: omap_hwoverlays_destroy(priv); +err_free_priv_obj: + omap_global_obj_fini(priv); err_gem_deinit: + drm_mode_config_cleanup(ddev); omap_gem_deinit(ddev); destroy_workqueue(priv->wq); omap_disconnect_pipelines(ddev); @@ -649,6 +732,8 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) omap_modeset_fini(ddev); omap_hwoverlays_destroy(priv); + omap_global_obj_fini(priv); + drm_mode_config_cleanup(ddev); omap_gem_deinit(ddev); destroy_workqueue(priv->wq); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index b4d9c2062723..a3079aad7ae3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -14,6 +14,7 @@ #include "dss/omapdss.h" #include "dss/dss.h" +#include #include #include @@ -41,6 +42,16 @@ struct omap_drm_pipeline { unsigned int alias_id; }; +/* + * Global private object state for tracking resources that are shared across + * multiple kms objects (planes/crtcs/etc). + */ +#define to_omap_global_state(x) container_of(x, struct omap_global_state, base) + +struct omap_global_state { + struct drm_private_state base; +}; + struct omap_drm_private { struct drm_device *ddev; struct device *dev; @@ -61,6 +72,8 @@ struct omap_drm_private { unsigned int num_ovls; struct omap_hw_overlay *overlays[8]; + struct drm_private_obj glob_obj; + struct drm_fb_helper *fbdev; struct workqueue_struct *wq; @@ -89,4 +102,8 @@ struct omap_drm_private { void omap_debugfs_init(struct drm_minor *minor); +struct omap_global_state * __must_check omap_get_global_state(struct drm_atomic_state *s); + +struct omap_global_state *omap_get_existing_global_state(struct omap_drm_private *priv); + #endif /* __OMAPDRM_DRV_H__ */ -- cgit v1.2.3 From 2e54ff0e5430883f2040450e9297ebad9f56f846 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:26 +0100 Subject: drm/omap: dynamically assign hw overlays to planes (re)assign the hw overlays to planes based on required caps, and to handle situations where we could not modify an in-use plane. This means all planes advertise the superset of formats and properties. Userspace must (as always) use atomic TEST_ONLY step for atomic updates, as not all planes may be available for use on every frame. The mapping of hwoverlays to plane is stored in omap_global_state, so that state updates are atomically committed in the same way that plane/etc state updates are managed. This is needed because the omap_plane_state keeps a pointer to the hwoverlay, and we don't want global state to become out of sync with the plane state if an atomic update fails, we hit deadlock/ backoff scenario, etc. The use of global_state_lock keeps multiple parallel updates which both re-assign hwoverlays properly serialized. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-8-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_drv.h | 3 + drivers/gpu/drm/omapdrm/omap_overlay.c | 109 ++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_overlay.h | 4 ++ drivers/gpu/drm/omapdrm/omap_plane.c | 127 +++++++++++++++++++++++++++------ 4 files changed, 220 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index a3079aad7ae3..825960fd3ea9 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -50,6 +50,9 @@ struct omap_drm_pipeline { struct omap_global_state { struct drm_private_state base; + + /* global atomic state of assignment between overlays and planes */ + struct drm_plane *hwoverlay_to_plane[8]; }; struct omap_drm_private { diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.c b/drivers/gpu/drm/omapdrm/omap_overlay.c index de67b39529bd..afb2b44fdf86 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.c +++ b/drivers/gpu/drm/omapdrm/omap_overlay.c @@ -21,6 +21,115 @@ static const char * const overlay_id_to_name[] = { [OMAP_DSS_VIDEO3] = "vid3", }; +/* + * Find a free overlay with the required caps and supported fourcc + */ +static struct omap_hw_overlay * +omap_plane_find_free_overlay(struct drm_device *dev, struct drm_plane *hwoverlay_to_plane[], + u32 caps, u32 fourcc) +{ + struct omap_drm_private *priv = dev->dev_private; + int i; + + DBG("caps: %x fourcc: %x", caps, fourcc); + + for (i = 0; i < priv->num_ovls; i++) { + struct omap_hw_overlay *cur = priv->overlays[i]; + + DBG("%d: id: %d cur->caps: %x", + cur->idx, cur->id, cur->caps); + + /* skip if already in-use */ + if (hwoverlay_to_plane[cur->idx]) + continue; + + /* skip if doesn't support some required caps: */ + if (caps & ~cur->caps) + continue; + + /* check supported format */ + if (!dispc_ovl_color_mode_supported(priv->dispc, + cur->id, fourcc)) + continue; + + return cur; + } + + DBG("no match"); + return NULL; +} + +/* + * Assign a new overlay to a plane with the required caps and supported fourcc + * If a plane need a new overlay, the previous one should have been released + * with omap_overlay_release() + * This should be called from the plane atomic_check() in order to prepare the + * next global overlay_map to be enabled when atomic transaction is valid. + */ +int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, + u32 caps, u32 fourcc, struct omap_hw_overlay **overlay) +{ + /* Get the global state of the current atomic transaction */ + struct omap_global_state *state = omap_get_global_state(s); + struct drm_plane **overlay_map = state->hwoverlay_to_plane; + struct omap_hw_overlay *ovl; + + ovl = omap_plane_find_free_overlay(s->dev, overlay_map, caps, fourcc); + if (!ovl) + return -ENOMEM; + + overlay_map[ovl->idx] = plane; + *overlay = ovl; + + DBG("%s: assign to plane %s caps %x", ovl->name, plane->name, caps); + + return 0; +} + +/* + * Release an overlay from a plane if the plane gets not visible or the plane + * need a new overlay if overlay caps changes. + * This should be called from the plane atomic_check() in order to prepare the + * next global overlay_map to be enabled when atomic transaction is valid. + */ +void omap_overlay_release(struct drm_atomic_state *s, struct omap_hw_overlay *overlay) +{ + /* Get the global state of the current atomic transaction */ + struct omap_global_state *state = omap_get_global_state(s); + struct drm_plane **overlay_map = state->hwoverlay_to_plane; + + if (!overlay) + return; + + if (WARN_ON(!overlay_map[overlay->idx])) + return; + + DBG("%s: release from plane %s", overlay->name, overlay_map[overlay->idx]->name); + + overlay_map[overlay->idx] = NULL; +} + +/* + * Update an overlay state that was attached to a plane before the current atomic state. + * This should be called from the plane atomic_update() or atomic_disable(), + * where an overlay association to a plane could have changed between the old and current + * atomic state. + */ +void omap_overlay_update_state(struct omap_drm_private *priv, + struct omap_hw_overlay *overlay) +{ + struct omap_global_state *state = omap_get_existing_global_state(priv); + struct drm_plane **overlay_map = state->hwoverlay_to_plane; + + /* Check if this overlay is not used anymore, then disable it */ + if (!overlay_map[overlay->idx]) { + DBG("%s: disabled", overlay->name); + + /* disable the overlay */ + dispc_ovl_enable(priv->dispc, overlay->id, false); + } +} + static void omap_overlay_destroy(struct omap_hw_overlay *overlay) { kfree(overlay); diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.h b/drivers/gpu/drm/omapdrm/omap_overlay.h index 51d26aebf77d..38ca55e1e2d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.h +++ b/drivers/gpu/drm/omapdrm/omap_overlay.h @@ -27,4 +27,8 @@ struct omap_hw_overlay { int omap_hwoverlays_init(struct omap_drm_private *priv); void omap_hwoverlays_destroy(struct omap_drm_private *priv); +int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, + u32 caps, u32 fourcc, struct omap_hw_overlay **overlay); +void omap_overlay_release(struct drm_atomic_state *s, struct omap_hw_overlay *overlay); +void omap_overlay_update_state(struct omap_drm_private *priv, struct omap_hw_overlay *overlay); #endif /* __OMAPDRM_OVERLAY_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 72d5adbbadfa..ce5ed45401fb 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "omap_dmm_tiler.h" #include "omap_drv.h" @@ -21,6 +22,8 @@ struct omap_plane_state { /* Must be first. */ struct drm_plane_state base; + + struct omap_hw_overlay *overlay; }; #define to_omap_plane(x) container_of(x, struct omap_plane, base) @@ -28,8 +31,6 @@ struct omap_plane_state { struct omap_plane { struct drm_plane base; enum omap_plane_id id; - - struct omap_hw_overlay *overlay; }; static int omap_plane_prepare_fb(struct drm_plane *plane, @@ -54,13 +55,29 @@ static void omap_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { struct omap_drm_private *priv = plane->dev->dev_private; - struct omap_plane *omap_plane = to_omap_plane(plane); struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); - enum omap_plane_id ovl_id = omap_plane->overlay->id; + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); + struct omap_plane_state *new_omap_state; + struct omap_plane_state *old_omap_state; struct omap_overlay_info info; + enum omap_plane_id ovl_id; int ret; + new_omap_state = to_omap_plane_state(new_state); + old_omap_state = to_omap_plane_state(old_state); + + /* Cleanup previously held overlay if needed */ + if (old_omap_state->overlay) + omap_overlay_update_state(priv, old_omap_state->overlay); + + if (!new_omap_state->overlay) { + DBG("[PLANE:%d:%s] no overlay attached", plane->base.id, plane->name); + return; + } + + ovl_id = new_omap_state->overlay->id; DBG("%s, crtc=%p fb=%p", plane->name, new_state->crtc, new_state->fb); @@ -79,9 +96,9 @@ static void omap_plane_atomic_update(struct drm_plane *plane, /* update scanout: */ omap_framebuffer_update_scanout(new_state->fb, new_state, &info); - DBG("%dx%d -> %dx%d (%d)", info.width, info.height, - info.out_width, info.out_height, - info.screen_width); + DBG("%s: %dx%d -> %dx%d (%d)", + new_omap_state->overlay->name, info.width, info.height, + info.out_width, info.out_height, info.screen_width); DBG("%d,%d %pad %pad", info.pos_x, info.pos_y, &info.paddr, &info.p_uv_addr); @@ -102,16 +119,26 @@ static void omap_plane_atomic_update(struct drm_plane *plane, static void omap_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state) { - struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, - plane); struct omap_drm_private *priv = plane->dev->dev_private; struct omap_plane *omap_plane = to_omap_plane(plane); - enum omap_plane_id ovl_id = omap_plane->overlay->id; + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, + plane); + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); + struct omap_plane_state *new_omap_state; + struct omap_plane_state *old_omap_state; + + new_omap_state = to_omap_plane_state(new_state); + old_omap_state = to_omap_plane_state(old_state); + + if (!old_omap_state->overlay) + return; new_state->rotation = DRM_MODE_ROTATE_0; new_state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id; - dispc_ovl_enable(priv->dispc, ovl_id, false); + omap_overlay_update_state(priv, old_omap_state->overlay); + new_omap_state->overlay = NULL; } #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) @@ -121,32 +148,37 @@ static int omap_plane_atomic_check(struct drm_plane *plane, { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, + plane); struct omap_drm_private *priv = plane->dev->dev_private; + struct omap_plane_state *omap_state = to_omap_plane_state(new_plane_state); + struct omap_global_state *omap_overlay_global_state; struct drm_crtc_state *crtc_state; + bool new_hw_overlay = false; u32 max_width, max_height; + struct drm_crtc *crtc; u16 width, height; + u32 caps = 0; + u32 fourcc; int ret; - if (!new_plane_state->fb) - return 0; + omap_overlay_global_state = omap_get_global_state(state); + if (IS_ERR(omap_overlay_global_state)) + return PTR_ERR(omap_overlay_global_state); dispc_ovl_get_max_size(priv->dispc, &width, &height); max_width = width << 16; max_height = height << 16; - /* crtc should only be NULL when disabling (i.e., !new_plane_state->fb) */ - if (WARN_ON(!new_plane_state->crtc)) + crtc = new_plane_state->crtc ? new_plane_state->crtc : plane->state->crtc; + if (!crtc) return 0; - crtc_state = drm_atomic_get_existing_crtc_state(state, - new_plane_state->crtc); + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); /* we should have a crtc state if the plane is attached to a crtc */ if (WARN_ON(!crtc_state)) return 0; - if (!crtc_state->enable) - return 0; - /* * Note: these are just sanity checks to filter out totally bad scaling * factors. The real limits must be calculated case by case, and @@ -159,6 +191,15 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (ret) return ret; + DBG("%s: visible %d -> %d", plane->name, + old_plane_state->visible, new_plane_state->visible); + + if (!new_plane_state->visible) { + omap_overlay_release(state, omap_state->overlay); + omap_state->overlay = NULL; + return 0; + } + if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0) return -EINVAL; @@ -179,6 +220,43 @@ static int omap_plane_atomic_check(struct drm_plane *plane, !omap_framebuffer_supports_rotation(new_plane_state->fb)) return -EINVAL; + if ((new_plane_state->src_w >> 16) != new_plane_state->crtc_w || + (new_plane_state->src_h >> 16) != new_plane_state->crtc_h) + caps |= OMAP_DSS_OVL_CAP_SCALE; + + fourcc = new_plane_state->fb->format->format; + + /* + * (re)allocate hw overlay if we don't have one or + * there is a caps mismatch + */ + if (!omap_state->overlay || (caps & ~omap_state->overlay->caps)) { + new_hw_overlay = true; + } else { + /* check supported format */ + if (!dispc_ovl_color_mode_supported(priv->dispc, omap_state->overlay->id, + fourcc)) + new_hw_overlay = true; + } + + if (new_hw_overlay) { + struct omap_hw_overlay *old_ovl = omap_state->overlay; + struct omap_hw_overlay *new_ovl = NULL; + + omap_overlay_release(state, old_ovl); + + ret = omap_overlay_assign(state, plane, caps, fourcc, &new_ovl); + if (ret) { + DBG("%s: failed to assign hw_overlay", plane->name); + omap_state->overlay = NULL; + return ret; + } + + omap_state->overlay = new_ovl; + } + + DBG("plane: %s overlay_id: %d", plane->name, omap_state->overlay->id); + return 0; } @@ -252,17 +330,21 @@ static void omap_plane_reset(struct drm_plane *plane) static struct drm_plane_state * omap_plane_atomic_duplicate_state(struct drm_plane *plane) { - struct omap_plane_state *state; + struct omap_plane_state *state, *current_state; if (WARN_ON(!plane->state)) return NULL; + current_state = to_omap_plane_state(plane->state); + state = kmalloc(sizeof(*state), GFP_KERNEL); if (!state) return NULL; __drm_atomic_helper_plane_duplicate_state(plane, &state->base); + state->overlay = current_state->overlay; + return &state->base; } @@ -344,12 +426,11 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, return ERR_PTR(-ENOMEM); omap_plane->id = idx; - omap_plane->overlay = priv->overlays[idx]; DBG("%d: type=%d", omap_plane->id, type); DBG(" crtc_mask: 0x%04x", possible_crtcs); - formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->overlay->id); + formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->id); for (nformats = 0; formats[nformats]; ++nformats) ; -- cgit v1.2.3 From 19e2d2669dacfd3783b6f948bf06a109a7cd668d Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:27 +0100 Subject: drm/omap: add plane_atomic_print_state support Now that we added specific item to our subclassed drm_plane_state we can add omap_plane_atomic_print_state() helper to dump out our own driver specific plane state. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-9-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_plane.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index ce5ed45401fb..23b752d837a4 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -348,6 +348,19 @@ omap_plane_atomic_duplicate_state(struct drm_plane *plane) return &state->base; } +static void omap_plane_atomic_print_state(struct drm_printer *p, + const struct drm_plane_state *state) +{ + struct omap_plane_state *omap_state = to_omap_plane_state(state); + + if (omap_state->overlay) + drm_printf(p, "\toverlay=%s (caps=0x%x)\n", + omap_state->overlay->name, + omap_state->overlay->caps); + else + drm_printf(p, "\toverlay=None\n"); +} + static int omap_plane_atomic_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, @@ -387,6 +400,7 @@ static const struct drm_plane_funcs omap_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_set_property = omap_plane_atomic_set_property, .atomic_get_property = omap_plane_atomic_get_property, + .atomic_print_state = omap_plane_atomic_print_state, }; static bool omap_plane_supports_yuv(struct drm_plane *plane) -- cgit v1.2.3 From e02b5cc9e898ad6f223a69df63397beae60390ff Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 17 Nov 2021 15:19:28 +0100 Subject: drm/omap: Add a 'right overlay' to plane state If the drm_plane has a source width that's greater than the max width supported by a single hw overlay, then we assign a 'r_overlay' to it in omap_plane_atomic_check(). Both overlays should have the capabilities required to handle the source framebuffer. The only parameters that vary between the left and right hwoverlays are the src_w, crtc_w, src_x and crtc_x as we just even chop the fb into left and right halves. We also take care of not creating odd width size when dealing with YUV formats. Since both halves need to be 'appear' side by side the zpos is recalculated when dealing with dual overlay cases so that the other planes zpos is consistent. Depending on user space usage it is possible that on occasion the number of requested planes exceeds the numbers of overlays required to display them. In that case a failure would be returned for the plane that cannot be handled at that time. It is up to user space to make sure the H/W resource are not over-subscribed. Signed-off-by: Benoit Parrot Signed-off-by: Neil Armstrong Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-10-narmstrong@baylibre.com --- drivers/gpu/drm/omapdrm/omap_drv.c | 98 ++++++++++++++++++++++++++- drivers/gpu/drm/omapdrm/omap_fb.c | 33 +++++++++- drivers/gpu/drm/omapdrm/omap_fb.h | 4 +- drivers/gpu/drm/omapdrm/omap_overlay.c | 23 ++++++- drivers/gpu/drm/omapdrm/omap_overlay.h | 3 +- drivers/gpu/drm/omapdrm/omap_plane.c | 117 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/omapdrm/omap_plane.h | 1 + 7 files changed, 267 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 44a9dcb3100c..2720a58ccd90 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -117,6 +117,102 @@ static void omap_atomic_commit_tail(struct drm_atomic_state *old_state) dispc_runtime_put(priv->dispc); } +static int drm_atomic_state_normalized_zpos_cmp(const void *a, const void *b) +{ + const struct drm_plane_state *sa = *(struct drm_plane_state **)a; + const struct drm_plane_state *sb = *(struct drm_plane_state **)b; + + if (sa->normalized_zpos != sb->normalized_zpos) + return sa->normalized_zpos - sb->normalized_zpos; + else + return sa->plane->base.id - sb->plane->base.id; +} + +/* + * This replaces the drm_atomic_normalize_zpos to handle the dual overlay case. + * + * Since both halves need to be 'appear' side by side the zpos is + * recalculated when dealing with dual overlay cases so that the other + * planes zpos is consistent. + */ +static int omap_atomic_update_normalize_zpos(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *old_state, *new_state; + struct drm_plane *plane; + int c, i, n, inc; + int total_planes = dev->mode_config.num_total_plane; + struct drm_plane_state **states; + int ret = 0; + + states = kmalloc_array(total_planes, sizeof(*states), GFP_KERNEL); + if (!states) + return -ENOMEM; + + for_each_oldnew_crtc_in_state(state, crtc, old_state, new_state, c) { + if (old_state->plane_mask == new_state->plane_mask && + !new_state->zpos_changed) + continue; + + /* Reset plane increment and index value for every crtc */ + n = 0; + + /* + * Normalization process might create new states for planes + * which normalized_zpos has to be recalculated. + */ + drm_for_each_plane_mask(plane, dev, new_state->plane_mask) { + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(new_state->state, + plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto done; + } + states[n++] = plane_state; + } + + sort(states, n, sizeof(*states), + drm_atomic_state_normalized_zpos_cmp, NULL); + + for (i = 0, inc = 0; i < n; i++) { + plane = states[i]->plane; + + states[i]->normalized_zpos = i + inc; + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] updated normalized zpos value %d\n", + plane->base.id, plane->name, + states[i]->normalized_zpos); + + if (is_omap_plane_dual_overlay(states[i])) + inc++; + } + new_state->zpos_changed = true; + } + +done: + kfree(states); + return ret; +} + +static int omap_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + int ret; + + ret = drm_atomic_helper_check(dev, state); + if (ret) + return ret; + + if (dev->mode_config.normalize_zpos) { + ret = omap_atomic_update_normalize_zpos(dev, state); + if (ret) + return ret; + } + + return 0; +} + static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = { .atomic_commit_tail = omap_atomic_commit_tail, }; @@ -124,7 +220,7 @@ static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = static const struct drm_mode_config_funcs omap_mode_config_funcs = { .fb_create = omap_framebuffer_create, .output_poll_changed = drm_fb_helper_output_poll_changed, - .atomic_check = drm_atomic_helper_check, + .atomic_check = omap_atomic_check, .atomic_commit = drm_atomic_helper_commit, }; diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 190afc564914..895e66b08a81 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -131,7 +131,9 @@ static u32 drm_rotation_to_tiler(unsigned int drm_rot) /* update ovl info for scanout, handles cases of multi-planar fb's, etc. */ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, - struct drm_plane_state *state, struct omap_overlay_info *info) + struct drm_plane_state *state, + struct omap_overlay_info *info, + struct omap_overlay_info *r_info) { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); const struct drm_format_info *format = omap_fb->format; @@ -218,6 +220,35 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, } else { info->p_uv_addr = 0; } + + if (r_info) { + info->width /= 2; + info->out_width /= 2; + + *r_info = *info; + + if (fb->format->is_yuv) { + if (info->width & 1) { + info->width++; + r_info->width--; + } + + if (info->out_width & 1) { + info->out_width++; + r_info->out_width--; + } + } + + r_info->pos_x = info->pos_x + info->out_width; + + r_info->paddr = get_linear_addr(fb, format, 0, + x + info->width, y); + if (fb->format->format == DRM_FORMAT_NV12) { + r_info->p_uv_addr = + get_linear_addr(fb, format, 1, + x + info->width, y); + } + } } /* pin, prepare for scanout: */ diff --git a/drivers/gpu/drm/omapdrm/omap_fb.h b/drivers/gpu/drm/omapdrm/omap_fb.h index c0e19aed8220..b75f0b5ef1d8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.h +++ b/drivers/gpu/drm/omapdrm/omap_fb.h @@ -26,7 +26,9 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, int omap_framebuffer_pin(struct drm_framebuffer *fb); void omap_framebuffer_unpin(struct drm_framebuffer *fb); void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, - struct drm_plane_state *state, struct omap_overlay_info *info); + struct drm_plane_state *state, + struct omap_overlay_info *info, + struct omap_overlay_info *r_info); bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb); void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m); diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.c b/drivers/gpu/drm/omapdrm/omap_overlay.c index afb2b44fdf86..10730c9b2752 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.c +++ b/drivers/gpu/drm/omapdrm/omap_overlay.c @@ -67,12 +67,13 @@ omap_plane_find_free_overlay(struct drm_device *dev, struct drm_plane *hwoverlay * next global overlay_map to be enabled when atomic transaction is valid. */ int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, - u32 caps, u32 fourcc, struct omap_hw_overlay **overlay) + u32 caps, u32 fourcc, struct omap_hw_overlay **overlay, + struct omap_hw_overlay **r_overlay) { /* Get the global state of the current atomic transaction */ struct omap_global_state *state = omap_get_global_state(s); struct drm_plane **overlay_map = state->hwoverlay_to_plane; - struct omap_hw_overlay *ovl; + struct omap_hw_overlay *ovl, *r_ovl; ovl = omap_plane_find_free_overlay(s->dev, overlay_map, caps, fourcc); if (!ovl) @@ -81,8 +82,26 @@ int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, overlay_map[ovl->idx] = plane; *overlay = ovl; + if (r_overlay) { + r_ovl = omap_plane_find_free_overlay(s->dev, overlay_map, + caps, fourcc); + if (!r_ovl) { + overlay_map[r_ovl->idx] = NULL; + *overlay = NULL; + return -ENOMEM; + } + + overlay_map[r_ovl->idx] = plane; + *r_overlay = r_ovl; + } + DBG("%s: assign to plane %s caps %x", ovl->name, plane->name, caps); + if (r_overlay) { + DBG("%s: assign to right of plane %s caps %x", + r_ovl->name, plane->name, caps); + } + return 0; } diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.h b/drivers/gpu/drm/omapdrm/omap_overlay.h index 38ca55e1e2d7..e36a43f35563 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.h +++ b/drivers/gpu/drm/omapdrm/omap_overlay.h @@ -28,7 +28,8 @@ struct omap_hw_overlay { int omap_hwoverlays_init(struct omap_drm_private *priv); void omap_hwoverlays_destroy(struct omap_drm_private *priv); int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, - u32 caps, u32 fourcc, struct omap_hw_overlay **overlay); + u32 caps, u32 fourcc, struct omap_hw_overlay **overlay, + struct omap_hw_overlay **r_overlay); void omap_overlay_release(struct drm_atomic_state *s, struct omap_hw_overlay *overlay); void omap_overlay_update_state(struct omap_drm_private *priv, struct omap_hw_overlay *overlay); #endif /* __OMAPDRM_OVERLAY_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 23b752d837a4..b35205c4e979 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -24,6 +24,7 @@ struct omap_plane_state { struct drm_plane_state base; struct omap_hw_overlay *overlay; + struct omap_hw_overlay *r_overlay; /* right overlay */ }; #define to_omap_plane(x) container_of(x, struct omap_plane, base) @@ -33,6 +34,13 @@ struct omap_plane { enum omap_plane_id id; }; +bool is_omap_plane_dual_overlay(struct drm_plane_state *state) +{ + struct omap_plane_state *omap_state = to_omap_plane_state(state); + + return !!omap_state->r_overlay; +} + static int omap_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { @@ -61,16 +69,21 @@ static void omap_plane_atomic_update(struct drm_plane *plane, plane); struct omap_plane_state *new_omap_state; struct omap_plane_state *old_omap_state; - struct omap_overlay_info info; - enum omap_plane_id ovl_id; + struct omap_overlay_info info, r_info; + enum omap_plane_id ovl_id, r_ovl_id; int ret; + bool dual_ovl; new_omap_state = to_omap_plane_state(new_state); old_omap_state = to_omap_plane_state(old_state); + dual_ovl = is_omap_plane_dual_overlay(new_state); + /* Cleanup previously held overlay if needed */ if (old_omap_state->overlay) omap_overlay_update_state(priv, old_omap_state->overlay); + if (old_omap_state->r_overlay) + omap_overlay_update_state(priv, old_omap_state->r_overlay); if (!new_omap_state->overlay) { DBG("[PLANE:%d:%s] no overlay attached", plane->base.id, plane->name); @@ -93,8 +106,11 @@ static void omap_plane_atomic_update(struct drm_plane *plane, info.color_encoding = new_state->color_encoding; info.color_range = new_state->color_range; + r_info = info; + /* update scanout: */ - omap_framebuffer_update_scanout(new_state->fb, new_state, &info); + omap_framebuffer_update_scanout(new_state->fb, new_state, &info, + dual_ovl ? &r_info : NULL); DBG("%s: %dx%d -> %dx%d (%d)", new_omap_state->overlay->name, info.width, info.height, @@ -102,6 +118,23 @@ static void omap_plane_atomic_update(struct drm_plane *plane, DBG("%d,%d %pad %pad", info.pos_x, info.pos_y, &info.paddr, &info.p_uv_addr); + if (dual_ovl) { + r_ovl_id = new_omap_state->r_overlay->id; + /* + * If the current plane uses 2 hw planes the very next + * zorder is used by the r_overlay so we just use the + * main overlay zorder + 1 + */ + r_info.zorder = info.zorder + 1; + + DBG("%s: %dx%d -> %dx%d (%d)", + new_omap_state->r_overlay->name, + r_info.width, r_info.height, + r_info.out_width, r_info.out_height, r_info.screen_width); + DBG("%d,%d %pad %pad", r_info.pos_x, r_info.pos_y, + &r_info.paddr, &r_info.p_uv_addr); + } + /* and finally, update omapdss: */ ret = dispc_ovl_setup(priv->dispc, ovl_id, &info, omap_crtc_timings(new_state->crtc), false, @@ -114,6 +147,21 @@ static void omap_plane_atomic_update(struct drm_plane *plane, } dispc_ovl_enable(priv->dispc, ovl_id, true); + + if (dual_ovl) { + ret = dispc_ovl_setup(priv->dispc, r_ovl_id, &r_info, + omap_crtc_timings(new_state->crtc), false, + omap_crtc_channel(new_state->crtc)); + if (ret) { + dev_err(plane->dev->dev, "Failed to setup plane right-overlay %s\n", + plane->name); + dispc_ovl_enable(priv->dispc, r_ovl_id, false); + dispc_ovl_enable(priv->dispc, ovl_id, false); + return; + } + + dispc_ovl_enable(priv->dispc, r_ovl_id, true); + } } static void omap_plane_atomic_disable(struct drm_plane *plane, @@ -139,6 +187,11 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, omap_overlay_update_state(priv, old_omap_state->overlay); new_omap_state->overlay = NULL; + + if (is_omap_plane_dual_overlay(old_state)) { + omap_overlay_update_state(priv, old_omap_state->r_overlay); + new_omap_state->r_overlay = NULL; + } } #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) @@ -154,6 +207,7 @@ static int omap_plane_atomic_check(struct drm_plane *plane, struct omap_plane_state *omap_state = to_omap_plane_state(new_plane_state); struct omap_global_state *omap_overlay_global_state; struct drm_crtc_state *crtc_state; + bool new_r_hw_overlay = false; bool new_hw_overlay = false; u32 max_width, max_height; struct drm_crtc *crtc; @@ -196,7 +250,9 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (!new_plane_state->visible) { omap_overlay_release(state, omap_state->overlay); + omap_overlay_release(state, omap_state->r_overlay); omap_state->overlay = NULL; + omap_state->r_overlay = NULL; return 0; } @@ -213,8 +269,30 @@ static int omap_plane_atomic_check(struct drm_plane *plane, if (new_plane_state->src_h > max_height || new_plane_state->crtc_h > height) return -EINVAL; - if (new_plane_state->src_w > max_width || new_plane_state->crtc_w > width) - return -EINVAL; + + if (new_plane_state->src_w > max_width || new_plane_state->crtc_w > width) { + bool is_fourcc_yuv = new_plane_state->fb->format->is_yuv; + + if (is_fourcc_yuv && (((new_plane_state->src_w >> 16) / 2 & 1) || + new_plane_state->crtc_w / 2 & 1)) { + /* + * When calculating the split overlay width + * and it yield an odd value we will need to adjust + * the indivual width +/- 1. So make sure it fits + */ + if (new_plane_state->src_w <= ((2 * width - 1) << 16) && + new_plane_state->crtc_w <= (2 * width - 1)) + new_r_hw_overlay = true; + else + return -EINVAL; + } else { + if (new_plane_state->src_w <= (2 * max_width) && + new_plane_state->crtc_w <= (2 * width)) + new_r_hw_overlay = true; + else + return -EINVAL; + } + } if (new_plane_state->rotation != DRM_MODE_ROTATE_0 && !omap_framebuffer_supports_rotation(new_plane_state->fb)) @@ -239,24 +317,44 @@ static int omap_plane_atomic_check(struct drm_plane *plane, new_hw_overlay = true; } + /* + * check if we need two overlays and only have 1 or + * if we had 2 overlays but will only need 1 + */ + if ((new_r_hw_overlay && !omap_state->r_overlay) || + (!new_r_hw_overlay && omap_state->r_overlay)) + new_hw_overlay = true; + if (new_hw_overlay) { struct omap_hw_overlay *old_ovl = omap_state->overlay; + struct omap_hw_overlay *old_r_ovl = omap_state->r_overlay; struct omap_hw_overlay *new_ovl = NULL; + struct omap_hw_overlay *new_r_ovl = NULL; omap_overlay_release(state, old_ovl); + omap_overlay_release(state, old_r_ovl); - ret = omap_overlay_assign(state, plane, caps, fourcc, &new_ovl); + ret = omap_overlay_assign(state, plane, caps, fourcc, &new_ovl, + new_r_hw_overlay ? &new_r_ovl : NULL); if (ret) { DBG("%s: failed to assign hw_overlay", plane->name); omap_state->overlay = NULL; + omap_state->r_overlay = NULL; return ret; } omap_state->overlay = new_ovl; + if (new_r_hw_overlay) + omap_state->r_overlay = new_r_ovl; + else + omap_state->r_overlay = NULL; } DBG("plane: %s overlay_id: %d", plane->name, omap_state->overlay->id); + if (omap_state->r_overlay) + DBG("plane: %s r_overlay_id: %d", plane->name, omap_state->r_overlay->id); + return 0; } @@ -344,6 +442,7 @@ omap_plane_atomic_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &state->base); state->overlay = current_state->overlay; + state->r_overlay = current_state->r_overlay; return &state->base; } @@ -359,6 +458,12 @@ static void omap_plane_atomic_print_state(struct drm_printer *p, omap_state->overlay->caps); else drm_printf(p, "\toverlay=None\n"); + if (omap_state->r_overlay) + drm_printf(p, "\tr_overlay=%s (caps=0x%x)\n", + omap_state->r_overlay->name, + omap_state->r_overlay->caps); + else + drm_printf(p, "\tr_overlay=None\n"); } static int omap_plane_atomic_set_property(struct drm_plane *plane, diff --git a/drivers/gpu/drm/omapdrm/omap_plane.h b/drivers/gpu/drm/omapdrm/omap_plane.h index 0c28fe8ffa20..a9a33e12722a 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.h +++ b/drivers/gpu/drm/omapdrm/omap_plane.h @@ -22,5 +22,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, u32 possible_crtcs); void omap_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); +bool is_omap_plane_dual_overlay(struct drm_plane_state *state); #endif /* __OMAPDRM_PLANE_H__ */ -- cgit v1.2.3 From d6c75c295f67b26fad8ba2e72db80e0f744e9da9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 5 Dec 2021 14:15:56 +0100 Subject: omapdrm: dss: mark runtime PM functions __maybe_unused Using the SET_RUNTIME_PM_OPS() macro causes a warning about the referenced functions when they are marked static but not __maybe_unused: drivers/gpu/drm/omapdrm/dss/dss.c:1572:12: error: unused function 'dss_runtime_suspend' [-Werror,-Wunused-function] drivers/gpu/drm/omapdrm/dss/dss.c:1584:12: error: unused function 'dss_runtime_resume' [-Werror,-Wunused-function] drivers/gpu/drm/omapdrm/dss/dispc.c:4845:12: error: unused function 'dispc_runtime_suspend' [-Werror,-Wunused-function] drivers/gpu/drm/omapdrm/dss/dispc.c:4860:12: error: unused function 'dispc_runtime_resume' [-Werror,-Wunused-function] Fixes: b92f7ea556f8 ("drm/omap: dss: Make use of the helper macro SET_RUNTIME_PM_OPS()") Signed-off-by: Arnd Bergmann Reviewed-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20211205131612.3192652-1-arnd@kernel.org --- drivers/gpu/drm/omapdrm/dss/dispc.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/dss.c | 4 ++-- drivers/gpu/drm/omapdrm/dss/venc.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 2da4d36a3446..c4de142cc85b 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -4869,7 +4869,7 @@ static int dispc_remove(struct platform_device *pdev) return 0; } -static int dispc_runtime_suspend(struct device *dev) +static __maybe_unused int dispc_runtime_suspend(struct device *dev) { struct dispc_device *dispc = dev_get_drvdata(dev); @@ -4884,7 +4884,7 @@ static int dispc_runtime_suspend(struct device *dev) return 0; } -static int dispc_runtime_resume(struct device *dev) +static __maybe_unused int dispc_runtime_resume(struct device *dev) { struct dispc_device *dispc = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index d730bf67fed9..a6845856cbce 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5058,7 +5058,7 @@ static int dsi_remove(struct platform_device *pdev) return 0; } -static int dsi_runtime_suspend(struct device *dev) +static __maybe_unused int dsi_runtime_suspend(struct device *dev) { struct dsi_data *dsi = dev_get_drvdata(dev); @@ -5071,7 +5071,7 @@ static int dsi_runtime_suspend(struct device *dev) return 0; } -static int dsi_runtime_resume(struct device *dev) +static __maybe_unused int dsi_runtime_resume(struct device *dev) { struct dsi_data *dsi = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 66db28bfe824..69b3e15b9356 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1569,7 +1569,7 @@ static void dss_shutdown(struct platform_device *pdev) DSSDBG("shutdown\n"); } -static int dss_runtime_suspend(struct device *dev) +static __maybe_unused int dss_runtime_suspend(struct device *dev) { struct dss_device *dss = dev_get_drvdata(dev); @@ -1581,7 +1581,7 @@ static int dss_runtime_suspend(struct device *dev) return 0; } -static int dss_runtime_resume(struct device *dev) +static __maybe_unused int dss_runtime_resume(struct device *dev) { struct dss_device *dss = dev_get_drvdata(dev); int r; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 508fddd376cf..4480b69ab5a7 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -879,7 +879,7 @@ static int venc_remove(struct platform_device *pdev) return 0; } -static int venc_runtime_suspend(struct device *dev) +static __maybe_unused int venc_runtime_suspend(struct device *dev) { struct venc_device *venc = dev_get_drvdata(dev); @@ -889,7 +889,7 @@ static int venc_runtime_suspend(struct device *dev) return 0; } -static int venc_runtime_resume(struct device *dev) +static __maybe_unused int venc_runtime_resume(struct device *dev) { struct venc_device *venc = dev_get_drvdata(dev); -- cgit v1.2.3 From 03848335b5b1faa4a4641fcf30b7c233579a45aa Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 7 Dec 2021 13:57:52 -0800 Subject: drm/bridge: sn65dsi86: defer if there is no dsi host Otherwise we don't get another shot at it if the bridge probes before the dsi host is registered. It seems like this is what *most* (but not all) of the other bridges do. It looks like this was missed in the conversion to attach dsi host at probe time. Fixes: c3b75d4734cb ("drm/bridge: sn65dsi86: Register and attach our DSI device at probe") Signed-off-by: Rob Clark Reviewed-by: Doug Anderson Tested-by: Doug Anderson Reviewed-by: Stephen Boyd [dianders: squashed in Stephen's simplification] Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20211207215753.635841-1-robdclark@gmail.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 02b490671f8f..c9452eec968b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -704,7 +704,7 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge) static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) { - int ret, val; + int val; struct mipi_dsi_host *host; struct mipi_dsi_device *dsi; struct device *dev = pdata->dev; @@ -714,16 +714,12 @@ static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) }; host = of_find_mipi_dsi_host_by_node(pdata->host_node); - if (!host) { - DRM_ERROR("failed to find dsi host\n"); - return -ENODEV; - } + if (!host) + return -EPROBE_DEFER; dsi = devm_mipi_dsi_device_register_full(dev, host, &info); - if (IS_ERR(dsi)) { - DRM_ERROR("failed to create dsi device\n"); + if (IS_ERR(dsi)) return PTR_ERR(dsi); - } /* TODO: setting to 4 MIPI lanes always for now */ dsi->lanes = 4; @@ -739,13 +735,7 @@ static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) pdata->dsi = dsi; - ret = devm_mipi_dsi_attach(dev, dsi); - if (ret < 0) { - DRM_ERROR("failed to attach dsi to host\n"); - return ret; - } - - return 0; + return devm_mipi_dsi_attach(dev, dsi); } static int ti_sn_bridge_attach(struct drm_bridge *bridge, @@ -1267,8 +1257,10 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, drm_bridge_add(&pdata->bridge); ret = ti_sn_attach_host(pdata); - if (ret) + if (ret) { + dev_err_probe(pdata->dev, ret, "failed to attach dsi host\n"); goto err_remove_bridge; + } return 0; -- cgit v1.2.3