|
| 1 | +/* |
| 2 | + * Copyright 2025 NXP |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#include <zephyr/logging/log.h> |
| 8 | + |
| 9 | +#include "mp_zaud.h" |
| 10 | +#include "mp_zaud_buffer_pool.h" |
| 11 | + |
| 12 | +LOG_MODULE_REGISTER(mp_zaud_buffer_pool, CONFIG_LIBMP_LOG_LEVEL); |
| 13 | + |
| 14 | +static bool mp_zaud_buffer_pool_config(struct mp_buffer_pool *pool, struct mp_structure *config) |
| 15 | +{ |
| 16 | + struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool); |
| 17 | + void *aligned_buffer = NULL; |
| 18 | + |
| 19 | + int sample_rate = mp_value_get_int(mp_structure_get_value(config, "samplerate")); |
| 20 | + int bit_width = mp_value_get_int(mp_structure_get_value(config, "bitwidth")); |
| 21 | + int num_of_channel = mp_value_get_int(mp_structure_get_value(config, "numOfchannel")); |
| 22 | + uint32_t frame_interval = |
| 23 | + mp_value_get_uint(mp_structure_get_value(config, "frameinterval")); |
| 24 | + int buffer_count = mp_value_get_int(mp_structure_get_value(config, "buffercount")); |
| 25 | + |
| 26 | + /* |
| 27 | + * TEMPORARY WORKAROUND: Adding 2 extra buffers to the minimum count |
| 28 | + * |
| 29 | + * Currently adding +2 buffers beyond the requested buffer_count because |
| 30 | + * the current buffer management system requires additional buffers |
| 31 | + * |
| 32 | + * This is a temporary solution |
| 33 | + * |
| 34 | + * TODO: Remove this hardcoded +2 offset when: |
| 35 | + * - Buffer lifecycle management is properly implemented |
| 36 | + * - Proper flow control prevents buffer starvation |
| 37 | + */ |
| 38 | + pool->config.min_buffers = buffer_count + 2; |
| 39 | + pool->config.size = (bit_width / BITS_PER_BYTE) * (sample_rate * frame_interval / 1000000) * |
| 40 | + num_of_channel; |
| 41 | + /* The address needs to be aligned to the size of the DMA transfer */ |
| 42 | + pool->config.align = bit_width >> 3; |
| 43 | + |
| 44 | + /* Allocate just the pool's buffers structure */ |
| 45 | + pool->buffers = k_calloc(pool->config.min_buffers, sizeof(struct mp_buffer)); |
| 46 | + if (pool->buffers == NULL) { |
| 47 | + LOG_ERR("Unable to allocate pool buffer"); |
| 48 | + return false; |
| 49 | + } |
| 50 | + |
| 51 | + /* TODO: Need to allocate in non-cachable memory */ |
| 52 | + zaud_pool->unaligned_buffer = (void *)k_calloc( |
| 53 | + 1, (pool->config.size * pool->config.min_buffers) + (pool->config.align - 1)); |
| 54 | + if (zaud_pool->unaligned_buffer == NULL) { |
| 55 | + LOG_ERR("Unable to allocate mem_slab buffer"); |
| 56 | + return false; |
| 57 | + } |
| 58 | + |
| 59 | + /* Align buffer to required alignment */ |
| 60 | + uintptr_t unaligned_addr = (uintptr_t)zaud_pool->unaligned_buffer; |
| 61 | + uintptr_t aligned_addr = |
| 62 | + (unaligned_addr + pool->config.align - 1) & ~(pool->config.align - 1); |
| 63 | + aligned_buffer = (void *)aligned_addr; |
| 64 | + |
| 65 | + k_mem_slab_init(zaud_pool->mem_slab, aligned_buffer, pool->config.size, |
| 66 | + pool->config.min_buffers); |
| 67 | + |
| 68 | + for (uint8_t i = 0; i < pool->config.min_buffers; i++) { |
| 69 | + /* Wrap mem_slab buffer to generic libMP buffer */ |
| 70 | + pool->buffers[i].pool = pool; |
| 71 | + pool->buffers[i].size = pool->config.size; |
| 72 | + pool->buffers[i].data = &(zaud_pool->mem_slab->buffer[pool->config.size * i]); |
| 73 | + pool->buffers[i].index = i; |
| 74 | + } |
| 75 | + |
| 76 | + return true; |
| 77 | +} |
| 78 | + |
| 79 | +static bool mp_zaud_buffer_pool_stop(struct mp_buffer_pool *pool) |
| 80 | +{ |
| 81 | + struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool); |
| 82 | + |
| 83 | + if (pool->buffers != NULL) { |
| 84 | + k_free(pool->buffers); |
| 85 | + pool->buffers = NULL; |
| 86 | + } |
| 87 | + |
| 88 | + if (zaud_pool->mem_slab->buffer != NULL) { |
| 89 | + k_free(zaud_pool->unaligned_buffer); |
| 90 | + zaud_pool->unaligned_buffer = NULL; |
| 91 | + zaud_pool->mem_slab->buffer = NULL; |
| 92 | + } |
| 93 | + |
| 94 | + zaud_pool->mem_slab = NULL; |
| 95 | + |
| 96 | + return true; |
| 97 | +} |
| 98 | + |
| 99 | +void mp_zaud_buffer_pool_init(struct mp_buffer_pool *pool) |
| 100 | +{ |
| 101 | + struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool); |
| 102 | + |
| 103 | + zaud_pool->zaud_dev = NULL; |
| 104 | + zaud_pool->mem_slab = NULL; |
| 105 | + |
| 106 | + mp_buffer_pool_init(pool); |
| 107 | + |
| 108 | + pool->configure = mp_zaud_buffer_pool_config; |
| 109 | + pool->stop = mp_zaud_buffer_pool_stop; |
| 110 | +} |
0 commit comments