feat(ppa): add PPA driver support for ESP32P4

Add fill operation
Split ppa_do_operation, pre-process some trans config
This commit is contained in:
Song Ruo Jing
2024-03-01 21:52:56 +08:00
parent fd19979d88
commit 776c3ef392
3 changed files with 243 additions and 86 deletions

View File

@@ -32,8 +32,6 @@ typedef struct ppa_invoker_t *ppa_invoker_handle_t;
* @brief A collection of configuration items that used for registering a PPA invoker
*/
typedef struct {
// ppa_engine_handle_t sr_engine;
// ppa_engine_handle_t blend_engine;
uint32_t engine_flag; /*!< Bitwise OR of `PPA_ENGINE_FLAG_*` flags indicating the required engines for the invoker */
// done_cb
// user_data
@@ -69,49 +67,51 @@ typedef enum {
PPA_TRANS_MODE_NON_BLOCKING, /*!< `ppa_do_xxx` function will return immediately after the PPA operation is pushed to the internal queue */
} ppa_trans_mode_t;
#define PPA_SR_TRANS_CONFIG struct { \
void *in_buffer; /*!< TODO: could be a buffer list, link descriptors together, process a batch
uint32_t batch_num; However, is it necessary? psram can not store too many pictures */ \
uint32_t in_pic_w; \
uint32_t in_pic_h; \
uint32_t in_block_w; \
uint32_t in_block_h; \
uint32_t in_block_offset_x; \
uint32_t in_block_offset_y; \
\
void *out_buffer; /*!< TODO: alignment restriction */ \
uint32_t out_pic_w; \
uint32_t out_pic_h; \
uint32_t out_block_offset_x; \
uint32_t out_block_offset_y; \
\
ppa_sr_rotation_angle_t rotation_angle; \
float scale_x; \
float scale_y; \
bool mirror_x; \
bool mirror_y; \
\
struct { \
ppa_sr_color_mode_t mode; \
color_range_t yuv_range; \
color_conv_std_rgb_yuv_t yuv_std; \
bool rgb_swap; \
bool byte_swap; \
ppa_alpha_mode_t alpha_mode; \
uint32_t alpha_value; /*!< When PPA_ALPHA_FIX_VALUE mode is selected, alpha_value is the alpha value to be replaced with (output_alpha = alpha_value)
When PPA_ALPHA_SCALE mode is selected, alpha_value/256 is the multiplier to the input alpha value (output_alpha = input_alpha * alpha_value / 256)
When other alpha modes are selected, this field is not used */ \
} in_color; \
\
struct { \
ppa_sr_color_mode_t mode; \
color_range_t yuv_range; \
color_conv_std_rgb_yuv_t yuv_std; \
} out_color; \
}
/**
* @brief A collection of configuration items to perform a PPA SR operation
*/
typedef struct {
void *in_buffer; // TODO: could be a buffer list, link descriptors together, process a batch
// uint32_t batch_num; // However, is it necessary? psram can not store too many pictures
uint32_t in_pic_w;
uint32_t in_pic_h;
uint32_t in_block_w;
uint32_t in_block_h;
uint32_t in_block_offset_x;
uint32_t in_block_offset_y;
void *out_buffer; // TODO: alignment restriction
uint32_t out_pic_w;
uint32_t out_pic_h;
uint32_t out_block_offset_x;
uint32_t out_block_offset_y;
ppa_sr_rotation_angle_t rotation_angle;
float scale_x;
float scale_y;
bool mirror_x;
bool mirror_y;
struct {
ppa_sr_color_mode_t mode;
color_range_t yuv_range;
color_conv_std_rgb_yuv_t yuv_std;
bool rgb_swap;
bool byte_swap;
ppa_alpha_mode_t alpha_mode;
uint32_t alpha_value; /*!< When PPA_ALPHA_FIX_VALUE mode is selected, alpha_value is the alpha value to be replaced with (output_alpha = alpha_value)
When PPA_ALPHA_SCALE mode is selected, alpha_value/256 is the multiplier to the input alpha value (output_alpha = input_alpha * alpha_value / 256)
When other alpha modes are selected, this field is not used */
} in_color;
struct {
ppa_sr_color_mode_t mode;
color_range_t yuv_range;
color_conv_std_rgb_yuv_t yuv_std;
} out_color;
} ppa_sr_trans_config_t;
typedef PPA_SR_TRANS_CONFIG ppa_sr_trans_config_t;
/**
* @brief Perform a scaling-and-rotating (SR) operation to a picture
@@ -191,9 +191,22 @@ typedef struct {
*/
esp_err_t ppa_do_blend(ppa_invoker_handle_t ppa_invoker, const ppa_blend_trans_config_t *config, ppa_trans_mode_t mode);
// TODO: FILL
typedef struct {
uint32_t fill_block_w;
uint32_t fill_block_h;
uint32_t fill_argb_color; /*!< The color to be filled, in ARGB8888 format ((A[31:24], R[23:16], G[15: 8], B[7:0])) */
void *out_buffer;
uint32_t out_pic_w;
uint32_t out_pic_h;
uint32_t out_block_offset_x;
uint32_t out_block_offset_y;
struct {
ppa_blend_color_mode_t mode;
} out_color;
// colorkey???
} ppa_fill_trans_config_t;
/**

View File

@@ -55,10 +55,18 @@ typedef struct ppa_engine_t ppa_engine_t;
typedef struct ppa_invoker_t ppa_invoker_t;
typedef ppa_sr_trans_config_t ppa_sr_transaction_t;
typedef struct {
PPA_SR_TRANS_CONFIG;
uint32_t scale_x_int;
uint32_t scale_x_frag;
uint32_t scale_y_int;
uint32_t scale_y_frag;
} ppa_sr_transaction_t;
typedef ppa_blend_trans_config_t ppa_blend_transaction_t;
typedef ppa_fill_trans_config_t ppa_fill_transaction_t;
typedef struct ppa_trans_s {
STAILQ_ENTRY(ppa_trans_s) entry; // link entry
dma2d_trans_config_t *trans_desc;
@@ -71,7 +79,8 @@ typedef struct {
union {
ppa_sr_transaction_t *sr_desc;
ppa_blend_transaction_t *blend_desc;
// ppa_fill_transaction_t
ppa_fill_transaction_t *fill_desc;
void *op_desc;
};
ppa_engine_t *ppa_engine;
ppa_trans_t *trans_elm;
@@ -146,18 +155,19 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
static esp_err_t ppa_engine_release(ppa_engine_t *ppa_engine);
static bool ppa_sr_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config);
static bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config);
static bool ppa_fill_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config);
extern uint32_t dma2d_tx_channel_reserved_mask[SOC_DMA2D_GROUPS];
extern uint32_t dma2d_rx_channel_reserved_mask[SOC_DMA2D_GROUPS];
static uint32_t ppa_specified_tx_channel_mask = 0;
static uint32_t ppa_specified_rx_channel_mask = 0;
static __attribute__((constructor)) void ppa_reserve_dma2d_channels(void)
{
// ppa_specified_tx_channel_mask = 1 << 0;
// ppa_specified_rx_channel_mask = 1 << 0;
dma2d_tx_channel_reserved_mask[0] |= ppa_specified_tx_channel_mask;
dma2d_rx_channel_reserved_mask[0] |= ppa_specified_rx_channel_mask;
}
// extern uint32_t dma2d_tx_channel_reserved_mask[SOC_DMA2D_GROUPS];
// extern uint32_t dma2d_rx_channel_reserved_mask[SOC_DMA2D_GROUPS];
// static uint32_t ppa_specified_tx_channel_mask = 0;
// static uint32_t ppa_specified_rx_channel_mask = 0;
// static __attribute__((constructor)) void ppa_reserve_dma2d_channels(void)
// {
// // ppa_specified_tx_channel_mask = 1 << 0;
// // ppa_specified_rx_channel_mask = 1 << 0;
// dma2d_tx_channel_reserved_mask[0] |= ppa_specified_tx_channel_mask;
// dma2d_rx_channel_reserved_mask[0] |= ppa_specified_rx_channel_mask;
// }
// TODO: acquire pm_lock?
static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engine_t **ret_engine)
@@ -694,11 +704,7 @@ static void ppa_recycle_transaction(ppa_trans_t *trans_elm)
if (trans_elm->trans_desc) {
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = (ppa_dma2d_trans_on_picked_config_t *)trans_elm->trans_desc->user_config;
if (trans_on_picked_desc) {
if (trans_on_picked_desc->trigger_periph == DMA2D_TRIG_PERIPH_PPA_SR) {
free(trans_on_picked_desc->sr_desc);
} else if (trans_on_picked_desc->trigger_periph == DMA2D_TRIG_PERIPH_PPA_BLEND) {
free(trans_on_picked_desc->blend_desc);
}
free(trans_on_picked_desc->op_desc);
free(trans_on_picked_desc);
}
free(trans_elm->trans_desc);
@@ -710,7 +716,7 @@ static void ppa_recycle_transaction(ppa_trans_t *trans_elm)
}
}
static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t *ppa_engine_base, ppa_operation_t ppa_operation, const void *config, ppa_trans_mode_t mode)
static esp_err_t ppa_prepare_trans_elm(ppa_invoker_handle_t ppa_invoker, ppa_engine_t *ppa_engine_base, ppa_operation_t ppa_operation, const void *config, ppa_trans_t **trans_elm, ppa_trans_mode_t mode)
{
esp_err_t ret = ESP_OK;
ppa_engine_type_t engine_type = ppa_engine_base->type;
@@ -720,7 +726,8 @@ static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t
dma2d_trans_config_t *dma_trans_desc = (dma2d_trans_config_t *)heap_caps_calloc(1, sizeof(dma2d_trans_config_t), PPA_MEM_ALLOC_CAPS);
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = (ppa_dma2d_trans_on_picked_config_t *)heap_caps_calloc(1, sizeof(ppa_dma2d_trans_on_picked_config_t), PPA_MEM_ALLOC_CAPS);
size_t ppa_trans_desc_size = (ppa_operation == PPA_OPERATION_SR) ? sizeof(ppa_sr_transaction_t) :
(ppa_operation == PPA_OPERATION_BLEND) ? sizeof(ppa_blend_transaction_t) : 0;
(ppa_operation == PPA_OPERATION_BLEND) ? sizeof(ppa_blend_transaction_t) :
(ppa_operation == PPA_OPERATION_FILL) ? sizeof(ppa_fill_transaction_t) : 0;
assert(ppa_trans_desc_size != 0);
void *ppa_trans_desc = heap_caps_calloc(1, ppa_trans_desc_size, PPA_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_trans_elm && dma_trans_elm && dma_trans_desc && trans_on_picked_desc && ppa_trans_desc, ESP_ERR_NO_MEM, err, TAG, "no mem for transaction storage");
@@ -728,32 +735,51 @@ static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t
new_trans_elm->sem = xSemaphoreCreateBinaryWithCaps(PPA_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_trans_elm->sem, ESP_ERR_NO_MEM, err, TAG, "no mem for transaction storage");
}
memcpy(ppa_trans_desc, config, ppa_trans_desc_size);
trans_on_picked_desc->blend_desc = ppa_trans_desc;
size_t cpy_size = (ppa_operation == PPA_OPERATION_SR) ? sizeof(ppa_sr_trans_config_t) :
(ppa_operation == PPA_OPERATION_BLEND) ? sizeof(ppa_blend_trans_config_t) :
(ppa_operation == PPA_OPERATION_FILL) ? sizeof(ppa_fill_trans_config_t) : 0;
memcpy(ppa_trans_desc, config, cpy_size);
trans_on_picked_desc->op_desc = ppa_trans_desc;
trans_on_picked_desc->ppa_engine = ppa_engine_base;
trans_on_picked_desc->trans_elm = new_trans_elm;
trans_on_picked_desc->trigger_periph = (engine_type == PPA_ENGINE_TYPE_SR) ? DMA2D_TRIG_PERIPH_PPA_SR : DMA2D_TRIG_PERIPH_PPA_BLEND;
dma_trans_desc->tx_channel_num = (ppa_operation == PPA_OPERATION_SR) ? 1 :
(ppa_operation == PPA_OPERATION_BLEND) ? 2 : 0;
(ppa_operation == PPA_OPERATION_BLEND) ? 2 : 0; // PPA_OPERATION_FILL does not have data input
dma_trans_desc->rx_channel_num = 1;
if (ppa_operation == PPA_OPERATION_SR) {
dma_trans_desc->specified_tx_channel_mask = ppa_specified_tx_channel_mask;
dma_trans_desc->specified_rx_channel_mask = ppa_specified_rx_channel_mask;
}
// dma_trans_desc->specified_tx_channel_mask = ppa_specified_tx_channel_mask;
// dma_trans_desc->specified_rx_channel_mask = ppa_specified_rx_channel_mask;
dma_trans_desc->user_config = (void *)trans_on_picked_desc;
dma_trans_desc->on_job_picked = (ppa_operation == PPA_OPERATION_SR) ? ppa_sr_transaction_on_picked :
(ppa_operation == PPA_OPERATION_BLEND) ? ppa_blend_transaction_on_picked : NULL;
(ppa_operation == PPA_OPERATION_BLEND) ? ppa_blend_transaction_on_picked :
(ppa_operation == PPA_OPERATION_FILL) ? ppa_fill_transaction_on_picked : NULL;
new_trans_elm->trans_desc = dma_trans_desc;
new_trans_elm->dma_trans_placeholder = dma_trans_elm;
new_trans_elm->invoker = ppa_invoker;
*trans_elm = new_trans_elm;
err:
if (ret != ESP_OK) {
ppa_recycle_transaction(new_trans_elm);
*trans_elm = NULL;
}
return ret;
}
static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t *ppa_engine_base, ppa_trans_t *trans_elm, ppa_trans_mode_t mode)
{
esp_err_t ret = ESP_OK;
ppa_engine_type_t engine_type = ppa_engine_base->type;
portENTER_CRITICAL(&ppa_invoker->spinlock);
if (ppa_invoker->in_accepting_trans_state) {
// Send transaction into PPA engine queue
STAILQ_INSERT_TAIL(&ppa_engine_base->trans_stailq, new_trans_elm, entry);
STAILQ_INSERT_TAIL(&ppa_engine_base->trans_stailq, trans_elm, entry);
if (engine_type == PPA_ENGINE_TYPE_SR) {
ppa_invoker->sr_trans_cnt++;
} else {
@@ -777,17 +803,17 @@ static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t
ppa_trans_t *temp = NULL;
portENTER_CRITICAL(&ppa_engine_base->spinlock);
STAILQ_FOREACH(temp, &ppa_engine_base->trans_stailq, entry) {
if (temp == new_trans_elm) {
if (temp == trans_elm) {
found = true;
break;
}
}
portEXIT_CRITICAL(&ppa_engine_base->spinlock);
if (found) {
ret = ppa_dma2d_enqueue(new_trans_elm);
ret = ppa_dma2d_enqueue(trans_elm);
if (ret != ESP_OK) {
portENTER_CRITICAL(&ppa_engine_base->spinlock);
STAILQ_REMOVE(&ppa_engine_base->trans_stailq, new_trans_elm, ppa_trans_s, entry);
STAILQ_REMOVE(&ppa_engine_base->trans_stailq, trans_elm, ppa_trans_s, entry);
portEXIT_CRITICAL(&ppa_engine_base->spinlock);
xSemaphoreGive(ppa_engine_base->sem);
goto err;
@@ -801,15 +827,12 @@ static esp_err_t ppa_do_operation(ppa_invoker_handle_t ppa_invoker, ppa_engine_t
// while (1) {
// printf("ppa intr: %ld\n", PPA.int_raw.val);
// }
xSemaphoreTake(new_trans_elm->sem, portMAX_DELAY); // Given in the ISR
xSemaphoreTake(trans_elm->sem, portMAX_DELAY); // Given in the ISR
// Sanity check new_trans_elm not in trans_stailq anymore? (loop takes time tho)
ppa_recycle_transaction(new_trans_elm);
ppa_recycle_transaction(trans_elm);
}
err:
if (ret != ESP_OK) {
ppa_recycle_transaction(new_trans_elm);
}
return ret;
}
@@ -1011,8 +1034,8 @@ static bool ppa_sr_transaction_on_picked(uint32_t num_chans, const dma2d_trans_c
// TODO: sr_macro_bk_ro_bypass
// PPA.sr_byte_order.sr_macro_bk_ro_bypass = 1;
ppa_ll_sr_set_rotation_angle(s_platform.hal.dev, sr_trans_desc->rotation_angle);
ppa_ll_sr_set_scaling_x(s_platform.hal.dev, (uint32_t)sr_trans_desc->scale_x, (uint32_t)(sr_trans_desc->scale_x * (PPA_LL_SR_SCALING_FRAG_MAX + 1)) & PPA_LL_SR_SCALING_FRAG_MAX);
ppa_ll_sr_set_scaling_y(s_platform.hal.dev, (uint32_t)sr_trans_desc->scale_y, (uint32_t)(sr_trans_desc->scale_y * (PPA_LL_SR_SCALING_FRAG_MAX + 1)) & PPA_LL_SR_SCALING_FRAG_MAX);
ppa_ll_sr_set_scaling_x(s_platform.hal.dev, sr_trans_desc->scale_x_int, sr_trans_desc->scale_x_frag);
ppa_ll_sr_set_scaling_y(s_platform.hal.dev, sr_trans_desc->scale_y_int, sr_trans_desc->scale_y_frag);
ppa_ll_sr_enable_mirror_x(s_platform.hal.dev, sr_trans_desc->mirror_x);
ppa_ll_sr_enable_mirror_y(s_platform.hal.dev, sr_trans_desc->mirror_y);
@@ -1039,7 +1062,25 @@ esp_err_t ppa_do_scale_and_rotate(ppa_invoker_handle_t ppa_invoker, const ppa_sr
// TODO: Maybe do buffer writeback and invalidation here, instead of in on_picked?
return ppa_do_operation(ppa_invoker, ppa_invoker->sr_engine, PPA_OPERATION_SR, (void *)config, mode);
ppa_trans_t *trans_elm = NULL;
esp_err_t ret = ppa_prepare_trans_elm(ppa_invoker, ppa_invoker->sr_engine, PPA_OPERATION_SR, (void *)config, &trans_elm, mode);
if (ret == ESP_OK) {
assert(trans_elm);
// Pre-process some data
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = trans_elm->trans_desc->user_config;
ppa_sr_transaction_t *sr_trans_desc = trans_on_picked_desc->sr_desc;
sr_trans_desc->scale_x_int = (uint32_t)sr_trans_desc->scale_x;
sr_trans_desc->scale_x_frag = (uint32_t)(sr_trans_desc->scale_x * (PPA_LL_SR_SCALING_FRAG_MAX + 1)) & PPA_LL_SR_SCALING_FRAG_MAX;
sr_trans_desc->scale_y_int = (uint32_t)sr_trans_desc->scale_y;
sr_trans_desc->scale_y_frag = (uint32_t)(sr_trans_desc->scale_y * (PPA_LL_SR_SCALING_FRAG_MAX + 1)) & PPA_LL_SR_SCALING_FRAG_MAX;
ret = ppa_do_operation(ppa_invoker, ppa_invoker->sr_engine, trans_elm, mode);
if (ret != ESP_OK) {
ppa_recycle_transaction(trans_elm);
}
}
return ret;
}
static bool ppa_blend_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config)
@@ -1210,10 +1251,113 @@ esp_err_t ppa_do_blend(ppa_invoker_handle_t ppa_invoker, const ppa_blend_trans_c
// TODO: Maybe do buffer writeback and invalidation here, instead of in on_picked?
return ppa_do_operation(ppa_invoker, ppa_invoker->blending_engine, PPA_OPERATION_BLEND, (void *)config, mode);
ppa_trans_t *trans_elm = NULL;
esp_err_t ret = ppa_prepare_trans_elm(ppa_invoker, ppa_invoker->blending_engine, PPA_OPERATION_BLEND, (void *)config, &trans_elm, mode);
if (ret == ESP_OK) {
assert(trans_elm);
ret = ppa_do_operation(ppa_invoker, ppa_invoker->blending_engine, trans_elm, mode);
if (ret != ESP_OK) {
ppa_recycle_transaction(trans_elm);
}
}
return ret;
}
static bool ppa_fill_transaction_on_picked(uint32_t num_chans, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config)
{
assert(num_chans == 1 && dma2d_chans && user_config);
ppa_dma2d_trans_on_picked_config_t *trans_on_picked_desc = (ppa_dma2d_trans_on_picked_config_t *)user_config;
assert(trans_on_picked_desc->trigger_periph == DMA2D_TRIG_PERIPH_PPA_BLEND && trans_on_picked_desc->fill_desc && trans_on_picked_desc->ppa_engine);
ppa_fill_transaction_t *fill_trans_desc = trans_on_picked_desc->fill_desc;
ppa_blend_engine_t *blend_engine = __containerof(trans_on_picked_desc->ppa_engine, ppa_blend_engine_t, base);
// Free 2D-DMA transaction placeholder (transaction has already been moved out from 2D-DMA queue)
free(trans_on_picked_desc->trans_elm->dma_trans_placeholder);
// Get the required 2D-DMA channel handles
assert(dma2d_chans[0].dir == DMA2D_CHANNEL_DIRECTION_RX);
dma2d_channel_handle_t dma2d_rx_chan = dma2d_chans[0].chan;
// Invalidate is performed on the entire picture (the window content is not continuous in the buffer)
color_space_pixel_format_t out_pixel_format = {
.color_type_id = fill_trans_desc->out_color.mode,
};
uint32_t out_buffer_len = fill_trans_desc->out_pic_w * fill_trans_desc->out_pic_h * color_hal_pixel_format_get_bit_depth(out_pixel_format) / 8;
esp_cache_msync(fill_trans_desc->out_buffer, out_buffer_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
// Fill 2D-DMA descriptors
blend_engine->dma_rx_desc->vb_size = fill_trans_desc->fill_block_h;
blend_engine->dma_rx_desc->hb_length = fill_trans_desc->fill_block_w;
blend_engine->dma_rx_desc->err_eof = 0;
blend_engine->dma_rx_desc->dma2d_en = 1;
blend_engine->dma_rx_desc->suc_eof = 1;
blend_engine->dma_rx_desc->owner = DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA;
blend_engine->dma_rx_desc->va_size = fill_trans_desc->out_pic_h;
blend_engine->dma_rx_desc->ha_length = fill_trans_desc->out_pic_w;
blend_engine->dma_rx_desc->pbyte = dma2d_desc_pixel_format_to_pbyte_value(out_pixel_format);
blend_engine->dma_rx_desc->y = fill_trans_desc->out_block_offset_y;
blend_engine->dma_rx_desc->x = fill_trans_desc->out_block_offset_x;
blend_engine->dma_rx_desc->mode = DMA2D_DESCRIPTOR_BLOCK_RW_MODE_SINGLE;
blend_engine->dma_rx_desc->buffer = (void *)fill_trans_desc->out_buffer;
blend_engine->dma_rx_desc->next = NULL;
esp_cache_msync((void *)blend_engine->dma_rx_desc, s_platform.dma_desc_mem_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
// Configure 2D-DMA channels
dma2d_trigger_t trig_periph = {
.periph = DMA2D_TRIG_PERIPH_PPA_BLEND,
.periph_sel_id = SOC_DMA2D_TRIG_PERIPH_PPA_BLEND_RX,
};
dma2d_connect(dma2d_rx_chan, &trig_periph);
dma2d_transfer_ability_t dma_transfer_ability = {
.data_burst_length = DMA2D_DATA_BURST_LENGTH_128,
.desc_burst_en = true,
.mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE,
};
dma2d_set_transfer_ability(dma2d_rx_chan, &dma_transfer_ability);
dma2d_rx_event_callbacks_t dma_event_cbs = {
.on_recv_eof = ppa_transaction_done_cb,
};
dma2d_register_rx_event_callbacks(dma2d_rx_chan, &dma_event_cbs, (void *)trans_on_picked_desc->trans_elm);
ppa_ll_blend_reset(s_platform.hal.dev);
dma2d_set_desc_addr(dma2d_rx_chan, (intptr_t)blend_engine->dma_rx_desc);
dma2d_start(dma2d_rx_chan);
// Configure PPA Blending engine
ppa_ll_blend_configure_filling_block(s_platform.hal.dev, fill_trans_desc->fill_argb_color, fill_trans_desc->fill_block_w, fill_trans_desc->fill_block_h);
ppa_ll_blend_set_tx_color_mode(s_platform.hal.dev, fill_trans_desc->out_color.mode);
ppa_ll_blend_start(s_platform.hal.dev, PPA_LL_BLEND_TRANS_MODE_FILL);
// No need to yield
return false;
}
esp_err_t ppa_do_fill(ppa_invoker_handle_t ppa_invoker, const ppa_fill_trans_config_t *config, ppa_trans_mode_t mode)
{
return ESP_OK;
ESP_RETURN_ON_FALSE(ppa_invoker && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(ppa_invoker->blending_engine, ESP_ERR_INVALID_ARG, TAG, "invoker did not register to Blending engine");
ESP_RETURN_ON_FALSE(mode <= PPA_TRANS_MODE_NON_BLOCKING, ESP_ERR_INVALID_ARG, TAG, "invalid mode");
// TODO: ARG CHECK
// fill_block_w <= PPA_BLEND_HB_V, fill_block_h <= PPA_BLEND_VB_V
// TODO: Maybe do buffer invalidation here, instead of in on_picked?
ppa_trans_t *trans_elm = NULL;
esp_err_t ret = ppa_prepare_trans_elm(ppa_invoker, ppa_invoker->blending_engine, PPA_OPERATION_FILL, (void *)config, &trans_elm, mode);
if (ret == ESP_OK) {
assert(trans_elm);
ret = ppa_do_operation(ppa_invoker, ppa_invoker->blending_engine, trans_elm, mode);
if (ret != ESP_OK) {
ppa_recycle_transaction(trans_elm);
}
}
return ret;
}

View File

@@ -638,7 +638,7 @@ static inline void ppa_ll_blend_configure_rx_fg_alpha(ppa_dev_t *dev, ppa_alpha_
* @param dev Peripheral instance address
* @param data The fix data to be filled to the image block pixels in ARGB8888 format
* @param hb The horizontal width of image block that would be filled in fix pixel filling mode. The unit is pixel.
* @param vb The vertical width of image block that would be filled in fix pixel filling mode. The unit is pixel.
* @param vb The vertical height of image block that would be filled in fix pixel filling mode. The unit is pixel.
*/
static inline void ppa_ll_blend_configure_filling_block(ppa_dev_t *dev, uint32_t data, uint32_t hb, uint32_t vb)
{