mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-10 06:31:24 +00:00
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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user