// Copyright 2020-2021 Beken // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include "clock_driver.h" #include "gpio_driver.h" #include "jpeg_driver.h" #include "jpeg_hal.h" #include "power_driver.h" #include "sys_driver.h" #include typedef struct { jpeg_isr_t isr_handler; void *param; } jpeg_isr_handler_t; typedef struct { jpeg_hal_t hal; jpeg_isr_handler_t jpeg_isr_handler[JPEG_ISR_MAX]; } jpeg_driver_t; typedef struct { uint8_t set_enable : 1; // 0:1/enable:disable config jpeg_encode uint8_t auto_enable : 1; // enable/disable set encode size uint16_t up_size; uint16_t low_size; } jpeg_encode_size_t; #define JPEG_RETURN_ON_NOT_INIT() do {\ if (!s_jpeg_driver_is_init) {\ return BK_ERR_JPEG_NOT_INIT;\ }\ } while(0) static jpeg_driver_t s_jpeg = {0}; static bool s_jpeg_driver_is_init = false; static jpeg_encode_size_t jpeg_encode_size = { .set_enable = false, .auto_enable = false, .up_size = 40 * 1024, .low_size = 10 * 1024, }; static void jpeg_isr(void); static void jpeg_init_common(const jpeg_config_t *config) { // jpeg power enable //sys_drv_jpeg_power_en(1); bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN, PM_POWER_MODULE_STATE_ON); // jpeg clk enable sys_drv_set_jpeg_clk_en(1); // jpeg_sys_int enable sys_drv_int_enable(JPEGENC_INTERRUPT_CTRL_BIT); // jpeg_sys_int enable // bus clk always on sys_drv_set_jpeg_disckg(1); // init jpeg jpeg_hal_set_global_ctrl(&s_jpeg.hal); } static void jpeg_deinit_common(void) { // jpeg stop jpeg_hal_stop_common(&s_jpeg.hal, JPEG_MODE); #if (!CONFIG_SOC_BK7236XX) jpeg_hal_stop_common(&s_jpeg.hal, YUV_MODE); #endif // jpeg soft_reset jpeg_hal_soft_reset(&s_jpeg.hal); // jpeg int clear jpeg_hal_reset_config_to_default(&s_jpeg.hal); // jpeg clk diable sys_drv_set_jpeg_clk_en(0); // auxs clk disable sys_drv_set_cis_auxs_clk_en(0); // bus clk disable sys_drv_set_jpeg_disckg(0); // jpeg_sys_int disable sys_drv_int_disable(JPEGENC_INTERRUPT_CTRL_BIT); // jpeg power disable //sys_drv_jpeg_power_en(0); bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN, PM_POWER_MODULE_STATE_OFF); // unregister isr for (uint8_t i = 0; i < JPEG_ISR_MAX; i++) { bk_jpeg_enc_unregister_isr(i); } } bk_err_t bk_jpeg_enc_driver_init(void) { if (s_jpeg_driver_is_init) { return BK_OK; } os_memset(&s_jpeg, 0, sizeof(s_jpeg)); jpeg_hal_init(&s_jpeg.hal); bk_int_isr_register(INT_SRC_JPEG, jpeg_isr, NULL); s_jpeg_driver_is_init = true; return BK_OK; } bk_err_t bk_jpeg_enc_driver_deinit(void) { if (!s_jpeg_driver_is_init) { return BK_OK; } bk_int_isr_unregister(INT_SRC_JPEG); os_memset(&s_jpeg, 0, sizeof(s_jpeg)); s_jpeg_driver_is_init = false; return BK_OK; } bk_err_t bk_jpeg_enc_init(const jpeg_config_t *config) { BK_RETURN_ON_NULL(config); JPEG_RETURN_ON_NOT_INIT(); // set cpu frequent to 320M bk_pm_module_vote_cpu_freq(PM_DEV_ID_JPEG, PM_CPU_FRQ_320M); jpeg_init_common(config); jpeg_hal_switch_mode(&s_jpeg.hal, config); return BK_OK; } bk_err_t bk_jpeg_enc_deinit(void) { JPEG_RETURN_ON_NOT_INIT(); jpeg_deinit_common(); // set cpu frequent to default value bk_pm_module_vote_cpu_freq(PM_DEV_ID_JPEG, PM_CPU_FRQ_DEFAULT); return BK_OK; } bk_err_t bk_jpeg_enc_partial_display_init(const jpeg_partial_offset_config_t *offset_config) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_partial_display_offset_config(&s_jpeg.hal, offset_config); jpeg_hal_enable_partial_display(&s_jpeg.hal, 1); return BK_OK; } bk_err_t bk_jpeg_enc_partial_display_deinit(void) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_enable_partial_display(&s_jpeg.hal, 0); return BK_OK; } bk_err_t bk_jpeg_enc_mode_switch(jpeg_config_t *config) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_switch_mode(&s_jpeg.hal, config); return BK_OK; } bk_err_t bk_jpeg_enc_start(yuv_mode_t mode) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_start_common(&s_jpeg.hal, mode); return BK_OK; } bk_err_t bk_jpeg_enc_stop(yuv_mode_t mode) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_stop_common(&s_jpeg.hal, mode); return BK_OK; } bk_err_t bk_jpeg_set_em_base_addr(uint8_t *address) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_set_em_base_addr(&s_jpeg.hal, address); return BK_OK; } uint32_t bk_jpeg_get_em_base_addr(void) { return jpeg_hal_get_jpeg_share_mem_addr(); } bk_err_t bk_jpeg_enc_yuv_fmt_sel(yuv_format_t fmt) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_yuv_fmt_sel(&s_jpeg.hal, fmt); return BK_OK; } uint32_t bk_jpeg_enc_get_frame_size(void) { JPEG_RETURN_ON_NOT_INIT(); return jpeg_hal_get_frame_byte_number(&s_jpeg.hal); } bk_err_t bk_jpeg_enc_register_isr(jpeg_isr_type_t type_id, jpeg_isr_t isr, void *param) { JPEG_RETURN_ON_NOT_INIT(); uint32_t int_level = rtos_disable_int(); s_jpeg.jpeg_isr_handler[type_id].isr_handler = isr; s_jpeg.jpeg_isr_handler[type_id].param = param; switch (type_id) { case JPEG_EOY: jpeg_hal_enable_end_yuv_int(&s_jpeg.hal); break; case JPEG_HEAD_OUTPUT: jpeg_hal_enable_head_output_int(&s_jpeg.hal); break; case JPEG_SOF: jpeg_hal_enable_start_frame_int(&s_jpeg.hal); break; case JPEG_EOF: jpeg_hal_enable_end_frame_int(&s_jpeg.hal); break; case JPEG_VSYNC_NEGEDGE: jpeg_hal_enable_vsync_negedge_int(&s_jpeg.hal); break; case JPEG_LINE_CLEAR: jpeg_hal_enable_line_clear_int(&s_jpeg.hal); break; case JPEG_FRAME_ERR: jpeg_hal_enable_frame_error_int(&s_jpeg.hal); break; default: break; } rtos_enable_int(int_level); return BK_OK; } bk_err_t bk_jpeg_enc_unregister_isr(jpeg_isr_type_t type_id) { JPEG_RETURN_ON_NOT_INIT(); uint32_t int_level = rtos_disable_int(); s_jpeg.jpeg_isr_handler[type_id].isr_handler = NULL; s_jpeg.jpeg_isr_handler[type_id].param = NULL; switch (type_id) { case JPEG_EOY: jpeg_hal_disable_end_yuv_int(&s_jpeg.hal); break; case JPEG_HEAD_OUTPUT: jpeg_hal_disable_head_output_int(&s_jpeg.hal); break; case JPEG_SOF: jpeg_hal_disable_start_frame_int(&s_jpeg.hal); break; case JPEG_EOF: jpeg_hal_disable_end_frame_int(&s_jpeg.hal); break; case JPEG_VSYNC_NEGEDGE: jpeg_hal_disable_vsync_negedge_int(&s_jpeg.hal); break; case JPEG_LINE_CLEAR: jpeg_hal_disable_line_clear_int(&s_jpeg.hal); break; case JPEG_FRAME_ERR: jpeg_hal_disable_frame_error_int(&s_jpeg.hal); break; default: break; } rtos_enable_int(int_level); return BK_OK; } bk_err_t bk_jpeg_enc_get_fifo_addr(uint32_t *fifo_addr) { *fifo_addr = JPEG_R_RX_FIFO; return BK_OK; } bk_err_t bk_jpeg_enc_set_auxs(uint32_t cksel, uint32_t ckdiv) { gpio_dev_unmap(JPEG_GPIO_AUXS); gpio_dev_map(JPEG_GPIO_AUXS, GPIO_DEV_CLK_AUXS); sys_hal_set_auxs_cis_clk_sel(cksel); sys_hal_set_auxs_cis_clk_div(ckdiv); bk_pm_clock_ctrl(PM_CLK_ID_AUXS, CLK_PWR_CTRL_PWR_UP); return BK_OK; } bk_err_t bk_jpeg_enc_set_mclk_div(mclk_div_t div) { JPEG_RETURN_ON_NOT_INIT(); jpeg_hal_set_mclk_div(&s_jpeg.hal, div); return BK_OK; } bk_err_t bk_jpeg_enc_encode_config(uint8_t enable, uint16_t up_size, uint16_t low_size) { JPEG_RETURN_ON_NOT_INIT(); uint32_t int_level = rtos_disable_int(); if (enable && low_size > 0 && up_size > low_size) { jpeg_encode_size.up_size = up_size; jpeg_encode_size.low_size = low_size; } jpeg_encode_size.set_enable = true; jpeg_encode_size.auto_enable = enable; rtos_enable_int(int_level); return BK_OK; } bk_err_t bk_jpeg_enc_soft_reset(void) { JPEG_RETURN_ON_NOT_INIT(); uint32_t int_level = rtos_disable_int(); jpeg_hal_soft_reset(&s_jpeg.hal); rtos_enable_int(int_level); return BK_OK; } static void jpeg_isr(void) { jpeg_hal_t *hal = &s_jpeg.hal; uint32_t int_status = jpeg_hal_get_interrupt_status(hal); JPEG_LOGD("[jpeg_isr] int_status:%x\r\n", int_status); jpeg_hal_clear_interrupt_status(hal, int_status); if (jpeg_hal_is_frame_start_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_SOF].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_SOF].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_SOF].param); } } if (jpeg_hal_is_frame_end_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_EOF].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_EOF].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_EOF].param); } if (jpeg_encode_size.set_enable) { if (jpeg_encode_size.auto_enable) { jpeg_hal_enable_bitrate_ctrl(&s_jpeg.hal, 1); jpeg_hal_set_target_size(&s_jpeg.hal, jpeg_encode_size.up_size, jpeg_encode_size.low_size); } else { jpeg_hal_enable_bitrate_ctrl(&s_jpeg.hal, 0); } jpeg_encode_size.set_enable = false; } } if (jpeg_hal_is_yuv_end_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_EOY].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_EOY].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_EOY].param); } } if (jpeg_hal_is_head_output_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_HEAD_OUTPUT].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_HEAD_OUTPUT].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_HEAD_OUTPUT].param); } } if (jpeg_hal_is_sync_negedge_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_VSYNC_NEGEDGE].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_VSYNC_NEGEDGE].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_VSYNC_NEGEDGE].param); } } if (jpeg_hal_is_line_clear_int_triggered(hal, int_status)) { if (s_jpeg.jpeg_isr_handler[JPEG_LINE_CLEAR].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_LINE_CLEAR].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_LINE_CLEAR].param); } } if (jpeg_hal_is_frame_error_int_triggered(hal, int_status)) { JPEG_LOGD("jpeg decode error!\r\n"); if (s_jpeg.jpeg_isr_handler[JPEG_FRAME_ERR].isr_handler) { s_jpeg.jpeg_isr_handler[JPEG_FRAME_ERR].isr_handler(0, s_jpeg.jpeg_isr_handler[JPEG_FRAME_ERR].param); } } }