From 0f0edc051a7ecf935594543fd5a50ff307514a85 Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Thu, 2 Apr 2026 18:41:35 +0800 Subject: [PATCH] ci(esp32s31): Add ci target test for esp32s31 --- components/esp_driver_jpeg/jpeg_decode.c | 30 +- components/esp_driver_jpeg/jpeg_encode.c | 26 +- .../test_apps/jpeg_test_apps/README.md | 4 +- .../jpeg_test_apps/main/test_jpeg_decode.c | 14 +- .../main/test_jpeg_performance.h | 13 +- .../test_apps/jpeg_test_apps/pytest_jpeg.py | 3 +- .../jpeg_test_apps/sdkconfig.defaults | 7 - .../jpeg_test_apps/sdkconfig.defaults.esp32p4 | 6 + .../sdkconfig.defaults.esp32s31 | 6 + .../esp32s31/include/hal/jpeg_ll.h | 696 ++++++++++++++++++ .../esp_hal_jpeg/esp32s31/jpeg_periph.c | 28 + components/esp_hal_jpeg/jpeg_hal.c | 4 + .../esp32s31/include/soc/Kconfig.soc_caps.in | 12 + .../include/soc/retention_periph_defs.h | 17 +- .../soc/esp32s31/include/soc/soc_caps.h | 5 + .../soc/esp32s31/register/soc/jpeg_struct.h | 3 +- docs/doxygen/Doxyfile_esp32s31 | 5 +- examples/peripherals/.build-test-rules.yml | 4 +- .../jpeg/jpeg_decode/main/jpeg_decode_main.c | 10 +- 19 files changed, 848 insertions(+), 45 deletions(-) create mode 100644 components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32p4 create mode 100644 components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32s31 create mode 100644 components/esp_hal_jpeg/esp32s31/include/hal/jpeg_ll.h create mode 100644 components/esp_hal_jpeg/esp32s31/jpeg_periph.c diff --git a/components/esp_driver_jpeg/jpeg_decode.c b/components/esp_driver_jpeg/jpeg_decode.c index ee161d29cd..50efd00c41 100644 --- a/components/esp_driver_jpeg/jpeg_decode.c +++ b/components/esp_driver_jpeg/jpeg_decode.c @@ -265,12 +265,18 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_ }; // Before 2DDMA starts. sync buffer from cache to psram - ret = esp_cache_msync((void*)decoder_engine->header_info->buffer_offset, decoder_engine->header_info->buffer_left, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - assert(ret == ESP_OK); + size_t cache_line_size = esp_cache_get_line_size_by_addr(decoder_engine->header_info->buffer_offset); + if (cache_line_size > 0) { + ret = esp_cache_msync((void*)decoder_engine->header_info->buffer_offset, decoder_engine->header_info->buffer_left, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + assert(ret == ESP_OK); + } // Before 2DDMA starts, invalidate cache ahead of time. - ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - assert(ret == ESP_OK); + cache_line_size = esp_cache_get_line_size_by_addr(decoder_engine->decoded_buf); + if (cache_line_size > 0) { + ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + assert(ret == ESP_OK); + } ESP_GOTO_ON_ERROR(dma2d_enqueue(decoder_engine->dma2d_group_handle, &trans_desc, decoder_engine->trans_desc), err2, TAG, "enqueue dma2d failed"); bool need_yield; @@ -290,8 +296,11 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_ if (jpeg_dma2d_event.dma_evt & JPEG_DMA2D_RX_EOF) { if (outbuf_cache_line_size > 0) { - ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - assert(ret == ESP_OK); + size_t cache_line_size = esp_cache_get_line_size_by_addr(decoder_engine->decoded_buf); + if (cache_line_size > 0) { + ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + assert(ret == ESP_OK); + } } break; } @@ -385,9 +394,12 @@ static void cfg_desc(jpeg_decoder_handle_t decoder_engine, dma2d_descriptor_t *d dsc->ha_length = ha; dsc->buffer = buf; dsc->next = next_dsc; - esp_err_t ret = esp_cache_msync((void*)dsc, decoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - assert(ret == ESP_OK); - (void)ret; + uint32_t line_size = esp_cache_get_line_size_by_addr(dsc); + if (line_size > 0) { + esp_err_t ret = esp_cache_msync((void*)dsc, decoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + assert(ret == ESP_OK); + (void)ret; + } } static esp_err_t jpeg_dec_config_dma_descriptor(jpeg_decoder_handle_t decoder_engine) diff --git a/components/esp_driver_jpeg/jpeg_encode.c b/components/esp_driver_jpeg/jpeg_encode.c index 9fa895fa99..1d2df2afae 100644 --- a/components/esp_driver_jpeg/jpeg_encode.c +++ b/components/esp_driver_jpeg/jpeg_encode.c @@ -283,8 +283,11 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ memset(encoder_engine->txlink, 0, encoder_engine->dma_desc_size); s_cfg_desc(encoder_engine, encoder_engine->txlink, JPEG_DMA2D_2D_ENABLE, DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE, dma_vb, dma_hb, JPEG_DMA2D_EOF_NOT_LAST, dma2d_desc_pixel_format_to_pbyte_value(encoder_engine->picture_format), DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA, encoder_engine->header_info->origin_v, encoder_engine->header_info->origin_h, raw_buffer, NULL); - ret = esp_cache_msync((void*)raw_buffer, inbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - assert(ret == ESP_OK); + size_t cache_line_size = esp_cache_get_line_size_by_addr(raw_buffer); + if (cache_line_size > 0) { + ret = esp_cache_msync((void*)raw_buffer, inbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + assert(ret == ESP_OK); + } dma2d_trans_config_t trans_desc = { .tx_channel_num = 1, @@ -314,10 +317,16 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ } if (s_rcv_event.dma_evt & JPEG_DMA2D_RX_EOF) { - ESP_GOTO_ON_ERROR(esp_cache_msync((void*)encoder_engine->rxlink, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err1, TAG, "sync memory to cache failed"); + size_t cache_line_size = esp_cache_get_line_size_by_addr(encoder_engine->rxlink); + if (cache_line_size > 0) { + ESP_GOTO_ON_ERROR(esp_cache_msync((void*)encoder_engine->rxlink, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err1, TAG, "sync memory to cache failed"); + } compressed_size = s_dma_desc_get_len(encoder_engine->rxlink); uint32_t _compressed_size = JPEG_ALIGN_UP(compressed_size, cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)); - ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), _compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err1, TAG, "sync memory to cache failed"); + cache_line_size = esp_cache_get_line_size_by_addr(bit_stream + encoder_engine->header_info->header_len); + if (cache_line_size > 0) { + ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), _compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err1, TAG, "sync memory to cache failed"); + } break; } } @@ -540,9 +549,12 @@ static void s_cfg_desc(jpeg_encoder_handle_t encoder_engine, dma2d_descriptor_t dsc->ha_length = ha; dsc->buffer = buf; dsc->next = next_dsc; - esp_err_t ret = esp_cache_msync((void*)dsc, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - assert(ret == ESP_OK); - (void)ret; + size_t cache_line_size = esp_cache_get_line_size_by_addr(dsc); + if (cache_line_size > 0) { + esp_err_t ret = esp_cache_msync((void*)dsc, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + assert(ret == ESP_OK); + (void)ret; + } } static void s_jpeg_enc_config_picture_color_space(jpeg_encoder_handle_t encoder_engine) diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/README.md b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/README.md index 12cad491b1..80e36095a4 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/README.md +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32-P4 | -| ----------------- | -------- | +| Supported Targets | ESP32-P4 | ESP32-S31 | +| ----------------- | -------- | --------- | jpeg_decoder can be used to generate '*.rgb' file which to be used for this test. diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_decode.c b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_decode.c index 19a2bcc085..f8a28fddd9 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_decode.c +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_decode.c @@ -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: Unlicense OR CC0-1.0 */ @@ -24,12 +24,18 @@ extern const uint8_t image_esp1080_jpg_end[] asm("_binary_esp1080_jpg_end"); extern const uint8_t image_no_huff_jpg_start[] asm("_binary_no_huff_jpg_start"); extern const uint8_t image_no_huff_jpg_end[] asm("_binary_no_huff_jpg_end"); +#if CONFIG_IDF_TARGET_ESP32S31 +#define TIMEOUT_MS 80 +#else +#define TIMEOUT_MS 40 +#endif + TEST_CASE("JPEG decode driver memory leaking check", "[jpeg]") { jpeg_decoder_handle_t jpgd_handle; jpeg_decode_engine_cfg_t decode_eng_cfg = { - .timeout_ms = 40, + .timeout_ms = TIMEOUT_MS, }; int size = esp_get_free_heap_size(); @@ -48,7 +54,7 @@ TEST_CASE("JPEG decode performance test for 1080*1920 YUV->RGB picture", "[jpeg] jpeg_decode_engine_cfg_t decode_eng_cfg = { .intr_priority = 0, - .timeout_ms = 40, + .timeout_ms = TIMEOUT_MS, }; jpeg_decode_cfg_t decode_cfg = { @@ -97,7 +103,7 @@ TEST_CASE("JPEG decode image without Huffman table JPEG->RGB picture", "[jpeg]") jpeg_decode_engine_cfg_t decode_eng_cfg = { .intr_priority = 0, - .timeout_ms = 40, + .timeout_ms = TIMEOUT_MS, }; jpeg_decode_cfg_t decode_cfg = { diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_performance.h b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_performance.h index 27730b7aa3..8f040e4662 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_performance.h +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/main/test_jpeg_performance.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,12 +11,23 @@ extern "C" { #endif +#if CONFIG_IDF_TARGET_ESP32P4 + // Decoder performance lists #define IDF_PERFORMANCE_MIN_JPEG_DECODE_1080P_2_RGB565_PERFORMANCE 40 // 40 fps for 1080p decoder. // Encoder performance lists #define IDF_PERFORMANCE_MIN_JPEG_ENCODE_RGB888_2_480P_PERFORMANCE 160 // 160 fps for 480p encoder. +#elif CONFIG_IDF_TARGET_ESP32S31 +// Decoder performance lists +#define IDF_PERFORMANCE_MIN_JPEG_DECODE_1080P_2_RGB565_PERFORMANCE 20 // 20 fps for 1080p decoder. + +// Encoder performance lists +#define IDF_PERFORMANCE_MIN_JPEG_ENCODE_RGB888_2_480P_PERFORMANCE 100 // 100 fps for 480p encoder. + +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py index 2ee2e26ae3..5142020218 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/pytest_jpeg.py @@ -3,6 +3,7 @@ import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -13,6 +14,6 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['esp32p4'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_JPEG_CODEC_SUPPORTED == 1'), indirect=['target']) def test_jpeg(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults index a4f59246ad..9f2a7a7bce 100644 --- a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults @@ -1,13 +1,6 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT_EN=n -# SPIRAM configurations - -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MODE_HEX=y -CONFIG_SPIRAM_SPEED_200M=y -CONFIG_IDF_EXPERIMENTAL_FEATURES=y - # Partition table configurations CONFIG_PARTITION_TABLE_CUSTOM=y diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32p4 b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..9afab923aa --- /dev/null +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32p4 @@ -0,0 +1,6 @@ +# SPIRAM configurations + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y diff --git a/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32s31 b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32s31 new file mode 100644 index 0000000000..d16705e92b --- /dev/null +++ b/components/esp_driver_jpeg/test_apps/jpeg_test_apps/sdkconfig.defaults.esp32s31 @@ -0,0 +1,6 @@ +# SPIRAM configurations + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_250M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y diff --git a/components/esp_hal_jpeg/esp32s31/include/hal/jpeg_ll.h b/components/esp_hal_jpeg/esp32s31/include/hal/jpeg_ll.h new file mode 100644 index 0000000000..71980060da --- /dev/null +++ b/components/esp_hal_jpeg/esp32s31/include/hal/jpeg_ll.h @@ -0,0 +1,696 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/jpeg_struct.h" +#include "hal/jpeg_types.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/hp_system_struct.h" +#include "hal/config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define JPEG_LL_GET_HW(num) (&JPEG) + +typedef enum { + JPEG_LL_DONE = (1 << 0), + JPEG_LL_DCT_DONE = (1 << 11), +} jpeg_ll_codec_intr_t; + +typedef enum { + JPEG_LL_INTR_CID_ERR = (1 << 2), + JPEG_LL_INTR_C_DHT_DC_ID = (1 << 3), + JPEG_LL_INTR_C_DHT_AC_ID = (1 << 4), + JPEG_LL_INTR_C_DQT_ID = (1 << 5), + JPEG_LL_INTR_RST_UXP_ERR = (1 << 6), + JPEG_LL_INTR_RST_CHECK_NON_ERR = (1 << 7), + JPEG_LL_INTR_RST_CHECK_POS_ERR = (1 << 8), + JPEG_LL_INTR_OUT_EOF = (1 << 9), + JPEG_LL_INTR_SCAN_CHECK_NONE = (1 << 13), + JPEG_LL_INTR_SCAN_POS_ERR = (1 << 14), + JPEG_LL_INTR_UXP_DET = (1 << 15), + JPEG_LL_INTR_DE_FRAME_EOF_ERR = (1 << 18), + JPEG_LL_INTR_DE_FRAME_EOF_LACK = (1 << 19), + JPEG_LL_INTR_SOS_UNMATCH_ERR = (1 << 20), + JPEG_LL_INTR_MARKER_ERR_FST = (1 << 21), + JPEG_LL_INTR_MARKER_ERR_OTHER = (1 << 22), + JPEG_LL_INTR_UNDETECT = (1 << 23), + JPEG_LL_INTR_DECODE_TIMEOUT = (1 << 24), +} jpeg_ll_decoder_intr_t; + +#define JPEG_LL_DECODER_EVENT_INTR (JPEG_LL_INTR_CID_ERR | \ + JPEG_LL_INTR_C_DHT_DC_ID | \ + JPEG_LL_INTR_C_DHT_AC_ID | \ + JPEG_LL_INTR_C_DQT_ID | \ + JPEG_LL_INTR_RST_UXP_ERR | \ + JPEG_LL_INTR_RST_CHECK_NON_ERR | \ + JPEG_LL_INTR_RST_CHECK_POS_ERR | \ + JPEG_LL_INTR_OUT_EOF | \ + JPEG_LL_INTR_SCAN_CHECK_NONE | \ + JPEG_LL_INTR_SCAN_POS_ERR | \ + JPEG_LL_INTR_UXP_DET | \ + JPEG_LL_INTR_DE_FRAME_EOF_ERR | \ + JPEG_LL_INTR_DE_FRAME_EOF_LACK | \ + JPEG_LL_INTR_SOS_UNMATCH_ERR | \ + JPEG_LL_INTR_MARKER_ERR_FST | \ + JPEG_LL_INTR_MARKER_ERR_OTHER | \ + JPEG_LL_INTR_UNDETECT | \ + JPEG_LL_INTR_DECODE_TIMEOUT) + +typedef enum { + JPEG_LL_RLE_PARALLEL_ERR = (1 << 1), + JPEG_LL_BS_LAST_BLOCK_EOF = (1 << 12), + JPEG_LL_EN_FRAME_EOF_ERR = (1 << 16), + JPEG_LL_EN_FRAME_EOF_LACK = (1 << 16), +} jpeg_ll_encoder_intr_t; + +#define JPEG_LL_ENCODER_EVENT_INTR (JPEG_LL_RLE_PARALLEL_ERR | \ + JPEG_LL_EN_FRAME_EOF_ERR) + +#define JPEG_LL_POWERED_BY_PMU 1 + +typedef enum { + JPEG_LL_MEM_LP_MODE_DEEP_SLEEP, // memory will enter deep sleep during low power stage, keep memory data + JPEG_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory will enter light sleep during low power stage, keep memory data + JPEG_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage + JPEG_LL_MEM_LP_MODE_DISABLE, // disable the low power stage +} jpeg_ll_mem_lp_mode_t; + +/** + * @brief Enable the hardware clock for JPEG module + * + * @param enable True to enable; false to disable + */ +static inline void jpeg_ll_enable_bus_clock(bool enable) +{ + HP_SYS_CLKRST.jpeg_ctrl0.reg_jpeg_sys_clk_en = enable; +} + +/** + * @brief Reset the JPEG module + */ +static inline void jpeg_ll_reset_module_register(void) +{ + HP_SYS_CLKRST.jpeg_ctrl0.reg_jpeg_rst_en = 1; + HP_SYS_CLKRST.jpeg_ctrl0.reg_jpeg_rst_en = 0; +} + +/** + * @brief Power control the JPEG memory block by the outside PMU logic + * + * @param dev Peripheral instance address + */ +static inline void jpeg_ll_mem_powered_by_pmu(jpeg_dev_t *hw) +{ + (void)hw; + HP_SYSTEM.sys_jpeg_mem_lp_ctrl.sys_jpeg_mem_force_ctrl = 0; + HP_SYSTEM.sys_jpeg_mem_lp_ctrl.sys_jpeg_mem_lp_en = 0; +} + +/** + * @brief Set low power mode for JPEG memory block + * + * @param dev Peripheral instance address + * @param mode JPEG memory low power mode in low power stage + */ +static inline void jpeg_ll_mem_set_low_power_mode(jpeg_dev_t *hw, jpeg_ll_mem_lp_mode_t mode) +{ + (void)hw; + HP_SYSTEM.sys_jpeg_mem_lp_ctrl.sys_jpeg_mem_lp_mode = mode; +} + +/** + * @brief Write the numbers of 1~n codewords length sum of ac0 table and write the minimum codeword of code length + * for 1~16 of ac0 table + * + * @param hw Pointer to JPEG hardware + * @param huffman_bits_table Pointer to huffman table + * @param minimum_code_table Pointer to minimum huffman code table + */ +static inline void jpeg_ll_dht_ac0_write_codeword(jpeg_dev_t *hw, uint8_t *huffman_bits_table, uint32_t *minimum_code_table) +{ + uint32_t element_number = 0; + for (int idx = 0; idx < JPEG_HUFFMAN_BITS_LEN_TABLE_LEN; idx++) { + element_number += (uint32_t)huffman_bits_table[idx]; + hw->dht_totlen_ac0.dht_totlen_ac0 = element_number; + hw->dht_codemin_ac0.dht_codemin_ac0 = minimum_code_table[idx]; + } +} + +/** + * @brief Write the symbols corresponding to the decoded codeword for AC0 huffman table in FIFO mode + * + * @param hw Pointer to JPEG hardware. + * @param huffman_value_table Pointer to huffman value table. + */ +static inline void jpeg_ll_dht_ac0_write_value(jpeg_dev_t *hw, uint8_t *huffman_value_table) +{ + for (int idx = 0; idx < JPEG_HUFFMAN_AC_VALUE_TABLE_LEN; idx++) { + hw->dht_val_ac0.dht_val_ac0 = (uint32_t)huffman_value_table[idx]; + } +} + +/** + * @brief Write the numbers of 1~n codewords length sum of ac1 table and write the minimum codeword of code length + * for 1~16 of ac1 table + * + * @param hw Pointer to JPEG hardware + * @param huffman_bits_table Pointer to huffman table + * @param minimum_code_table Pointer to minimum huffman code table + */ +static inline void jpeg_ll_dht_ac1_write_codeword(jpeg_dev_t *hw, uint8_t *huffman_bits_table, uint32_t *minimum_code_table) +{ + uint32_t element_number = 0; + for (int idx = 0; idx < JPEG_HUFFMAN_BITS_LEN_TABLE_LEN; idx++) { + element_number += (uint32_t)huffman_bits_table[idx]; + hw->dht_totlen_ac1.dht_totlen_ac1 = element_number; + hw->dht_codemin_ac1.dht_codemin_ac1 = minimum_code_table[idx]; + } +} + +/** + * @brief Write the symbols corresponding to the decoded codeword for AC1 huffman table in FIFO mode + * + * @param hw Pointer to JPEG hardware. + * @param huffman_value_table Pointer to huffman value table. + */ +static inline void jpeg_ll_dht_ac1_write_value(jpeg_dev_t *hw, uint8_t *huffman_value_table) +{ + for (int idx = 0; idx < JPEG_HUFFMAN_AC_VALUE_TABLE_LEN; idx++) { + hw->dht_val_ac1.dht_val_ac1 = (uint32_t)huffman_value_table[idx]; + } +} + +/** + * @brief Write the numbers of 1~n codewords length sum of dc0 table and write the minimum codeword of code length + * for 1~16 of dc0 table + * + * @param hw Pointer to JPEG hardware + * @param huffman_bits_table Pointer to huffman table + * @param minimum_code_table Pointer to minimum huffman code table + */ +static inline void jpeg_ll_dht_dc0_write_codeword(jpeg_dev_t *hw, uint8_t *huffman_bits_table, uint32_t *minimum_code_table) +{ + uint32_t element_number = 0; + for (int idx = 0; idx < JPEG_HUFFMAN_BITS_LEN_TABLE_LEN; idx++) { + element_number += (uint32_t)huffman_bits_table[idx]; + hw->dht_totlen_dc0.dht_totlen_dc0 = element_number; + hw->dht_codemin_dc0.dht_codemin_dc0 = minimum_code_table[idx]; + } +} + +/** + * @brief Write the symbols corresponding to the decoded codeword for DC0 huffman table in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param huffman_value_table Pointer to huffman value table. + */ +static inline void jpeg_ll_dht_dc0_write_value(jpeg_dev_t *hw, uint8_t *huffman_value_table) +{ + for (int idx = 0; idx < JPEG_HUFFMAN_DC_VALUE_TABLE_LEN; idx++) { + hw->dht_val_dc0.dht_val_dc0 = (uint32_t)huffman_value_table[idx]; + } +} + +/** + * @brief Write the numbers of 1~n codewords length sum of dc1 table and write the minimum codeword of code length + * for 1~16 of dc1 table + * + * @param hw Pointer to JPEG hardware + * @param huffman_bits_table Pointer to huffman table + * @param minimum_code_table Pointer to minimum huffman code table + */ +static inline void jpeg_ll_dht_dc1_write_codeword(jpeg_dev_t *hw, uint8_t *huffman_bits_table, uint32_t *minimum_code_table) +{ + uint32_t element_number = 0; + for (int idx = 0; idx < JPEG_HUFFMAN_BITS_LEN_TABLE_LEN; idx++) { + element_number += (uint32_t)huffman_bits_table[idx]; + hw->dht_totlen_dc1.dht_totlen_dc1 = element_number; + hw->dht_codemin_dc1.dht_codemin_dc1 = minimum_code_table[idx]; + } +} + +/** + * @brief Write the symbols corresponding to the decoded codeword for DC1 huffman table in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param huffman_value_table Pointer to huffman value table. + */ +static inline void jpeg_ll_dht_dc1_write_value(jpeg_dev_t *hw, uint8_t *huffman_value_table) +{ + for (int idx = 0; idx < JPEG_HUFFMAN_DC_VALUE_TABLE_LEN; idx++) { + hw->dht_val_dc1.dht_val_dc1 = (uint32_t)huffman_value_table[idx]; + } +} + +/** + * @brief Configures the quantization coefficient table precision for the encoder + * + * @param hw Pointer to JPEG hardware + * @param qnr_presition precision of quantization coefficient table + */ +static inline void jpeg_ll_set_qnr_presition(jpeg_dev_t *hw, uint8_t qnr_presition) +{ + hw->config.qnr_precision = qnr_presition; +} + +/** + * @brief Configures it to write quantization coefficient for table0 in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param quantization_table Pointer to quantization table. + */ +static inline void jpeg_ll_write_quantization_coefficient_t0(jpeg_dev_t *hw, uint32_t *quantization_table) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->dqt_info, t0_dqt_info, 0); + for (int q = 0; q < JPEG_QUANTIZATION_TABLE_LEN; q++) { + hw->t0qnr.t0_qnr_val = quantization_table[q]; + } +} + +/** + * @brief Configures it to write quantization coefficient for table1 in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param quantization_table Pointer to quantization table. + */ +static inline void jpeg_ll_write_quantization_coefficient_t1(jpeg_dev_t *hw, uint32_t *quantization_table) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->dqt_info, t1_dqt_info, 1); + for (int q = 0; q < JPEG_QUANTIZATION_TABLE_LEN; q++) { + hw->t1qnr.t1_qnr_val = quantization_table[q]; + } +} + +/** + * @brief Configures it to write quantization coefficient for table2 in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param quantization_table Pointer to quantization table. + */ +static inline void jpeg_ll_write_quantization_coefficient_t2(jpeg_dev_t *hw, uint32_t *quantization_table) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->dqt_info, t2_dqt_info, 2); + for (int q = 0; q < JPEG_QUANTIZATION_TABLE_LEN; q++) { + hw->t2qnr.t2_qnr_val = quantization_table[q]; + } +} + +/** + * @brief Configures it to write quantization coefficient for table3 in FIFO mode + * + * @param hw Pointer to JPEG hardware + * @param quantization_table Pointer to quantization table. + */ +static inline void jpeg_ll_write_quantization_coefficient_t3(jpeg_dev_t *hw, uint32_t *quantization_table) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->dqt_info, t3_dqt_info, 3); + for (int q = 0; q < JPEG_QUANTIZATION_TABLE_LEN; q++) { + hw->t3qnr.t3_qnr_val = quantization_table[q]; + } +} + +/** + * @brief Configures image’s height + * + * @param hw Pointer to JPEG hardware + * @param height height of image. + */ +static inline void jpeg_ll_set_picture_height(jpeg_dev_t *hw, uint32_t height) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pic_size, va, height); +} + +/** + * @brief Configures image’s width + * + * @param hw Pointer to JPEG hardware + * @param height width of image. + */ +static inline void jpeg_ll_set_picture_width(jpeg_dev_t *hw, uint32_t width) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pic_size, ha, width); +} + +/** + * @brief Configure component0. + * + * @param hw Pointer to JPEG hardware + * @param identifier ID of component 0. + * @param horizontal_factor Configures the horizontal sampling factor of component 0. + * @param vertical_factor Configures the vertical sampling factor of component 0. + * @param qun_table_id Configures the selected quantization coefficient table ID for component 0. + */ +static inline void jpeg_ll_set_frame_info_component0(jpeg_dev_t *hw, uint8_t identifier, uint8_t horizontal_factor, uint8_t vertical_factor, uint8_t qun_table_id) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c0, c0_id, identifier); + hw->c0.c0_x_factor = horizontal_factor; + hw->c0.c0_y_factor = vertical_factor; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c0, c0_dqt_tbl_sel, qun_table_id); +} + +/** + * @brief Configure component1. + * + * @param hw Pointer to JPEG hardware + * @param identifier ID of component 1. + * @param horizontal_factor Configures the horizontal sampling factor of component 1. + * @param vertical_factor Configures the vertical sampling factor of component 1. + * @param qun_table_id Configures the selected quantization coefficient table ID for component 1. + */ +static inline void jpeg_ll_set_frame_info_component1(jpeg_dev_t *hw, uint8_t identifier, uint8_t horizontal_factor, uint8_t vertical_factor, uint8_t qun_table_id) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c1, c1_id, identifier); + hw->c1.c1_x_factor = horizontal_factor; + hw->c1.c1_y_factor = vertical_factor; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c1, c1_dqt_tbl_sel, qun_table_id); +} + +/** + * @brief Configure component2. + * + * @param hw Pointer to JPEG hardware + * @param identifier ID of component 2. + * @param horizontal_factor Configures the horizontal sampling factor of component 2. + * @param vertical_factor Configures the vertical sampling factor of component 2. + * @param qun_table_id Configures the selected quantization coefficient table ID for component 2. + */ +static inline void jpeg_ll_set_frame_info_component2(jpeg_dev_t *hw, uint8_t identifier, uint8_t horizontal_factor, uint8_t vertical_factor, uint8_t qun_table_id) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c2, c2_id, identifier); + hw->c2.c2_x_factor = horizontal_factor; + hw->c2.c2_y_factor = vertical_factor; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c2, c2_dqt_tbl_sel, qun_table_id); +} + +/** + * @brief Configure component3. + * + * @param hw Pointer to JPEG hardware + * @param identifier ID of component 3. + * @param horizontal_factor Configures the horizontal sampling factor of component 3. + * @param vertical_factor Configures the vertical sampling factor of component 3. + * @param qun_table_id Configures the selected quantization coefficient table ID for component 3. + */ +static inline void jpeg_ll_set_frame_info_component3(jpeg_dev_t *hw, uint8_t identifier, uint8_t horizontal_factor, uint8_t vertical_factor, uint8_t qun_table_id) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c3, c3_id, identifier); + hw->c3.c3_x_factor = horizontal_factor; + hw->c3.c3_y_factor = vertical_factor; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->c3, c3_dqt_tbl_sel, qun_table_id); +} + +/** + * @brief Get factor from component0 + * + * @param hw Pointer to JPEG hardware + * @param component_factor Pointer to component factor + */ +static inline void jpeg_ll_get_component0_factor(jpeg_dev_t *hw, jpeg_component_factor_t *component_factor) +{ + component_factor->horizontal = hw->c0.c0_x_factor; + component_factor->vertical = hw->c0.c0_y_factor; +} + +/** + * @brief Get factor from component1 + * + * @param hw Pointer to JPEG hardware + * @param component_factor Pointer to component factor + */ +static inline void jpeg_ll_get_component1_factor(jpeg_dev_t *hw, jpeg_component_factor_t *component_factor) +{ + component_factor->horizontal = hw->c1.c1_x_factor; + component_factor->vertical = hw->c1.c1_y_factor; +} + +/** + * @brief Configures whether or not to start compressing a new image + * + * @param hw Pointer to JPEG hardware + */ +static inline void jpeg_ll_process_start(jpeg_dev_t *hw) +{ + hw->config.jpeg_start = 1; +} + +/** + * @brief Configures whether or not pause the JPEG codec. + * + * @param hw Pointer to JPEG hardware + * @param en true: pause the jpeg codec, false: resume. + */ +static inline void jpeg_ll_codec_pause(jpeg_dev_t *hw, bool en) +{ + hw->config.pause_en = en; +} + +/** + * @brief Apply soft reset, this will reset the hardware fsm and fifo. + * + * @param hw Pointer to JPEG hardware. + */ +static inline void jpeg_ll_soft_rst(jpeg_dev_t *hw) +{ + hw->config.soft_rst = 1; + hw->config.soft_rst = 0; +} + +/** + * @brief Configures if the JPEG codec is working as an encoder or a decoder. + * + * @param hw Pointer to JPEG hardware. + * @param mode Refer to `jpeg_codec_mode_t` + */ +static inline void jpeg_ll_set_codec_mode(jpeg_dev_t *hw, jpeg_codec_mode_t mode) +{ + uint8_t mode_val = 0; + switch (mode) { + case JPEG_CODEC_ENCODER: + mode_val = 0; + break; + case JPEG_CODEC_DECODER: + mode_val = 1; + break; + default: + HAL_ASSERT(false); + break; + } + hw->config.mode = mode_val; +} + +/** + * @brief Configures whether or not to enable FIFO mode of configuring quantization coefficient tables. + * + * @param hw Pointer to JPEG hardware. + * @param mode 0: Use non-fifo mode. 1: Use fifo mode. + */ +static inline void jpeg_ll_set_access_qnr_ram_mode(jpeg_dev_t *hw, uint8_t mode) +{ + hw->config.qnr_fifo_en = mode; +} + +/** + * @brief Configures the number of color components in image when decoding + * + * @param hw Pointer to JPEG hardware. + * @param component_num Number of color components + */ +static inline void jpeg_ll_set_decode_component_num(jpeg_dev_t *hw, uint8_t component_num) +{ + // ESP32P4 only support to decode color component not larger than 4 + HAL_ASSERT(component_num <= 3); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->decode_conf, component_num, component_num); +} + +/** + * @brief Configures the format of the image to be compressed + * + * @param hw Pointer to JPEG hardware. + * @param mode_sel Select sample mode, refer to `jpeg_sample_mode_t`. + */ +static inline void jpeg_ll_sample_mode_select(jpeg_dev_t *hw, jpeg_sample_mode_t mode_sel) +{ + uint8_t sample_sel = 0; + switch (mode_sel) { + case JPEG_SAMPLE_MODE_YUV444: + sample_sel = 0; + break; + case JPEG_SAMPLE_MODE_YUV422: + sample_sel = 1; + break; + case JPEG_SAMPLE_MODE_YUV420: + sample_sel = 2; + break; + default: + HAL_ASSERT(false); + break; + } + hw->config.sample_sel = sample_sel; +} + +/** + * @brief Configure whether or not to reverse the original image's pixel order. + * + * @param hw Pointer to JPEG hardware. + * @param reverse_en 0: not revert; 1: revert. + */ +static inline void jpeg_ll_pixel_reverse(jpeg_dev_t *hw, bool reverse_en) +{ + hw->config.pixel_rev = reverse_en; +} + +/** + * @brief Configures whether or not to add EOI of “0xffd9” at the end of bitstream + * + * @param hw Pointer to JPEG hardware. + * @param tailer_en 1: Add `0xffd9` at the end of bitstream. + */ +static inline void jpeg_ll_add_tail(jpeg_dev_t *hw, bool tailer_en) +{ + hw->config.tailer_en = tailer_en; +} + +/** + * @brief Configures whether or not to add “00” after “ff” + * + * @param hw Pointer to JPEG hardware. + * @param ff_check_en 0: not add `00` after `ff`; 1: Add. + */ +static inline void jpeg_ll_enable_ff_check(jpeg_dev_t *hw, bool ff_check_en) +{ + hw->config.ff_check_en = ff_check_en; +} + +/** + * @brief Configures the luma quantization table ID for the encoder + * + * @param hw Pointer to JPEG hardware. + * @param lqnr_id ID of luma quantization table. + */ +static inline void jpeg_ll_luminance_qnr_table_id(jpeg_dev_t *hw, uint8_t lqnr_id) +{ + hw->config.lqnr_tbl_sel = lqnr_id; +} + +/** + * @brief Configures the chroma quantization table ID for the encoder. + * + * @param hw Pointer to JPEG hardware. + * @param cqnr_id ID of chroma quantization table. + */ +static inline void jpeg_ll_chrominance_qnr_table_id(jpeg_dev_t *hw, uint8_t cqnr_id) +{ + hw->config.cqnr_tbl_sel = cqnr_id; +} + +/** + * @brief Configures the restart interval in DRI segment when decoding + * + * @param hw Pointer to JPEG hardware. + * @param restart_interval value of restart interval. + */ +static inline void jpeg_ll_set_restart_interval(jpeg_dev_t *hw, uint16_t restart_interval) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->decode_conf, restart_interval, restart_interval); +} + +/** + * @brief Get JPEG interrupt status register address + * + * @param hw Pointer to JPEG hardware. + * @return address of interrupt status register. + */ +static inline volatile void *jpeg_ll_get_interrupt_status_reg(jpeg_dev_t *hw) +{ + return &hw->int_st; +} + +/** + * @brief Enable JPEG interrupt + * + * @param hw Pointer to JPEG hardware. + */ +static inline void jpeg_ll_enable_intr_mask(jpeg_dev_t *hw, uint32_t mask) +{ + hw->int_ena.val |= mask; +} + +/** + * @brief Clear JPEG interrupt + * + * @param hw Pointer to JPEG hardware. + */ +static inline void jpeg_ll_clear_intr_mask(jpeg_dev_t *hw, uint32_t mask) +{ + hw->int_clr.val = mask; +} + +/** + * @brief Disable JPEG interrupt + * + * @param hw Pointer to JPEG hardware. + */ +static inline void jpeg_ll_disable_intr_mask(jpeg_dev_t *hw, uint32_t mask) +{ + hw->int_ena.val &= (~mask); +} + +/** + * @brief Get JPEG interrupt status + * + * @param hw Pointer to JPEG hardware. + */ +static inline uint32_t jpeg_ll_get_intr_status(jpeg_dev_t *hw) +{ + return hw->int_st.val; +} + +/** + * @brief Configures the pixel format of the image to be compressed + * + * @param hw Pointer to JPEG hardware. + * @param pixel_format Pixel format, refer to `jpeg_enc_src_type_t`. + */ +static inline void jpeg_ll_config_picture_pixel_format(jpeg_dev_t *hw, jpeg_enc_src_type_t pixel_format) +{ + uint8_t cs = 0; + switch (pixel_format) { + case JPEG_ENC_SRC_RGB888: + cs = 0; + break; + case JPEG_ENC_SRC_YUV422: + cs = 1; + break; + case JPEG_ENC_SRC_RGB565: + cs = 2; + break; + case JPEG_ENC_SRC_GRAY: + cs = 3; + break; + case JPEG_ENC_SRC_YUV444: + cs = 4; + break; + case JPEG_ENC_SRC_YUV420: + cs = 5; + break; + default: + abort(); + } + hw->config.color_space = cs; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_jpeg/esp32s31/jpeg_periph.c b/components/esp_hal_jpeg/esp32s31/jpeg_periph.c new file mode 100644 index 0000000000..f1777abe44 --- /dev/null +++ b/components/esp_hal_jpeg/esp32s31/jpeg_periph.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/jpeg_periph.h" + +// JPEG_CONFIG_REG JPEG_INT_ENA_REG +#define JPEG_RETENTION_REGS_CNT 2 +#define JPEG_RETENTION_REGS_BASE (DR_REG_JPEG_BASE + 0x0) +static const uint32_t jpeg_regs_map[4] = {0x8001, 0x0, 0x0, 0x0}; +static const regdma_entries_config_t jpeg_regdma_entries[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_JPEG_LINK(0x00), + JPEG_RETENTION_REGS_BASE, JPEG_RETENTION_REGS_BASE, + JPEG_RETENTION_REGS_CNT, 0, 0, + jpeg_regs_map[0], jpeg_regs_map[1], + jpeg_regs_map[2], jpeg_regs_map[3]), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const jpeg_reg_ctx_link_t jpeg_regs_retention = { + .link_list = jpeg_regdma_entries, + .link_num = ARRAY_SIZE(jpeg_regdma_entries), + .module_id = SLEEP_RETENTION_MODULE_JPEG, +}; diff --git a/components/esp_hal_jpeg/jpeg_hal.c b/components/esp_hal_jpeg/jpeg_hal.c index b2705e1e7d..b2cba9883c 100644 --- a/components/esp_hal_jpeg/jpeg_hal.c +++ b/components/esp_hal_jpeg/jpeg_hal.c @@ -11,6 +11,10 @@ void jpeg_hal_init(jpeg_hal_context_t *hal) { hal->dev = JPEG_LL_GET_HW(); +#if JPEG_LL_POWERED_BY_PMU + jpeg_ll_mem_powered_by_pmu(hal->dev); + jpeg_ll_mem_set_low_power_mode(hal->dev, JPEG_LL_MEM_LP_MODE_SHUT_DOWN); +#endif } void jpeg_hal_deinit(jpeg_hal_context_t *hal) diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 348b966141..e764ce53b3 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -171,6 +171,10 @@ config SOC_REGI2C_SUPPORTED bool default y +config SOC_JPEG_CODEC_SUPPORTED + bool + default y + config SOC_USB_OTG_PERIPH_NUM int default 1 @@ -854,3 +858,11 @@ config SOC_MCPWM_SUPPORT_EVENT_COMPARATOR config SOC_MCPWM_CAPTURE_CLK_FROM_GROUP bool default y + +config SOC_JPEG_DECODE_SUPPORTED + bool + default y + +config SOC_JPEG_ENCODE_SUPPORTED + bool + default y diff --git a/components/soc/esp32s31/include/soc/retention_periph_defs.h b/components/soc/esp32s31/include/soc/retention_periph_defs.h index ff690a6d96..bf68254897 100644 --- a/components/soc/esp32s31/include/soc/retention_periph_defs.h +++ b/components/soc/esp32s31/include/soc/retention_periph_defs.h @@ -64,20 +64,21 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_PCNT0 = 39, SLEEP_RETENTION_MODULE_PCNT1 = 40, SLEEP_RETENTION_MODULE_SDM0 = 41, + SLEEP_RETENTION_MODULE_JPEG = 42, /* Modem module, which includes WiFi, BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_WIFI_MAC = 42, - SLEEP_RETENTION_MODULE_WIFI_BB = 43, - SLEEP_RETENTION_MODULE_BLE_MAC = 44, - SLEEP_RETENTION_MODULE_BT_BB = 45, - SLEEP_RETENTION_MODULE_802154_MAC = 46, - SLEEP_RETENTION_MODULE_CLOCK_MODEM = 47, - SLEEP_RETENTION_MODULE_MODEM_PHY = 48, + SLEEP_RETENTION_MODULE_WIFI_MAC = 43, + SLEEP_RETENTION_MODULE_WIFI_BB = 44, + SLEEP_RETENTION_MODULE_BLE_MAC = 45, + SLEEP_RETENTION_MODULE_BT_BB = 46, + SLEEP_RETENTION_MODULE_802154_MAC = 47, + SLEEP_RETENTION_MODULE_CLOCK_MODEM = 48, + SLEEP_RETENTION_MODULE_MODEM_PHY = 49, SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; -#define is_top_domain_module(m) ((m >= SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) && ((m <= SLEEP_RETENTION_MODULE_SDM0))) +#define is_top_domain_module(m) ((m >= SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) && ((m <= SLEEP_RETENTION_MODULE_JPEG))) #ifdef __cplusplus } diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 8cfeb48e98..b5fb7cc0fc 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -101,6 +101,7 @@ // #define SOC_SIMD_INSTRUCTION_SUPPORTED 1 // TODO: [ESP32S31] IDF-14661 #define SOC_CORDIC_SUPPORTED 1 #define SOC_REGI2C_SUPPORTED 1 +#define SOC_JPEG_CODEC_SUPPORTED 1 /*-------------------------- USB CAPS ----------------------------------------*/ #define SOC_USB_OTG_PERIPH_NUM (1U) @@ -399,3 +400,7 @@ #define SOC_MCPWM_SUPPORT_EVENT_COMPARATOR (1) ///< Support event comparator (based on ETM) #define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers // #define SOC_MCPWM_SUPPORT_SLEEP_RETENTION (1) ///< Support back up registers before sleep + +/*--------------------------- JPEG --------------------------------*/ +#define SOC_JPEG_DECODE_SUPPORTED (1) +#define SOC_JPEG_ENCODE_SUPPORTED (1) diff --git a/components/soc/esp32s31/register/soc/jpeg_struct.h b/components/soc/esp32s31/register/soc/jpeg_struct.h index f9417db854..d3630bd71e 100644 --- a/components/soc/esp32s31/register/soc/jpeg_struct.h +++ b/components/soc/esp32s31/register/soc/jpeg_struct.h @@ -1431,7 +1431,7 @@ typedef union { } jpeg_version_reg_t; -typedef struct { +typedef struct jpeg_dev_t { volatile jpeg_config_reg_t config; volatile jpeg_dqt_info_reg_t dqt_info; volatile jpeg_pic_size_reg_t pic_size; @@ -1481,6 +1481,7 @@ typedef struct { volatile jpeg_version_reg_t version; } jpeg_dev_t; +extern jpeg_dev_t JPEG; #ifndef __cplusplus _Static_assert(sizeof(jpeg_dev_t) == 0x100, "Invalid size of jpeg_dev_t structure"); diff --git a/docs/doxygen/Doxyfile_esp32s31 b/docs/doxygen/Doxyfile_esp32s31 index ea02c2ccc3..d86b78dfb4 100644 --- a/docs/doxygen/Doxyfile_esp32s31 +++ b/docs/doxygen/Doxyfile_esp32s31 @@ -1,2 +1,5 @@ INPUT += \ - $(PROJECT_PATH)/components/esp_hal_dma/esp32s31/include/hal/bitscrambler_peri_select.h + $(PROJECT_PATH)/components/esp_hal_dma/esp32s31/include/hal/bitscrambler_peri_select.h \ + $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_decode.h \ + $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_encode.h \ + $(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_types.h \ diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index a712d5d59e..1ec490056e 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -291,7 +291,7 @@ examples/peripherals/isp/multi_pipelines: examples/peripherals/jpeg/jpeg_decode: disable: - - if: SOC_JPEG_CODEC_SUPPORTED != 1 + - if: SOC_JPEG_CODEC_SUPPORTED != 1 or SOC_SDMMC_HOST_SUPPORTED != 1 depends_components: - esp_driver_dma - esp_hal_jpeg @@ -300,7 +300,7 @@ examples/peripherals/jpeg/jpeg_decode: examples/peripherals/jpeg/jpeg_encode: disable: - - if: SOC_JPEG_ENCODE_SUPPORTED != 1 + - if: SOC_JPEG_ENCODE_SUPPORTED != 1 or SOC_SDMMC_HOST_SUPPORTED != 1 depends_components: - esp_driver_dma - esp_hal_jpeg diff --git a/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c b/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c index e5f0243bf8..fff835472e 100644 --- a/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c +++ b/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -22,6 +22,12 @@ const static char raw_file_1080[] = "/sdcard/out.rgb"; const static char jpg_file_720[] = "/sdcard/esp720.jpg"; const static char raw_file_720[] = "/sdcard/out2.rgb"; +#if CONFIG_IDF_TARGET_ESP32S31 +#define TIMEOUT_MS 80 +#else +#define TIMEOUT_MS 40 +#endif + static esp_err_t sdcard_init(void) { esp_err_t ret = ESP_OK; @@ -97,7 +103,7 @@ void app_main(void) jpeg_decoder_handle_t jpgd_handle; jpeg_decode_engine_cfg_t decode_eng_cfg = { - .timeout_ms = 40, + .timeout_ms = TIMEOUT_MS, }; ESP_ERROR_CHECK(jpeg_new_decoder_engine(&decode_eng_cfg, &jpgd_handle));