| /* |
| * Copyright (c) 2019, Linaro Limited |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/drivers/video.h> |
| |
| #if defined(CONFIG_VIDEO_BUFFER_USE_SHARED_MULTI_HEAP) |
| #include <zephyr/multi_heap/shared_multi_heap.h> |
| |
| #define VIDEO_COMMON_HEAP_ALLOC(align, size, timeout) \ |
| shared_multi_heap_aligned_alloc(CONFIG_VIDEO_BUFFER_SMH_ATTRIBUTE, align, size) |
| #define VIDEO_COMMON_FREE(block) shared_multi_heap_free(block) |
| #else |
| K_HEAP_DEFINE(video_buffer_pool, CONFIG_VIDEO_BUFFER_POOL_SZ_MAX*CONFIG_VIDEO_BUFFER_POOL_NUM_MAX); |
| #define VIDEO_COMMON_HEAP_ALLOC(align, size, timeout) \ |
| k_heap_aligned_alloc(&video_buffer_pool, align, size, timeout); |
| #define VIDEO_COMMON_FREE(block) k_heap_free(&video_buffer_pool, block) |
| #endif |
| |
| static struct video_buffer video_buf[CONFIG_VIDEO_BUFFER_POOL_NUM_MAX]; |
| |
| struct mem_block { |
| void *data; |
| }; |
| |
| static struct mem_block video_block[CONFIG_VIDEO_BUFFER_POOL_NUM_MAX]; |
| |
| struct video_buffer *video_buffer_aligned_alloc(size_t size, size_t align) |
| { |
| struct video_buffer *vbuf = NULL; |
| struct mem_block *block; |
| int i; |
| |
| /* find available video buffer */ |
| for (i = 0; i < ARRAY_SIZE(video_buf); i++) { |
| if (video_buf[i].buffer == NULL) { |
| vbuf = &video_buf[i]; |
| block = &video_block[i]; |
| break; |
| } |
| } |
| |
| if (vbuf == NULL) { |
| return NULL; |
| } |
| |
| /* Alloc buffer memory */ |
| block->data = VIDEO_COMMON_HEAP_ALLOC(align, size, K_FOREVER); |
| if (block->data == NULL) { |
| return NULL; |
| } |
| |
| vbuf->buffer = block->data; |
| vbuf->size = size; |
| vbuf->bytesused = 0; |
| |
| return vbuf; |
| } |
| |
| struct video_buffer *video_buffer_alloc(size_t size) |
| { |
| return video_buffer_aligned_alloc(size, sizeof(void *)); |
| } |
| |
| void video_buffer_release(struct video_buffer *vbuf) |
| { |
| struct mem_block *block = NULL; |
| int i; |
| |
| /* vbuf to block */ |
| for (i = 0; i < ARRAY_SIZE(video_block); i++) { |
| if (video_block[i].data == vbuf->buffer) { |
| block = &video_block[i]; |
| break; |
| } |
| } |
| |
| vbuf->buffer = NULL; |
| if (block) { |
| VIDEO_COMMON_FREE(block->data); |
| } |
| } |