forked from espressif/esp-idf
feat(ppa): add PPA driver support for ESP32P4
Add burst_length option to client Change uint32_t to color_pixel_rgb888_data_t Descriptor always malloc with MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT Add dscr-port mode block size configuration as a separate API in 2D-DMA driver Do writeback only on an extended window, instead of entire picture
This commit is contained in:
@ -10,5 +10,4 @@ endif()
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${public_include}
|
||||
PRIV_REQUIRES esp_mm esp_pm
|
||||
# LDFRAGMENTS "linker.lf"
|
||||
)
|
||||
|
@ -33,9 +33,12 @@ typedef struct ppa_client_t *ppa_client_handle_t;
|
||||
* @brief A collection of configuration items that used for registering a PPA client
|
||||
*/
|
||||
typedef struct {
|
||||
ppa_operation_t oper_type; /*!< The desired PPA operation for the client */
|
||||
uint32_t max_pending_trans_num; /*!< The maximum number of pending transactions for the client.
|
||||
By default, it will be 1, which is sufficient if all transactions are performed with `PPA_TRANS_MODE_BLOCKING` */
|
||||
ppa_operation_t oper_type; /*!< The desired PPA operation for the client */
|
||||
uint32_t max_pending_trans_num; /*!< The maximum number of pending transactions for the client.
|
||||
By default, it will be 1, which is sufficient if all transactions are performed with `PPA_TRANS_MODE_BLOCKING` */
|
||||
ppa_data_burst_length_t data_burst_length; /*!< The desired data burst length for all the transactions of the client.
|
||||
Use a small burst length will decrease PPA performance, but can save burst bandwidth for other peripheral usages.
|
||||
By default, it will be at the maximum burst length, `PPA_DATA_BURST_LENGTH_128` */
|
||||
} ppa_client_config_t;
|
||||
|
||||
/**
|
||||
@ -131,8 +134,8 @@ typedef struct {
|
||||
* @brief A collection of configuration items for an output picture and the target block inside the picture
|
||||
*/
|
||||
typedef struct {
|
||||
void *buffer; /*!< Pointer to the output picture buffer (requires align to the cache line size) */
|
||||
uint32_t buffer_size; /*!< Size of the output picture buffer (requires align to the cache line size) */
|
||||
void *buffer; /*!< Pointer to the output picture buffer (requires alignment: internal memory needs align to L1 cache line size, external memory needs align to L1 and L2 cache line size) */
|
||||
uint32_t buffer_size; /*!< Size of the output picture buffer (requires alignment: internal memory needs align to L1 cache line size, external memory needs align to L1 and L2 cache line size) */
|
||||
uint32_t pic_w; /*!< Output picture width (unit: pixel) */
|
||||
uint32_t pic_h; /*!< Output picture height (unit: pixel) */
|
||||
uint32_t block_offset_x; /*!< Target block offset in x direction in the picture (unit: pixel) */
|
||||
@ -232,13 +235,13 @@ typedef struct {
|
||||
// A pixel, where its background element and foreground element are both out of their color-keying ranges, will follow Alpha Blending
|
||||
bool bg_ck_en; /*!< Whether to enable color keying for background
|
||||
If not enabled, all background pixels are considered as out of the color-keying range */
|
||||
uint32_t bg_ck_rgb_low_thres; /*!< The lower threshold of the color-keying range for the background, in RGB888 format (R[23:16], G[15: 8], B[7:0]) */
|
||||
uint32_t bg_ck_rgb_high_thres; /*!< The higher threshold of the color-keying range for the background, in RGB888 format (R[23:16], G[15: 8], B[7:0]) */
|
||||
color_pixel_rgb888_data_t bg_ck_rgb_low_thres; /*!< The lower threshold of the color-keying range for the background, in RGB888 format */
|
||||
color_pixel_rgb888_data_t bg_ck_rgb_high_thres;/*!< The higher threshold of the color-keying range for the background, in RGB888 format */
|
||||
bool fg_ck_en; /*!< Whether to enable color keying for foreground
|
||||
If not enabled, all foreground pixels are considered as out of the color-keying range */
|
||||
uint32_t fg_ck_rgb_low_thres; /*!< The lower threshold of the color-keying range for the foreground, in RGB888 format (R[23:16], G[15: 8], B[7:0]) */
|
||||
uint32_t fg_ck_rgb_high_thres; /*!< The higher threshold of the color-keying range for the foreground, in RGB888 format (R[23:16], G[15: 8], B[7:0]) */
|
||||
uint32_t ck_rgb_default_val; /*!< The color to overwrite when a pixel, where its background element and foreground element are both within their color-keying ranges, in RGB888 format (R[23:16], G[15: 8], B[7:0]) */
|
||||
color_pixel_rgb888_data_t fg_ck_rgb_low_thres; /*!< The lower threshold of the color-keying range for the foreground, in RGB888 format */
|
||||
color_pixel_rgb888_data_t fg_ck_rgb_high_thres;/*!< The higher threshold of the color-keying range for the foreground, in RGB888 format */
|
||||
color_pixel_rgb888_data_t ck_rgb_default_val; /*!< The color to overwrite when a pixel, where its background element and foreground element are both within their color-keying ranges, in RGB888 format */
|
||||
bool ck_reverse_bg2fg; /*!< If this bit is set, in color-keying, for the pixel, where its background element is in the color range, but its foreground element is not in the color range, it will output the foreground element instead of the background element */
|
||||
|
||||
ppa_trans_mode_t mode; /*!< Determines whether to block inside the operation functions, see `ppa_trans_mode_t` */
|
||||
|
@ -118,7 +118,7 @@ bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_chann
|
||||
dma2d_connect(dma2d_rx_chan, &trig_periph);
|
||||
|
||||
dma2d_transfer_ability_t dma_transfer_ability = {
|
||||
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
|
||||
.data_burst_length = blend_trans_desc->data_burst_length,
|
||||
.desc_burst_en = true,
|
||||
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
|
||||
};
|
||||
@ -155,13 +155,15 @@ bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_chann
|
||||
ppa_ll_blend_set_tx_color_mode(platform->hal.dev, blend_trans_desc->out.blend_cm);
|
||||
|
||||
// Color keying
|
||||
color_pixel_rgb888_data_t rgb888_black = RGB888_BLACK;
|
||||
color_pixel_rgb888_data_t rgb888_white = RGB888_WHITE;
|
||||
ppa_ll_blend_configure_rx_bg_ck_range(platform->hal.dev,
|
||||
blend_trans_desc->bg_ck_en ? blend_trans_desc->bg_ck_rgb_low_thres : 0xFFFFFF,
|
||||
blend_trans_desc->bg_ck_en ? blend_trans_desc->bg_ck_rgb_high_thres : 0);
|
||||
blend_trans_desc->bg_ck_en ? &blend_trans_desc->bg_ck_rgb_low_thres : &rgb888_white,
|
||||
blend_trans_desc->bg_ck_en ? &blend_trans_desc->bg_ck_rgb_high_thres : &rgb888_black);
|
||||
ppa_ll_blend_configure_rx_fg_ck_range(platform->hal.dev,
|
||||
blend_trans_desc->fg_ck_en ? blend_trans_desc->fg_ck_rgb_low_thres : 0xFFFFFF,
|
||||
blend_trans_desc->fg_ck_en ? blend_trans_desc->fg_ck_rgb_high_thres : 0);
|
||||
ppa_ll_blend_set_ck_default_rgb(platform->hal.dev, (blend_trans_desc->bg_ck_en && blend_trans_desc->fg_ck_en) ? blend_trans_desc->ck_rgb_default_val : 0);
|
||||
blend_trans_desc->fg_ck_en ? &blend_trans_desc->fg_ck_rgb_low_thres : &rgb888_white,
|
||||
blend_trans_desc->fg_ck_en ? &blend_trans_desc->fg_ck_rgb_high_thres : &rgb888_black);
|
||||
ppa_ll_blend_set_ck_default_rgb(platform->hal.dev, (blend_trans_desc->bg_ck_en && blend_trans_desc->fg_ck_en) ? &blend_trans_desc->ck_rgb_default_val : &rgb888_black);
|
||||
ppa_ll_blend_enable_ck_fg_bg_reverse(platform->hal.dev, blend_trans_desc->ck_reverse_bg2fg);
|
||||
|
||||
ppa_ll_blend_start(platform->hal.dev, PPA_LL_BLEND_TRANS_MODE_BLEND);
|
||||
@ -178,7 +180,7 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
|
||||
// in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
|
||||
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
|
||||
ESP_RETURN_ON_FALSE((uintptr_t)config->out.buffer % buf_alignment_size == 0 && config->out.buffer_size % buf_alignment_size == 0,
|
||||
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
|
||||
color_space_pixel_format_t out_pixel_format = {
|
||||
.color_type_id = config->out.blend_cm,
|
||||
@ -225,27 +227,28 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
|
||||
}
|
||||
// To reduce complexity, color_mode, alpha_update_mode correctness are checked in their corresponding LL functions
|
||||
|
||||
// Write back and invalidate are performed on the entire picture (the window content is not continuous in the buffer)
|
||||
// Write back in_bg_buffer, in_fg_buffer
|
||||
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
|
||||
// Write back in_bg_buffer, in_fg_buffer extended windows (alignment not necessary on C2M direction)
|
||||
color_space_pixel_format_t in_bg_pixel_format = {
|
||||
.color_type_id = config->in_bg.blend_cm,
|
||||
};
|
||||
uint32_t in_bg_pic_len = config->in_bg.pic_w * config->in_bg.pic_h * color_hal_pixel_format_get_bit_depth(in_bg_pixel_format) / 8;
|
||||
esp_cache_msync((void *)config->in_bg.buffer, in_bg_pic_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
uint32_t in_bg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_bg_pixel_format); // bits
|
||||
uint32_t in_bg_ext_window = (uint32_t)config->in_bg.buffer + config->in_bg.block_offset_y * config->in_bg.pic_w * in_bg_pixel_depth / 8;
|
||||
uint32_t in_bg_ext_window_len = config->in_bg.pic_w * config->in_bg.block_h * in_bg_pixel_depth / 8;
|
||||
esp_cache_msync((void *)in_bg_ext_window, in_bg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
color_space_pixel_format_t in_fg_pixel_format = {
|
||||
.color_type_id = config->in_fg.blend_cm,
|
||||
};
|
||||
uint32_t in_fg_pic_len = config->in_fg.pic_w * config->in_fg.pic_h * color_hal_pixel_format_get_bit_depth(in_fg_pixel_format) / 8;
|
||||
esp_cache_msync((void *)config->in_fg.buffer, in_fg_pic_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
// Invalidate out_buffer
|
||||
uint32_t in_fg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_fg_pixel_format); // bits
|
||||
uint32_t in_fg_ext_window = (uint32_t)config->in_fg.buffer + config->in_fg.block_offset_y * config->in_fg.pic_w * in_fg_pixel_depth / 8;
|
||||
uint32_t in_fg_ext_window_len = config->in_fg.pic_w * config->in_fg.block_h * in_fg_pixel_depth / 8;
|
||||
esp_cache_msync((void *)in_fg_ext_window, in_fg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
// Invalidate out_buffer entire picture (alignment strict on M2C direction)
|
||||
esp_cache_msync((void *)config->out.buffer, config->out.buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ppa_trans_t *trans_elm = NULL;
|
||||
portENTER_CRITICAL(&ppa_client->spinlock);
|
||||
bool trans_elm_acquired = xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0);
|
||||
portEXIT_CRITICAL(&ppa_client->spinlock);
|
||||
if (trans_elm_acquired) {
|
||||
if (xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0)) {
|
||||
dma2d_trans_config_t *dma_trans_desc = trans_elm->trans_desc;
|
||||
|
||||
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = dma_trans_desc->user_config;
|
||||
@ -254,6 +257,7 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
|
||||
memcpy(blend_trans_desc, config, sizeof(ppa_blend_oper_config_t));
|
||||
blend_trans_desc->bg_alpha_value = new_bg_alpha_value;
|
||||
blend_trans_desc->fg_alpha_value = new_fg_alpha_value;
|
||||
blend_trans_desc->data_burst_length = ppa_client->data_burst_length;
|
||||
|
||||
trans_on_picked_desc->ppa_engine = ppa_client->engine;
|
||||
trans_on_picked_desc->trigger_periph = DMA2D_TRIG_PERIPH_PPA_BLEND;
|
||||
|
@ -75,8 +75,8 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
|
||||
if (!s_platform.srm) {
|
||||
ppa_srm_engine_t *srm_engine = heap_caps_calloc(1, sizeof(ppa_srm_engine_t), PPA_MEM_ALLOC_CAPS);
|
||||
SemaphoreHandle_t srm_sem = xSemaphoreCreateBinaryWithCaps(PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *srm_tx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *srm_rx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *srm_tx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
dma2d_descriptor_t *srm_rx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (srm_engine && srm_sem && srm_tx_dma_desc && srm_rx_dma_desc) {
|
||||
srm_engine->dma_tx_desc = srm_tx_dma_desc;
|
||||
srm_engine->dma_rx_desc = srm_rx_dma_desc;
|
||||
@ -120,9 +120,9 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
|
||||
if (!s_platform.blending) {
|
||||
ppa_blend_engine_t *blending_engine = heap_caps_calloc(1, sizeof(ppa_blend_engine_t), PPA_MEM_ALLOC_CAPS);
|
||||
SemaphoreHandle_t blending_sem = xSemaphoreCreateBinaryWithCaps(PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *blending_tx_bg_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *blending_tx_fg_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *blending_rx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | PPA_MEM_ALLOC_CAPS);
|
||||
dma2d_descriptor_t *blending_tx_bg_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
dma2d_descriptor_t *blending_tx_fg_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
dma2d_descriptor_t *blending_rx_dma_desc = (dma2d_descriptor_t *)heap_caps_aligned_calloc(alignment, 1, s_platform.dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (blending_engine && blending_sem && blending_tx_bg_dma_desc && blending_tx_fg_dma_desc && blending_rx_dma_desc) {
|
||||
blending_engine->dma_tx_bg_desc = blending_tx_bg_dma_desc;
|
||||
blending_engine->dma_tx_fg_desc = blending_tx_fg_dma_desc;
|
||||
@ -277,6 +277,7 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand
|
||||
|
||||
client->oper_type = config->oper_type;
|
||||
client->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
client->data_burst_length = config->data_burst_length ? config->data_burst_length : PPA_DATA_BURST_LENGTH_128;
|
||||
if (config->oper_type == PPA_OPERATION_SRM) {
|
||||
ppa_engine_config_t engine_config = {
|
||||
.engine = PPA_ENGINE_TYPE_SRM,
|
||||
@ -397,7 +398,7 @@ static void ppa_free_transaction(ppa_trans_t *trans_elm)
|
||||
bool ppa_recycle_transaction(ppa_client_handle_t ppa_client, ppa_trans_t *trans_elm)
|
||||
{
|
||||
// Reset transaction and send back to client's trans_elm_ptr_queue
|
||||
// TODO: To be very safe, we shall memset all to 0, and reconnect necessary pointers?
|
||||
// TODO: To be very safe, we shall memset all to 0, and reconnect necessary pointers?
|
||||
BaseType_t HPTaskAwoken;
|
||||
BaseType_t sent = xQueueSendFromISR(ppa_client->trans_elm_ptr_queue, &trans_elm, &HPTaskAwoken);
|
||||
assert(sent);
|
||||
|
@ -62,7 +62,7 @@ bool ppa_fill_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channe
|
||||
dma2d_connect(dma2d_rx_chan, &trig_periph);
|
||||
|
||||
dma2d_transfer_ability_t dma_transfer_ability = {
|
||||
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
|
||||
.data_burst_length = fill_trans_desc->data_burst_length,
|
||||
.desc_burst_en = true,
|
||||
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
|
||||
};
|
||||
@ -94,30 +94,34 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config
|
||||
// out_buffer ptr cannot in flash region
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
|
||||
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
|
||||
ESP_RETURN_ON_FALSE((uintptr_t)config->out.buffer % buf_alignment_size == 0 && config->out.buffer_size % buf_alignment_size == 0,
|
||||
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
|
||||
color_space_pixel_format_t out_pixel_format = {
|
||||
.color_type_id = config->out.fill_cm,
|
||||
};
|
||||
uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * color_hal_pixel_format_get_bit_depth(out_pixel_format) / 8;
|
||||
uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format);
|
||||
uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8;
|
||||
ESP_RETURN_ON_FALSE(out_pic_len <= config->out.buffer_size, ESP_ERR_INVALID_ARG, TAG, "out.pic_w/h mismatch with out.buffer_size");
|
||||
// To reduce complexity, color_mode, fill_block_w/h correctness are checked in their corresponding LL functions
|
||||
|
||||
// Write back and invalidate are performed on the entire picture (the window content is not continuous in the buffer)
|
||||
esp_cache_msync((void *)config->out.buffer, config->out.buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
|
||||
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
|
||||
// Write back buffer extended window (alignment not necessary on C2M direction)
|
||||
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
|
||||
uint32_t out_ext_window_len = config->out.pic_w * config->fill_block_h * out_pixel_depth / 8;
|
||||
esp_cache_msync((void *)out_ext_window, out_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
// Invalidate out_buffer entire picture (alignment strict on M2C direction)
|
||||
esp_cache_msync((void *)config->out.buffer, config->out.buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ppa_trans_t *trans_elm = NULL;
|
||||
portENTER_CRITICAL(&ppa_client->spinlock);
|
||||
bool trans_elm_acquired = xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0);
|
||||
portEXIT_CRITICAL(&ppa_client->spinlock);
|
||||
if (trans_elm_acquired) {
|
||||
if (xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0)) {
|
||||
dma2d_trans_config_t *dma_trans_desc = trans_elm->trans_desc;
|
||||
|
||||
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = dma_trans_desc->user_config;
|
||||
|
||||
ppa_fill_oper_t *fill_trans_desc = (ppa_fill_oper_t *)trans_on_picked_desc->fill_desc;
|
||||
memcpy(fill_trans_desc, config, sizeof(ppa_fill_oper_config_t));
|
||||
fill_trans_desc->data_burst_length = ppa_client->data_burst_length;
|
||||
|
||||
trans_on_picked_desc->ppa_engine = ppa_client->engine;
|
||||
trans_on_picked_desc->trigger_periph = DMA2D_TRIG_PERIPH_PPA_BLEND;
|
||||
|
@ -22,7 +22,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PPA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) // TODO...
|
||||
#define PPA_MEM_ALLOC_CAPS (MALLOC_CAP_DEFAULT)
|
||||
|
||||
#define PPA_PM_LOCK_NAME_LEN_MAX 16
|
||||
|
||||
@ -80,6 +80,7 @@ struct ppa_client_t {
|
||||
portMUX_TYPE spinlock; // Client level spinlock
|
||||
ppa_event_callback_t done_cb; // Transaction done callback
|
||||
QueueHandle_t trans_elm_ptr_queue; // Queue that contains the pointers to the allocated memory to save the transaction contexts
|
||||
ppa_data_burst_length_t data_burst_length; // The desired data burst length for all the transactions of the client
|
||||
};
|
||||
|
||||
/****************************** OPERATION ************************************/
|
||||
@ -115,6 +116,7 @@ typedef struct {
|
||||
uint32_t scale_y_int; // Calculation result for the integral part of the scale_y to be directly written to register
|
||||
uint32_t scale_y_frag; // Calculation result for the fractional part of the scale_y to be directly written to register
|
||||
uint32_t alpha_value; // Calculation result for the fix alpha value to be directly written to register
|
||||
ppa_data_burst_length_t data_burst_length; // Data burst length for the transaction, information passed from the client
|
||||
} ppa_srm_oper_t;
|
||||
|
||||
// The elements in this structure listed first are identical to the elements in structure `ppa_blend_oper_config_t`
|
||||
@ -144,12 +146,12 @@ typedef struct {
|
||||
|
||||
// color-keying
|
||||
bool bg_ck_en;
|
||||
uint32_t bg_ck_rgb_low_thres;
|
||||
uint32_t bg_ck_rgb_high_thres;
|
||||
color_pixel_rgb888_data_t bg_ck_rgb_low_thres;
|
||||
color_pixel_rgb888_data_t bg_ck_rgb_high_thres;
|
||||
bool fg_ck_en;
|
||||
uint32_t fg_ck_rgb_low_thres;
|
||||
uint32_t fg_ck_rgb_high_thres;
|
||||
uint32_t ck_rgb_default_val;
|
||||
color_pixel_rgb888_data_t fg_ck_rgb_low_thres;
|
||||
color_pixel_rgb888_data_t fg_ck_rgb_high_thres;
|
||||
color_pixel_rgb888_data_t ck_rgb_default_val;
|
||||
bool ck_reverse_bg2fg;
|
||||
|
||||
ppa_trans_mode_t mode;
|
||||
@ -157,9 +159,24 @@ typedef struct {
|
||||
|
||||
uint32_t bg_alpha_value; // Calculation result for the fix alpha value for BG to be directly written to register
|
||||
uint32_t fg_alpha_value; // Calculation result for the fix alpha value for FG to be directly written to register
|
||||
ppa_data_burst_length_t data_burst_length; // Data burst length for the transaction, information passed from the client
|
||||
} ppa_blend_oper_t;
|
||||
|
||||
typedef ppa_fill_oper_config_t ppa_fill_oper_t;
|
||||
// The elements in this structure listed first are identical to the elements in structure `ppa_fill_oper_config_t`
|
||||
// With adding a few extra elements at the end
|
||||
// This allows memcpy
|
||||
typedef struct {
|
||||
ppa_out_pic_blk_config_t out;
|
||||
|
||||
uint32_t fill_block_w;
|
||||
uint32_t fill_block_h;
|
||||
color_pixel_argb8888_data_t fill_argb_color;
|
||||
|
||||
ppa_trans_mode_t mode;
|
||||
void *user_data;
|
||||
|
||||
ppa_data_burst_length_t data_burst_length; // Data burst length for the transaction, information passed from the client
|
||||
} ppa_fill_oper_t;
|
||||
|
||||
/***************************** TRANSACTION ***********************************/
|
||||
|
||||
|
@ -93,16 +93,20 @@ bool ppa_srm_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel
|
||||
dma2d_connect(dma2d_rx_chan, &trig_periph);
|
||||
|
||||
dma2d_transfer_ability_t dma_transfer_ability = {
|
||||
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
|
||||
.data_burst_length = srm_trans_desc->data_burst_length,
|
||||
.desc_burst_en = true,
|
||||
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
|
||||
// Configure the block size to be received by the SRM engine, which is passed from the 2D-DMA TX channel (i.e. 2D-DMA dscr-port mode)
|
||||
.dscr_port_block_h = (srm_trans_desc->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) ? PPA_LL_SRM_YUV420_BLOCK_SIZE : PPA_LL_SRM_DEFAULT_BLOCK_SIZE,
|
||||
.dscr_port_block_v = (srm_trans_desc->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) ? PPA_LL_SRM_YUV420_BLOCK_SIZE : PPA_LL_SRM_DEFAULT_BLOCK_SIZE,
|
||||
};
|
||||
dma2d_set_transfer_ability(dma2d_tx_chan, &dma_transfer_ability);
|
||||
dma2d_set_transfer_ability(dma2d_rx_chan, &dma_transfer_ability);
|
||||
|
||||
// Configure the block size to be received by the SRM engine, which is passed from the 2D-DMA TX channel (i.e. 2D-DMA dscr-port mode)
|
||||
dma2d_dscr_port_mode_config_t dma_dscr_port_mode_config = {
|
||||
.block_h = (srm_trans_desc->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) ? PPA_LL_SRM_YUV420_BLOCK_SIZE : PPA_LL_SRM_DEFAULT_BLOCK_SIZE,
|
||||
.block_v = (srm_trans_desc->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) ? PPA_LL_SRM_YUV420_BLOCK_SIZE : PPA_LL_SRM_DEFAULT_BLOCK_SIZE,
|
||||
};
|
||||
dma2d_configure_dscr_port_mode(dma2d_tx_chan, &dma_dscr_port_mode_config);
|
||||
|
||||
// YUV444 and YUV422 are not supported by PPA module, need to utilize 2D-DMA color space conversion feature to do a conversion
|
||||
ppa_srm_color_mode_t ppa_in_color_mode = srm_trans_desc->in.srm_cm;
|
||||
if (ppa_in_color_mode == PPA_SRM_COLOR_MODE_YUV444) {
|
||||
@ -180,8 +184,25 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
|
||||
// in_buffer could be anywhere (ram, flash, psram), out_buffer ptr cannot in flash region
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_internal(config->out.buffer) || esp_ptr_external_ram(config->out.buffer), ESP_ERR_INVALID_ARG, TAG, "invalid out.buffer addr");
|
||||
uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size;
|
||||
ESP_RETURN_ON_FALSE((uintptr_t)config->out.buffer % buf_alignment_size == 0 && config->out.buffer_size % buf_alignment_size == 0,
|
||||
ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size");
|
||||
// For YUV420 input/output: in desc, ha/hb/va/vb/x/y must be even number
|
||||
if (config->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) {
|
||||
ESP_RETURN_ON_FALSE(config->in.pic_h % 2 == 0 && config->in.pic_w % 2 == 0 &&
|
||||
config->in.block_h % 2 == 0 && config->in.block_w % 2 == 0 &&
|
||||
config->in.block_offset_x % 2 == 0 && config->in.block_offset_y % 2 == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "YUV420 input does not support odd h/w/offset_x/offset_y");
|
||||
}
|
||||
// TODO: ECO2 support YUV422
|
||||
// else if (config->in.srm_cm == PPA_SRM_COLOR_MODE_YUV422) {
|
||||
// ESP_RETURN_ON_FALSE(config->in.pic_w % 2 == 0 && config->in.block_w % 2 == 0 && config->in.block_offset_x % 2 == 0,
|
||||
// ESP_ERR_INVALID_ARG, TAG, "YUV422 input does not support odd w/offset_x");
|
||||
// }
|
||||
if (config->out.srm_cm == PPA_SRM_COLOR_MODE_YUV420) {
|
||||
ESP_RETURN_ON_FALSE(config->out.pic_h % 2 == 0 && config->out.pic_w % 2 == 0 &&
|
||||
config->out.block_offset_x % 2 == 0 && config->out.block_offset_y % 2 == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "YUV420 output does not support odd h/w/offset_x/offset_y");
|
||||
}
|
||||
color_space_pixel_format_t out_pixel_format = {
|
||||
.color_type_id = config->out.srm_cm,
|
||||
};
|
||||
@ -217,26 +238,22 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
|
||||
new_alpha_value = (uint32_t)(config->alpha_scale_ratio * 256);
|
||||
}
|
||||
// To reduce complexity, rotation_angle, color_mode, alpha_update_mode correctness are checked in their corresponding LL functions
|
||||
// TODO:
|
||||
// YUV420: in desc, ha/hb/va/vb/x/y must be even number
|
||||
// What for YUV444/YUV422
|
||||
|
||||
// Write back and invalidate are performed on the entire picture (the window content is not continuous in the buffer)
|
||||
// Write back in_buffer
|
||||
// Write back and invalidate necessary data (note that the window content is not continuous in the buffer)
|
||||
// Write back in_buffer extended window (alignment not necessary on C2M direction)
|
||||
color_space_pixel_format_t in_pixel_format = {
|
||||
.color_type_id = config->in.srm_cm,
|
||||
};
|
||||
uint32_t in_pic_len = config->in.pic_w * config->in.pic_h * color_hal_pixel_format_get_bit_depth(in_pixel_format) / 8;
|
||||
esp_cache_msync((void *)config->in.buffer, in_pic_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
// Invalidate out_buffer
|
||||
uint32_t in_pixel_depth = color_hal_pixel_format_get_bit_depth(in_pixel_format); // bits
|
||||
uint32_t in_ext_window = (uint32_t)config->in.buffer + config->in.block_offset_y * config->in.pic_w * in_pixel_depth / 8;
|
||||
uint32_t in_ext_window_len = config->in.pic_w * config->in.block_h * in_pixel_depth / 8;
|
||||
esp_cache_msync((void *)in_ext_window, in_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||
// Invalidate out_buffer entire picture (alignment strict on M2C direction)
|
||||
esp_cache_msync((void *)config->out.buffer, config->out.buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ppa_trans_t *trans_elm = NULL;
|
||||
portENTER_CRITICAL(&ppa_client->spinlock);
|
||||
bool trans_elm_acquired = xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0);
|
||||
portEXIT_CRITICAL(&ppa_client->spinlock);
|
||||
if (trans_elm_acquired) {
|
||||
if (xQueueReceive(ppa_client->trans_elm_ptr_queue, (void *)&trans_elm, 0)) {
|
||||
dma2d_trans_config_t *dma_trans_desc = trans_elm->trans_desc;
|
||||
|
||||
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = dma_trans_desc->user_config;
|
||||
@ -248,6 +265,7 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
|
||||
srm_trans_desc->scale_y_int = (uint32_t)srm_trans_desc->scale_y;
|
||||
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * (PPA_LL_SRM_SCALING_FRAG_MAX + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX;
|
||||
srm_trans_desc->alpha_value = new_alpha_value;
|
||||
srm_trans_desc->data_burst_length = ppa_client->data_burst_length;
|
||||
|
||||
trans_on_picked_desc->ppa_engine = ppa_client->engine;
|
||||
trans_on_picked_desc->trigger_periph = DMA2D_TRIG_PERIPH_PPA_SRM;
|
||||
|
@ -41,19 +41,19 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]")
|
||||
TEST_ASSERT_NOT_NULL(buf_2);
|
||||
|
||||
// Register different types of PPA clients
|
||||
ppa_client_handle_t ppa_client_a_handle;
|
||||
ppa_client_handle_t ppa_client_b_handle;
|
||||
ppa_client_handle_t ppa_client_c_handle;
|
||||
ppa_client_handle_t ppa_client_d_handle;
|
||||
ppa_client_handle_t ppa_client_srm_handle;
|
||||
ppa_client_handle_t ppa_client_blend_handle;
|
||||
ppa_client_handle_t ppa_client_fill_handle_a;
|
||||
ppa_client_handle_t ppa_client_fill_handle_b;
|
||||
ppa_client_config_t ppa_client_config = {
|
||||
.oper_type = PPA_OPERATION_SRM,
|
||||
};
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_a_handle));
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_srm_handle));
|
||||
ppa_client_config.oper_type = PPA_OPERATION_BLEND;
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_b_handle));
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_blend_handle));
|
||||
ppa_client_config.oper_type = PPA_OPERATION_FILL;
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_c_handle));
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_d_handle));
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_fill_handle_a));
|
||||
TEST_ESP_OK(ppa_register_client(&ppa_client_config, &ppa_client_fill_handle_b));
|
||||
|
||||
ppa_srm_oper_config_t srm_oper_config = {
|
||||
.in.buffer = buf_1,
|
||||
@ -80,9 +80,9 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]")
|
||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||
};
|
||||
// A SRM client can request to do a SRM operation
|
||||
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_a_handle, &srm_oper_config));
|
||||
TEST_ESP_OK(ppa_do_scale_rotate_mirror(ppa_client_srm_handle, &srm_oper_config));
|
||||
// A non-SRM client can not request to do a SRM operation
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_scale_rotate_mirror(ppa_client_b_handle, &srm_oper_config));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_scale_rotate_mirror(ppa_client_blend_handle, &srm_oper_config));
|
||||
|
||||
ppa_blend_oper_config_t blend_oper_config = {
|
||||
.in_bg.buffer = buf_1,
|
||||
@ -114,9 +114,9 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]")
|
||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||
};
|
||||
// A blend client can request to do a blend operation
|
||||
TEST_ESP_OK(ppa_do_blend(ppa_client_b_handle, &blend_oper_config));
|
||||
TEST_ESP_OK(ppa_do_blend(ppa_client_blend_handle, &blend_oper_config));
|
||||
// A non-blend client can not request to do a blend operation
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_blend(ppa_client_d_handle, &blend_oper_config));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, ppa_do_blend(ppa_client_fill_handle_b, &blend_oper_config));
|
||||
|
||||
ppa_fill_oper_config_t fill_oper_config = {
|
||||
.out.buffer = buf_1,
|
||||
@ -136,17 +136,17 @@ TEST_CASE("ppa_client_do_ppa_operation", "[PPA]")
|
||||
.mode = PPA_TRANS_MODE_NON_BLOCKING,
|
||||
};
|
||||
// A fill client can request to do a fill operation
|
||||
TEST_ESP_OK(ppa_do_fill(ppa_client_c_handle, &fill_oper_config));
|
||||
TEST_ESP_OK(ppa_do_fill(ppa_client_fill_handle_a, &fill_oper_config));
|
||||
// Another fill client can also request another fill operation at the same time
|
||||
TEST_ESP_OK(ppa_do_fill(ppa_client_d_handle, &fill_oper_config));
|
||||
TEST_ESP_OK(ppa_do_fill(ppa_client_fill_handle_b, &fill_oper_config));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// Unregister all PPA clients
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_a_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_b_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_c_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_d_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_srm_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_blend_handle));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_fill_handle_a));
|
||||
TEST_ESP_OK(ppa_unregister_client(ppa_client_fill_handle_b));
|
||||
|
||||
free(buf_1);
|
||||
free(buf_2);
|
||||
|
@ -828,9 +828,6 @@ esp_err_t dma2d_set_transfer_ability(dma2d_channel_handle_t dma2d_chan, const dm
|
||||
dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en);
|
||||
dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length);
|
||||
dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size);
|
||||
if (ability->dscr_port_block_h && ability->dscr_port_block_v) {
|
||||
dma2d_ll_tx_set_dscr_port_block_size(group->hal.dev, channel_id, ability->dscr_port_block_h, ability->dscr_port_block_v);
|
||||
}
|
||||
} else {
|
||||
dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en);
|
||||
dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length);
|
||||
@ -874,6 +871,24 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t dma2d_configure_dscr_port_mode(dma2d_channel_handle_t dma2d_chan, const dma2d_dscr_port_mode_config_t *config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_FALSE_ISR(dma2d_chan && config, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
|
||||
dma2d_group_t *group = dma2d_chan->group;
|
||||
int channel_id = dma2d_chan->channel_id;
|
||||
|
||||
if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) {
|
||||
ESP_GOTO_ON_FALSE_ISR(config->block_h > 0 && config->block_v > 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
|
||||
dma2d_ll_tx_set_dscr_port_block_size(group->hal.dev, channel_id, config->block_h, config->block_v);
|
||||
}
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t dma2d_enqueue(dma2d_pool_handle_t dma2d_pool, const dma2d_trans_config_t *trans_desc, dma2d_trans_t *trans_placeholder)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
@ -220,7 +220,7 @@ typedef struct {
|
||||
esp_err_t dma2d_apply_strategy(dma2d_channel_handle_t dma2d_chan, const dma2d_strategy_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief A collection of transfer ability items that each 2D-DMA channel could apply to improve transfer efficiency or to ensure desired transfer block size
|
||||
* @brief A collection of transfer ability items that each 2D-DMA channel could apply to improve transfer efficiency
|
||||
*
|
||||
* @note The 2D-DMA driver has no knowledge about the DMA buffer (address and size) used by upper layer.
|
||||
* So it's the responsibility of the **upper layer** to take care of the buffer address and size.
|
||||
@ -231,8 +231,6 @@ typedef struct {
|
||||
bool desc_burst_en; /*!< If set / clear, DMA channel enables / disables burst reading descriptor link */
|
||||
dma2d_data_burst_length_t data_burst_length; /*!< Configure the DMA channel burst reading data length */
|
||||
dma2d_macro_block_size_t mb_size; /*!< Configure the DMA channel macro block size (only useful in DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE mode) */
|
||||
uint32_t dscr_port_block_h; /*!< Configure the DMA TX channel horizontal width of the block in dscr-port mode (unit: pixel) */
|
||||
uint32_t dscr_port_block_v; /*!< Configure the DMA TX channel vertical height of the block in dscr-port mode (unit: pixel) */
|
||||
} dma2d_transfer_ability_t;
|
||||
|
||||
/**
|
||||
@ -273,6 +271,26 @@ typedef struct {
|
||||
*/
|
||||
esp_err_t dma2d_configure_color_space_conversion(dma2d_channel_handle_t dma2d_chan, const dma2d_csc_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief A collection of configurations apply to 2D-DMA channel DSCR-PORT mode
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t block_h; /*!< Horizontal width of the block in dscr-port mode (unit: pixel) */
|
||||
uint32_t block_v; /*!< Vertical height of the block in dscr-port mode (unit: pixel) */
|
||||
} dma2d_dscr_port_mode_config_t;
|
||||
|
||||
/**
|
||||
* @brief Configure 2D-DMA channel DSCR-PORT mode
|
||||
*
|
||||
* @note This API only targets PPA SRM, which uses 2D-DMA DSCR-PORT mode.
|
||||
*
|
||||
* @param[in] dma2d_chan 2D-DMA channel handle, get from the `on_job_picked` callback input argument `dma2d_chans`
|
||||
* @param[in] config Configuration of 2D-DMA channel DSCR-PORT mode
|
||||
* @return
|
||||
* - ESP_OK: Configure 2D-DMA dscr-port mode successfully
|
||||
*/
|
||||
esp_err_t dma2d_configure_dscr_port_mode(dma2d_channel_handle_t dma2d_chan, const dma2d_dscr_port_mode_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Type of 2D-DMA event data
|
||||
*/
|
||||
|
@ -113,6 +113,7 @@ entries:
|
||||
dma2d: dma2d_apply_strategy (noflash)
|
||||
dma2d: dma2d_set_transfer_ability (noflash)
|
||||
dma2d: dma2d_configure_color_space_conversion (noflash)
|
||||
dma2d: dma2d_configure_dscr_port_mode (noflash)
|
||||
dma2d: dma2d_enqueue (noflash)
|
||||
|
||||
[mapping:dma2d_hal]
|
||||
|
@ -679,10 +679,15 @@ static inline void ppa_ll_blend_set_rx_fg_fix_rgb(ppa_dev_t *dev, color_pixel_rg
|
||||
* @param rgb_thres_low Color-key lower threshold of background in RGB888 format
|
||||
* @param rgb_thres_high Color-key higher threshold of background in RGB888 format
|
||||
*/
|
||||
static inline void ppa_ll_blend_configure_rx_bg_ck_range(ppa_dev_t *dev, uint32_t rgb_thres_low, uint32_t rgb_thres_high)
|
||||
static inline void ppa_ll_blend_configure_rx_bg_ck_range(ppa_dev_t *dev, color_pixel_rgb888_data_t *rgb_thres_low, color_pixel_rgb888_data_t *rgb_thres_high)
|
||||
{
|
||||
dev->ck_bg_low.val = rgb_thres_low;
|
||||
dev->ck_bg_high.val = rgb_thres_high;
|
||||
dev->ck_bg_low.colorkey_bg_b_low = rgb_thres_low->b;
|
||||
dev->ck_bg_low.colorkey_bg_g_low = rgb_thres_low->g;
|
||||
dev->ck_bg_low.colorkey_bg_r_low = rgb_thres_low->r;
|
||||
|
||||
dev->ck_bg_high.colorkey_bg_b_high = rgb_thres_high->b;
|
||||
dev->ck_bg_high.colorkey_bg_g_high = rgb_thres_high->g;
|
||||
dev->ck_bg_high.colorkey_bg_r_high = rgb_thres_high->r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,10 +697,15 @@ static inline void ppa_ll_blend_configure_rx_bg_ck_range(ppa_dev_t *dev, uint32_
|
||||
* @param rgb_thres_low Color-key lower threshold of foreground in RGB888 format
|
||||
* @param rgb_thres_high Color-key higher threshold of foreground in RGB888 format
|
||||
*/
|
||||
static inline void ppa_ll_blend_configure_rx_fg_ck_range(ppa_dev_t *dev, uint32_t rgb_thres_low, uint32_t rgb_thres_high)
|
||||
static inline void ppa_ll_blend_configure_rx_fg_ck_range(ppa_dev_t *dev, color_pixel_rgb888_data_t *rgb_thres_low, color_pixel_rgb888_data_t *rgb_thres_high)
|
||||
{
|
||||
dev->ck_fg_low.val = rgb_thres_low;
|
||||
dev->ck_fg_high.val = rgb_thres_high;
|
||||
dev->ck_fg_low.colorkey_fg_b_low = rgb_thres_low->b;
|
||||
dev->ck_fg_low.colorkey_fg_g_low = rgb_thres_low->g;
|
||||
dev->ck_fg_low.colorkey_fg_r_low = rgb_thres_low->r;
|
||||
|
||||
dev->ck_fg_high.colorkey_fg_b_high = rgb_thres_high->b;
|
||||
dev->ck_fg_high.colorkey_fg_g_high = rgb_thres_high->g;
|
||||
dev->ck_fg_high.colorkey_fg_r_high = rgb_thres_high->r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -704,9 +714,11 @@ static inline void ppa_ll_blend_configure_rx_fg_ck_range(ppa_dev_t *dev, uint32_
|
||||
* @param dev Peripheral instance address
|
||||
* @param rgb Default RGB value in RGB888 format
|
||||
*/
|
||||
static inline void ppa_ll_blend_set_ck_default_rgb(ppa_dev_t *dev, uint32_t rgb)
|
||||
static inline void ppa_ll_blend_set_ck_default_rgb(ppa_dev_t *dev, color_pixel_rgb888_data_t *rgb)
|
||||
{
|
||||
dev->ck_default.val = (dev->ck_default.colorkey_fg_bg_reverse << PPA_COLORKEY_FG_BG_REVERSE_S) | rgb;
|
||||
dev->ck_default.colorkey_default_b = rgb->b;
|
||||
dev->ck_default.colorkey_default_g = rgb->g;
|
||||
dev->ck_default.colorkey_default_r = rgb->r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,6 +176,12 @@ typedef struct {
|
||||
uint8_t r; /*!< R component [0, 255] */
|
||||
} color_pixel_rgb888_data_t;
|
||||
|
||||
///< Color BLACK in color_pixel_rgb888_data_t
|
||||
#define RGB888_BLACK {.b = 0x00, .g = 0x00, .r = 0x00}
|
||||
|
||||
///< Color WHITE in color_pixel_rgb888_data_t
|
||||
#define RGB888_WHITE {.b = 0xFF, .g = 0xFF, .r = 0xFF}
|
||||
|
||||
/**
|
||||
* @brief Data structure for RGB565 pixel unit
|
||||
*/
|
||||
|
@ -118,9 +118,11 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* @brief Enumeration of 2D-DMA data burst length options
|
||||
*
|
||||
* Starting from 1, saving 0 for special purpose (upper layer could use 0 to be a default burst length)
|
||||
*/
|
||||
typedef enum {
|
||||
DMA2D_DATA_BURST_LENGTH_8, /*!< 2D-DMA block size: 8 bytes */
|
||||
DMA2D_DATA_BURST_LENGTH_8 = 1, /*!< 2D-DMA block size: 8 bytes */
|
||||
DMA2D_DATA_BURST_LENGTH_16, /*!< 2D-DMA block size: 16 bytes */
|
||||
DMA2D_DATA_BURST_LENGTH_32, /*!< 2D-DMA block size: 32 bytes */
|
||||
DMA2D_DATA_BURST_LENGTH_64, /*!< 2D-DMA block size: 64 bytes */
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hal/color_types.h"
|
||||
#include "hal/dma2d_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -53,10 +54,11 @@ typedef enum {
|
||||
PPA_BLEND_COLOR_MODE_ARGB8888 = COLOR_TYPE_ID(COLOR_SPACE_ARGB, COLOR_PIXEL_ARGB8888), /*!< PPA blend color mode: ARGB8888 */
|
||||
PPA_BLEND_COLOR_MODE_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), /*!< PPA blend color mode: RGB888 */
|
||||
PPA_BLEND_COLOR_MODE_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), /*!< PPA blend color mode: RGB565 */
|
||||
PPA_BLEND_COLOR_MODE_L8 = COLOR_TYPE_ID(COLOR_SPACE_CLUT, COLOR_PIXEL_L8), /*!< PPA blend color mode: L8, only available on blend inputs */
|
||||
PPA_BLEND_COLOR_MODE_L4 = COLOR_TYPE_ID(COLOR_SPACE_CLUT, COLOR_PIXEL_L4), /*!< PPA blend color mode: L4, only available on blend inputs */
|
||||
PPA_BLEND_COLOR_MODE_A8 = COLOR_TYPE_ID(COLOR_SPACE_ALPHA, COLOR_PIXEL_A8), /*!< PPA blend color mode: A8, only available on blend foreground input */
|
||||
PPA_BLEND_COLOR_MODE_A4 = COLOR_TYPE_ID(COLOR_SPACE_ALPHA, COLOR_PIXEL_A4), /*!< PPA blend color mode: A4, only available on blend foreground input */
|
||||
// TODO: Support CLUT to support L4/L8 color mode
|
||||
PPA_BLEND_COLOR_MODE_L8 = COLOR_TYPE_ID(COLOR_SPACE_CLUT, COLOR_PIXEL_L8), /*!< PPA blend color mode: L8, only available on blend inputs */
|
||||
PPA_BLEND_COLOR_MODE_L4 = COLOR_TYPE_ID(COLOR_SPACE_CLUT, COLOR_PIXEL_L4), /*!< PPA blend color mode: L4, only available on blend inputs */
|
||||
} ppa_blend_color_mode_t;
|
||||
|
||||
/**
|
||||
@ -97,6 +99,17 @@ typedef enum {
|
||||
PPA_COLOR_RANGE_FULL = COLOR_RANGE_FULL, /*!< Full color range, 0 is the darkest black and 255 is the brightest white */
|
||||
} ppa_color_range_t;
|
||||
|
||||
/**
|
||||
* @brief Enumeration of PPA supported data burst length
|
||||
*/
|
||||
typedef enum {
|
||||
PPA_DATA_BURST_LENGTH_8 = DMA2D_DATA_BURST_LENGTH_8, /*!< Data burst length: 8 bytes */
|
||||
PPA_DATA_BURST_LENGTH_16 = DMA2D_DATA_BURST_LENGTH_16, /*!< Data burst length: 16 bytes */
|
||||
PPA_DATA_BURST_LENGTH_32 = DMA2D_DATA_BURST_LENGTH_32, /*!< Data burst length: 32 bytes */
|
||||
PPA_DATA_BURST_LENGTH_64 = DMA2D_DATA_BURST_LENGTH_64, /*!< Data burst length: 64 bytes */
|
||||
PPA_DATA_BURST_LENGTH_128 = DMA2D_DATA_BURST_LENGTH_128, /*!< Data burst length: 128 bytes */
|
||||
} ppa_data_burst_length_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user