komeda display HWs have kinds of coefficient tables for various purposes like gamma/degamma. ususally these tables are shared by multiple HW component and have limited number. Introduce komeda_coeffs_table/manager for describing and managing these tables, like table reuse, racing. Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@xxxxxxx> --- drivers/gpu/drm/arm/display/komeda/Makefile | 1 + .../drm/arm/display/komeda/komeda_coeffs.c | 119 ++++++++++++++++++ .../drm/arm/display/komeda/komeda_coeffs.h | 74 +++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_coeffs.c create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_coeffs.h diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile index 73b8e8be1862..e853c1c499c9 100644 --- a/drivers/gpu/drm/arm/display/komeda/Makefile +++ b/drivers/gpu/drm/arm/display/komeda/Makefile @@ -8,6 +8,7 @@ komeda-y := \ komeda_drv.o \ komeda_dev.o \ komeda_format_caps.o \ + komeda_coeffs.o \ komeda_color_mgmt.o \ komeda_pipeline.o \ komeda_pipeline_state.o \ diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.c b/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.c new file mode 100644 index 000000000000..d9d35e23003c --- /dev/null +++ b/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. + * Author: James.Qian.Wang <james.qian.wang@xxxxxxx> + * + */ +#include <linux/slab.h> +#include "komeda_coeffs.h" + +static inline bool is_table_in_using(struct komeda_coeffs_table *table) +{ + return refcount_read(&table->refcount) > 1; +} + +/* request a coeffs table for the coeffs data specified by argument coeffs */ +struct komeda_coeffs_table * +komeda_coeffs_request(struct komeda_coeffs_manager *mgr, void *coeffs) +{ + struct komeda_coeffs_table *table; + u32 i; + + mutex_lock(&mgr->mutex); + + /* search table list to find if there is a in-using table with the + * same coefficient content, if find, reuse this table. + */ + for (i = 0; i < mgr->n_tables; i++) { + table = mgr->tables[i]; + + /* skip the unused table */ + if (!is_table_in_using(table)) + continue; + + if (!memcmp(table->coeffs, coeffs, mgr->coeffs_sz)) + goto found; + } + + /* can not reuse the existing in-using table, loop for a new one */ + for (i = 0; i < mgr->n_tables; i++) { + table = mgr->tables[i]; + + if (!is_table_in_using(table)) { + memcpy(table->coeffs, coeffs, mgr->coeffs_sz); + table->needs_update = true; + goto found; + } + } + + /* Since previous two search loop will directly goto found if found an + * available table, so once program ran here means search failed. + * clear the table to NULL, unlock(mgr->mutex) and return NULL. + */ + table = NULL; + +found: + komeda_coeffs_get(table); + mutex_unlock(&mgr->mutex); + return table; +} + +/* Add a coeffs table to manager */ +int komeda_coeffs_add(struct komeda_coeffs_manager *mgr, + u32 hw_id, u32 __iomem *reg, + void (*update)(struct komeda_coeffs_table *table)) +{ + struct komeda_coeffs_table *table; + + if (mgr->n_tables >= ARRAY_SIZE(mgr->tables)) + return -ENOSPC; + + table = kzalloc(sizeof(*table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + table->coeffs = kzalloc(mgr->coeffs_sz, GFP_KERNEL); + if (!table->coeffs) { + kfree(table); + return -ENOMEM; + } + + refcount_set(&table->refcount, 1); + table->mgr = mgr; + table->hw_id = hw_id; + table->update = update; + table->reg = reg; + + mgr->tables[mgr->n_tables++] = table; + return 0; +} + +struct komeda_coeffs_manager *komeda_coeffs_create_manager(u32 coeffs_sz) +{ + struct komeda_coeffs_manager *mgr; + + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return ERR_PTR(-ENOMEM); + + mutex_init(&mgr->mutex); + mgr->coeffs_sz = coeffs_sz; + + return mgr; +} + +void komeda_coeffs_destroy_manager(struct komeda_coeffs_manager *mgr) +{ + u32 i; + + if (!mgr) + return; + + for (i = 0; i < mgr->n_tables; i++) { + WARN_ON(is_table_in_using(mgr->tables[i])); + kfree(mgr->tables[i]->coeffs); + kfree(mgr->tables[i]); + } + + kfree(mgr); +} diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.h b/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.h new file mode 100644 index 000000000000..172ac2ea17ba --- /dev/null +++ b/drivers/gpu/drm/arm/display/komeda/komeda_coeffs.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. + * Author: James.Qian.Wang <james.qian.wang@xxxxxxx> + * + */ +#ifndef _KOMEDA_COEFFS_H_ +#define _KOMEDA_COEFFS_H_ + +#include <linux/refcount.h> + +/* Komeda display HWs have kinds of coefficient tables for various purposes, + * like gamma/degamma. ususally these tables are shared by multiple HW component + * and limited number. + * The komeda_coeffs_table/manager are imported for describing and managing + * these tables for table reuse and racing. + */ +struct komeda_coeffs_table { + struct komeda_coeffs_manager *mgr; + refcount_t refcount; + bool needs_update; + u32 hw_id; + void *coeffs; + u32 __iomem *reg; + void (*update)(struct komeda_coeffs_table *table); +}; + +struct komeda_coeffs_manager { + struct mutex mutex; /* for tables accessing */ + u32 n_tables; + u32 coeffs_sz; + struct komeda_coeffs_table *tables[8]; +}; + +static inline struct komeda_coeffs_table * +komeda_coeffs_get(struct komeda_coeffs_table *table) +{ + if (table) + refcount_inc(&table->refcount); + + return table; +} + +static inline void __komeda_coeffs_put(struct komeda_coeffs_table *table) +{ + if (table) + refcount_dec(&table->refcount); +} + +#define komeda_coeffs_put(table) \ +do { \ + __komeda_coeffs_put(table); \ + (table) = NULL; \ +} while (0) + +static inline void komeda_coeffs_update(struct komeda_coeffs_table *table) +{ + if (!table || !table->needs_update) + return; + + table->update(table); + table->needs_update = false; +} + +struct komeda_coeffs_manager *komeda_coeffs_create_manager(u32 coeffs_sz); +void komeda_coeffs_destroy_manager(struct komeda_coeffs_manager *mgr); + +int komeda_coeffs_add(struct komeda_coeffs_manager *mgr, + u32 hw_id, u32 __iomem *reg, + void (*update)(struct komeda_coeffs_table *table)); +struct komeda_coeffs_table * +komeda_coeffs_request(struct komeda_coeffs_manager *mgr, void *coeffs); + +#endif /*_KOMEDA_COEFFS_H_*/ -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel