123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /*
- * Copyright (c) 2020 Actions Technology Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <assert.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/atomic.h>
- #include "de_common.h"
- struct de_command_pool {
- sys_slist_t list;
- struct k_sem sem;
- struct k_spinlock lock;
- };
- struct de_instance {
- uint16_t flags;
- uint16_t sequence;
- bool waiting;
- atomic_t alloc_num;
- struct k_sem sem;
- struct k_spinlock lock;
- struct de_command_pool *pool;
- display_engine_instance_callback_t callback;
- void *user_data;
- };
- static struct de_command_entry *de_command_pool_alloc(struct de_command_pool *pool);
- static void de_command_pool_free(struct de_command_pool *pool, struct de_command_entry *entry);
- static struct de_command_entry __in_section_unique(ram.noinit.drv_de.cmd)
- de_entries[CONFIG_DISPLAY_ENGINE_DRAW_COMMAND_NUM + CONFIG_DISPLAY_ENGINE_POST_COMMAND_NUM];
- static struct de_command_pool de_draw_pool;
- #if CONFIG_DISPLAY_ENGINE_POST_COMMAND_NUM > 0
- static struct de_command_pool de_post_pool;
- #endif
- static struct de_instance de_instances[CONFIG_DISPLAY_ENGINE_INSTANCE_NUM];
- int de_alloc_instance(uint32_t flags)
- {
- for (int i = 0; i < ARRAY_SIZE(de_instances); i++) {
- if (de_instances[i].pool == NULL) {
- de_instances[i].flags = (uint16_t)flags;
- #if CONFIG_DISPLAY_ENGINE_POST_COMMAND_NUM > 0
- if (flags & DISPLAY_ENGINE_FLAG_POST) {
- de_instances[i].pool = &de_post_pool;
- } else
- #endif
- {
- de_instances[i].pool = &de_draw_pool;
- }
- k_sem_init(&de_instances[i].sem, 0, 1);
- memset(&de_instances[i].lock, 0, sizeof(de_instances[i].lock));
- return i;
- }
- }
- return -ENOBUFS;
- }
- int de_free_instance(int inst)
- {
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- memset(&de_instances[inst], 0, sizeof(de_instances[inst]));
- return 0;
- }
- bool de_instance_has_flag(int inst, uint32_t flag)
- {
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- return (de_instances[inst].flags & flag);
- }
- __de_func struct de_command_entry *de_instance_alloc_entry(int inst)
- {
- struct de_command_entry *entry;
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- if (inst < 0 || inst >= ARRAY_SIZE(de_instances) ||
- de_instances[inst].pool == NULL) {
- return NULL;
- }
- entry = de_command_pool_alloc(de_instances[inst].pool);
- assert (entry != NULL);
- if (entry) {
- entry->inst = (uint8_t)inst;
- entry->seq = de_instances[inst].sequence++;
- atomic_inc(&de_instances[inst].alloc_num);
- }
- return entry;
- }
- __de_func int de_instance_free_entry(struct de_command_entry *entry)
- {
- int inst = entry->inst;
- bool waiting;
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- atomic_dec(&de_instances[inst].alloc_num);
- k_spinlock_key_t key = k_spin_lock(&de_instances[inst].lock);
- waiting = de_instances[inst].waiting;
- k_spin_unlock(&de_instances[inst].lock, key);
- if (waiting) {
- k_sem_give(&de_instances[inst].sem);
- }
- de_command_pool_free(de_instances[inst].pool, entry);
- return 0;
- }
- __de_func int de_instance_poll(int inst, int timeout)
- {
- k_spinlock_key_t key;
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- wait_finish:
- key = k_spin_lock(&de_instances[inst].lock);
- de_instances[inst].waiting = (atomic_get(&de_instances[inst].alloc_num) > 0);
- k_spin_unlock(&de_instances[inst].lock, key);
- if (de_instances[inst].waiting) {
- k_sem_take(&de_instances[inst].sem, (timeout >= 0) ? K_MSEC(timeout) : K_FOREVER);
- de_instances[inst].waiting = 0;
- goto wait_finish;
- }
- return atomic_get(&de_instances[inst].alloc_num) ? -ETIMEDOUT : 0;
- }
- int de_instance_register_callback(int inst, display_engine_instance_callback_t callback, void *user_data)
- {
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- de_instances[inst].user_data = user_data;
- de_instances[inst].callback = callback;
- return 0;
- }
- __de_func int de_instance_notify(struct de_command_entry *entry, int status)
- {
- int inst = entry->inst;
- assert(inst >= 0 && inst < ARRAY_SIZE(de_instances));
- assert(de_instances[inst].pool != NULL);
- if (de_instances[inst].callback) {
- de_instances[inst].callback(status, entry->seq, de_instances[inst].user_data);
- }
- return 0;
- }
- static void de_command_pool_init(struct de_command_pool *pool,
- struct de_command_entry *entries, int num_entries)
- {
- sys_slist_init(&pool->list);
- for (int i = num_entries - 1; i >= 0; i--) {
- sys_slist_append(&pool->list, &entries[i].node);
- }
- k_sem_init(&pool->sem, num_entries, num_entries);
- }
- void de_command_pools_init(void)
- {
- de_command_pool_init(&de_draw_pool, de_entries, CONFIG_DISPLAY_ENGINE_DRAW_COMMAND_NUM);
- #if CONFIG_DISPLAY_ENGINE_POST_COMMAND_NUM > 0
- de_command_pool_init(&de_post_pool, &de_entries[CONFIG_DISPLAY_ENGINE_DRAW_COMMAND_NUM], CONFIG_DISPLAY_ENGINE_POST_COMMAND_NUM);
- #endif
- }
- __de_func static struct de_command_entry *de_command_pool_alloc(struct de_command_pool *pool)
- {
- sys_snode_t *node = NULL;
- k_spinlock_key_t key;
- get_free_entry:
- key = k_spin_lock(&pool->lock);
- node = sys_slist_peek_head(&pool->list);
- if (node)
- sys_slist_remove(&pool->list, NULL, node);
- k_spin_unlock(&pool->lock, key);
- if (node == NULL && !k_is_in_isr()) {
- k_sem_take(&pool->sem, K_FOREVER);
- goto get_free_entry;
- }
- assert (node != NULL);
- return CONTAINER_OF(node, struct de_command_entry, node);
- }
- __de_func static void de_command_pool_free(struct de_command_pool *pool, struct de_command_entry *entry)
- {
- bool empty;
- k_spinlock_key_t key = k_spin_lock(&pool->lock);
- empty = sys_slist_is_empty(&pool->list);
- sys_slist_append(&pool->list, &entry->node);
- k_spin_unlock(&pool->lock, key);
- if (empty) {
- k_sem_give(&pool->sem);
- }
- }
|