mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
feat(ppa): add sleep retention support for DMA2D and PPA
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include "hal/color_hal.h"
|
||||
#include "hal/color_types.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
@@ -55,6 +56,25 @@ const dma2d_trans_on_picked_callback_t ppa_oper_trans_on_picked_func[PPA_OPERATI
|
||||
[PPA_OPERATION_FILL] = ppa_fill_transaction_on_picked,
|
||||
};
|
||||
|
||||
/** PPA Power Management Strategy
|
||||
*
|
||||
* SRM and Blending have separate CPU_FREQ_MAX PM locks, and each PM lock is acquired whenever there is PPA operation in process.
|
||||
*
|
||||
* When no PPA operation is in process, sleep can happen, and PPA domain can be powered down if allow_pd is set.
|
||||
* Necessary register context will be saved and restored by sleep retention.
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
static esp_err_t ppa_create_sleep_retention_link_cb(void *arg)
|
||||
{
|
||||
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||
esp_err_t err = sleep_retention_entries_create(ppa_reg_retention_info.regdma_entry_array,
|
||||
ppa_reg_retention_info.array_size,
|
||||
REGDMA_LINK_PRI_PPA, module);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engine_t **ret_engine)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@@ -187,6 +207,40 @@ static esp_err_t ppa_engine_acquire(const ppa_engine_config_t *config, ppa_engin
|
||||
ESP_LOGE(TAG, "install 2D-DMA failed");
|
||||
goto wrap_up;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
s_platform.flags.allow_pd = config->flags.allow_pd; // Uses the first acquired engine's allow_pd flag as the platform's allow_pd flag
|
||||
|
||||
// Initialize sleep retention module for PPA
|
||||
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = {
|
||||
.create = {
|
||||
.handle = ppa_create_sleep_retention_link_cb,
|
||||
.arg = NULL,
|
||||
},
|
||||
},
|
||||
.attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH,
|
||||
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
|
||||
};
|
||||
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||
// even though the sleep retention module init failed, PPA driver should still work, so just warning here
|
||||
ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep");
|
||||
} else if (s_platform.flags.allow_pd) {
|
||||
if (sleep_retention_module_allocate(module) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "fail to allocate retention link list");
|
||||
// don't call sleep_retention_module_deinit here, otherwise PPA peripheral may be powered off during sleep
|
||||
} else {
|
||||
if (sleep_retention_module_attach(module) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s_platform.flags.allow_pd != config->flags.allow_pd) {
|
||||
ESP_LOGW(TAG, "allow_pd flag mismatch among clients, will follow flags.allow_pd = %d", s_platform.flags.allow_pd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
wrap_up:
|
||||
@@ -247,6 +301,20 @@ static esp_err_t ppa_engine_release(ppa_engine_t *ppa_engine)
|
||||
if (!s_platform.srm && !s_platform.blending) {
|
||||
assert(s_platform.srm_engine_ref_count == 0 && s_platform.blend_engine_ref_count == 0);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
sleep_retention_module_t module = ppa_reg_retention_info.module;
|
||||
if (sleep_retention_is_module_attached(module)) {
|
||||
sleep_retention_module_detach(module);
|
||||
}
|
||||
if (sleep_retention_is_module_created(module)) {
|
||||
sleep_retention_module_free(module);
|
||||
}
|
||||
if (sleep_retention_is_module_inited(module)) {
|
||||
sleep_retention_module_deinit(module);
|
||||
}
|
||||
s_platform.flags.allow_pd = false;
|
||||
#endif
|
||||
|
||||
if (s_platform.dma2d_pool_handle) {
|
||||
dma2d_release_pool(s_platform.dma2d_pool_handle); // TODO: check return value. If not ESP_OK, then must be error on other 2D-DMA clients :( Give a warning log?
|
||||
s_platform.dma2d_pool_handle = NULL;
|
||||
@@ -288,11 +356,13 @@ esp_err_t ppa_register_client(const ppa_client_config_t *config, ppa_client_hand
|
||||
if (config->oper_type == PPA_OPERATION_SRM) {
|
||||
ppa_engine_config_t engine_config = {
|
||||
.engine = PPA_ENGINE_TYPE_SRM,
|
||||
.flags.allow_pd = config->flags.allow_pd,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire SRM engine");
|
||||
} else if (config->oper_type == PPA_OPERATION_BLEND || config->oper_type == PPA_OPERATION_FILL) {
|
||||
ppa_engine_config_t engine_config = {
|
||||
.engine = PPA_ENGINE_TYPE_BLEND,
|
||||
.flags.allow_pd = config->flags.allow_pd,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(ppa_engine_acquire(&engine_config, &client->engine), err, TAG, "unable to acquire Blending engine");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "hal/ppa_types.h"
|
||||
#include "hal/ppa_hal.h"
|
||||
#include "esp_pm.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/regdma.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -81,6 +83,9 @@ typedef struct ppa_blend_engine_t {
|
||||
|
||||
typedef struct {
|
||||
ppa_engine_type_t engine; // Engine type
|
||||
struct {
|
||||
uint32_t allow_pd: 1; // If set, engine allows the power domain to be powered off when system enters sleep mode
|
||||
} flags; // Configuration flags
|
||||
} ppa_engine_config_t;
|
||||
|
||||
/******************************** CLIENT *************************************/
|
||||
@@ -247,8 +252,22 @@ struct ppa_platform_t {
|
||||
size_t int_mem_align; // Alignment requirement for the internal outgoing buffer to satisfy cache line size
|
||||
size_t ext_mem_align; // Alignment requirement for the external outgoing buffer to satisfy cache line size
|
||||
uint32_t dma_desc_mem_size; // Alignment requirement for the 2D-DMA descriptor to satisfy cache line size
|
||||
struct {
|
||||
uint32_t allow_pd: 1; // If set, driver allows the power domain to be powered off when system enters sleep mode
|
||||
} flags; // Configuration flags
|
||||
};
|
||||
|
||||
#if SOC_PAU_SUPPORTED
|
||||
#include "soc/retention_periph_defs.h"
|
||||
typedef struct {
|
||||
const periph_retention_module_t module;
|
||||
const regdma_entries_config_t *regdma_entry_array;
|
||||
uint32_t array_size;
|
||||
} ppa_retention_desc_t;
|
||||
|
||||
extern const ppa_retention_desc_t ppa_reg_retention_info;
|
||||
#endif // SOC_PAU_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user