2148 lines
56 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
// 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 <driver/int.h>
#include <os/os.h>
#include <os/mem.h>
#include <os/str.h>
#include <driver/dma.h>
#include <driver/i2c.h>
#include <driver/jpeg_enc.h>
#include <driver/jpeg_enc_types.h>
#include <driver/media_types.h>
#include <driver/dvp_camera.h>
#include <driver/dvp_camera_types.h>
#include <driver/gpio_types.h>
#include <driver/gpio.h>
#include <driver/h264.h>
#include "bk_general_dma.h"
#include <driver/psram.h>
#include <driver/yuv_buf.h>
#include <driver/video_common_driver.h>
#include <driver/aon_rtc.h>
#include "bk_misc.h"
#include "gpio_driver.h"
#define TAG "dvp_drv"
#define LOGI(...) BK_LOGW(TAG, ##__VA_ARGS__)
#define LOGW(...) BK_LOGW(TAG, ##__VA_ARGS__)
#define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__)
#define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__)
#define H264_SPS_PPS_SIZE (41)
#define H264_SELF_DEFINE_SEI_SIZE (96)
static const uint8 crc8_table[256] =
{
0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
};
static uint8 hnd_crc8(
uint8 *pdata, /* pointer to array of data to process */
uint32 nbytes, /* number of input data bytes to process */
uint8 crc /* either CRC8_INIT_VALUE or previous return value */
)
{
/* hard code the crc loop instead of using CRC_INNER_LOOP macro
* to avoid the undefined and unnecessary (uint8 >> 8) operation.
*/
while (nbytes-- > 0)
{
crc = crc8_table[(crc ^ *pdata++) & 0xff];
}
return crc;
}
typedef struct
{
uint8_t eof : 1;
uint8_t error : 1;
uint8_t index : 1;
uint8_t cached : 1;
uint8_t psram_dma_busy : 1;
uint8_t sps_pps_flag : 1;
uint8_t i_frame : 1;
uint8_t regenerate_idr : 1;
uint8_t sequence;
#ifndef CONFIG_H264_GOP_START_IDR_FRAME
uint8_t sps_pps[64]; //for psram write through
#endif
#ifdef CONFIG_H264_ADD_SELF_DEFINE_SEI
uint8_t sei[H264_SELF_DEFINE_SEI_SIZE]; // save frame infomation
#endif
uint8_t offset;
uint8_t psram_dma;
uint8 * buffer;
uint32_t frame_id;
uint32_t psram_dma_left;
uint32_t dma_length;
beken_semaphore_t sem;
frame_buffer_t *frame;
} dvp_driver_t;
typedef struct
{
uint32_t yuv_em_addr;
uint32_t yuv_pingpong_length;
uint32_t yuv_data_offset;
uint8_t dma_collect_yuv;
}encode_yuv_config_t;
#define JPEG_CRC_SIZE (5)
#define FRAME_BUFFER_CACHE (1024 * 5)
#if !CONFIG_YUV_BUF
#define DVP_STRIP
#endif
//#define DVP_DIAG_DEBUG
#ifdef DVP_DIAG_DEBUG
#define DVP_DIAG_DEBUG_INIT() \
do { \
gpio_dev_unmap(GPIO_2); \
bk_gpio_disable_pull(GPIO_2); \
bk_gpio_enable_output(GPIO_2); \
bk_gpio_set_output_low(GPIO_2); \
\
gpio_dev_unmap(GPIO_3); \
bk_gpio_disable_pull(GPIO_3); \
bk_gpio_enable_output(GPIO_3); \
bk_gpio_set_output_low(GPIO_3); \
\
gpio_dev_unmap(GPIO_4); \
bk_gpio_disable_pull(GPIO_4); \
bk_gpio_enable_output(GPIO_4); \
bk_gpio_set_output_low(GPIO_4); \
\
gpio_dev_unmap(GPIO_5); \
bk_gpio_disable_pull(GPIO_5); \
bk_gpio_enable_output(GPIO_5); \
bk_gpio_set_output_low(GPIO_5); \
\
gpio_dev_unmap(GPIO_12); \
bk_gpio_disable_pull(GPIO_12); \
bk_gpio_enable_output(GPIO_12); \
bk_gpio_set_output_low(GPIO_12); \
\
gpio_dev_unmap(GPIO_13); \
bk_gpio_disable_pull(GPIO_13); \
bk_gpio_enable_output(GPIO_13); \
bk_gpio_set_output_low(GPIO_13); \
\
} while (0)
#define DVP_JPEG_VSYNC_ENTRY() bk_gpio_set_output_high(GPIO_2)
#define DVP_JPEG_VSYNC_OUT() bk_gpio_set_output_low(GPIO_2)
#define DVP_JPEG_EOF_ENTRY() bk_gpio_set_output_high(GPIO_3)
#define DVP_JPEG_EOF_OUT() bk_gpio_set_output_low(GPIO_3)
#define DVP_YUV_EOF_ENTRY() bk_gpio_set_output_high(GPIO_4)
#define DVP_YUV_EOF_OUT() bk_gpio_set_output_low(GPIO_4)
#define DVP_JPEG_START_ENTRY() bk_gpio_set_output_high(GPIO_5)
#define DVP_JPEG_START_OUT() bk_gpio_set_output_low(GPIO_5)
#define DVP_JPEG_HEAD_ENTRY() bk_gpio_set_output_high(GPIO_12)
#define DVP_JPEG_HEAD_OUT() bk_gpio_set_output_low(GPIO_12)
#define DVP_PPI_ERROR_ENTRY() DVP_YUV_EOF_ENTRY()
#define DVP_PPI_ERROR_OUT() DVP_YUV_EOF_OUT()
#define DVP_H264_EOF_ENTRY() DVP_JPEG_EOF_ENTRY()
#define DVP_H264_EOF_OUT() DVP_JPEG_EOF_OUT()
#define DVP_JPEG_SDMA_ENTRY() bk_gpio_set_output_high(GPIO_13)
#define DVP_JPEG_SDMA_OUT() bk_gpio_set_output_low(GPIO_13)
#define DVP_DEBUG_IO() \
do { \
bk_gpio_set_output_high(GPIO_6); \
bk_gpio_set_output_low(GPIO_6); \
} while (0)
#else
#define DVP_DIAG_DEBUG_INIT()
#define DVP_JPEG_EOF_ENTRY()
#define DVP_JPEG_EOF_OUT()
#define DVP_YUV_EOF_ENTRY()
#define DVP_YUV_EOF_OUT()
#define DVP_JPEG_START_ENTRY()
#define DVP_JPEG_START_OUT()
#define DVP_JPEG_HEAD_ENTRY()
#define DVP_JPEG_HEAD_OUT()
#define DVP_PPI_ERROR_ENTRY()
#define DVP_PPI_ERROR_OUT()
#define DVP_H264_EOF_ENTRY()
#define DVP_H264_EOF_OUT()
#define DVP_JPEG_SDMA_ENTRY()
#define DVP_JPEG_SDMA_OUT()
#define DVP_JPEG_VSYNC_ENTRY()
#define DVP_JPEG_VSYNC_OUT()
#endif
extern media_debug_t *media_debug;
static dvp_camera_config_t *dvp_camera_config = NULL;
static const dvp_sensor_config_t *current_sensor = NULL;
static dvp_driver_t * dvp_camera_drv = NULL;
static media_state_t dvp_state = MASTER_TURN_OFF;
static uint8_t *dvp_camera_encode = NULL;
frame_buffer_t *curr_encode_frame = NULL;
frame_buffer_t *curr_yuv_frame = NULL;
jpeg_config_t jpeg_config = {0};
static uint8_t dvp_camera_dma_channel = DMA_ID_MAX;
static encode_yuv_config_t *encode_yuv_config = NULL;
bk_err_t dvp_memcpy_by_chnl(void *out, const void *in, uint32_t len, dma_id_t cpy_chnls);
static const dvp_sensor_config_t **devices_list = NULL;
static uint16_t devices_size = 0;
const dvp_sensor_config_t **get_sensor_config_devices_list(void)
{
return devices_list;
}
int get_sensor_config_devices_num(void)
{
return devices_size;
}
void bk_dvp_camera_set_devices_list(const dvp_sensor_config_t **list, uint16_t size)
{
devices_list = list;
devices_size = size;
}
const dvp_sensor_config_t *get_sensor_config_interface_by_id(sensor_id_t id)
{
uint32_t i;
for (i = 0; i < devices_size; i++)
{
if (devices_list[i]->id == id)
{
return devices_list[i];
}
}
return NULL;
}
const dvp_sensor_config_t *bk_dvp_get_sensor_auto_detect(void)
{
uint32_t i;
uint8_t count = 3;
do {
for (i = 0; i < devices_size; i++)
{
if (devices_list[i]->detect() == true)
{
return devices_list[i];
}
}
count--;
rtos_delay_milliseconds(5);
} while (count > 0);
return NULL;
}
static uint32_t dvp_camera_get_milliseconds(void)
{
uint32_t time = 0;
#if CONFIG_ARCH_RISCV
extern u64 riscv_get_mtimer(void);
time = (riscv_get_mtimer() / 26000) & 0xFFFFFFFF;
#elif CONFIG_ARCH_CM33
#if CONFIG_AON_RTC
time = (bk_aon_rtc_get_us() / 1000) & 0xFFFFFFFF;
#endif
#endif
return time;
}
#ifdef DVP_STRIP
static uint32_t dvp_frame_strip(uint8_t *src, uint32_t size)
{
uint32_t i = 0;
uint32_t first_zero = 0;
uint32_t tail = 0, tail_old = 0;
uint32_t length = 0;
uint8_t sram_tmp[16] = {0};
if ((size >> 3) & 0x1)
{
length = size & 0xFFFFFFF0;
tail_old = tail = size & 0x0F;
}
else
{
length = (size & 0xFFFFFFF8) - 0x08;
tail_old = tail = (size & 0x07) + 0x08;
}
for (i = 0; i < tail; i++)
{
sram_tmp[i] = src[length + i];
}
tail --;
if (sram_tmp[tail] != 0xD9
&& sram_tmp[tail - 1] != 0xFF)
{
LOGE("strip tail error %u \n", size);
return 0;
}
else
{
tail -= 2;
}
for (i = tail; i > 0; i--)
{
if (sram_tmp[i] == 0xFF)
{
tail--;
}
else if(sram_tmp[i] == 0x00)
{
if (first_zero == 0)
{
if (sram_tmp[i-1] == 0xFF)
{
tail --;
first_zero ++;
}
else if ((sram_tmp[i-1] & 0x01) && (sram_tmp[i-1] & 0x0F) != 0X0D)
{
tail--;
}
else
{
tail++;
break;
}
}
else
{
tail++;
break;
}
}
else
{
tail++;
break;
}
}
sram_tmp[tail++] = 0xFF;
sram_tmp[tail++] = 0xD9;
if (tail_old > tail)
{
os_memset(sram_tmp + tail, 0, tail_old - tail);
#if (CONFIG_PSRAM)
bk_psram_word_memcpy(src + length, sram_tmp, 16);
#else
for (i = 0; i < 16; i++)
{
src[length + i] = sram_tmp[i];
}
#endif
}
return length + tail;
}
#endif
static bk_err_t dvp_camera_init_device(const dvp_sensor_config_t *sensor)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
int ret = 0;
if (dvp_camera_config->device->info.resolution.width != (sensor->def_ppi >> 16) ||
dvp_camera_config->device->info.resolution.height != (sensor->def_ppi & 0xFFFF))
{
if (!(pixel_ppi_to_cap((dvp_camera_config->device->info.resolution.width << 16)
| dvp_camera_config->device->info.resolution.height) & (sensor->ppi_cap)))
{
dvp_camera_config->device->info.resolution.width = sensor->def_ppi >> 16;
dvp_camera_config->device->info.resolution.height = sensor->def_ppi & 0xFFFF;
}
}
return ret;
}
static void dvp_memcpy_finish_callback(dma_id_t id)
{
if(dvp_state != MASTER_TURN_ON)
{
return;
}
dvp_camera_drv->psram_dma_busy = false;
dvp_camera_drv->index = !dvp_camera_drv->index;
if (dvp_camera_drv->eof == true)
{
frame_buffer_t *frame = dvp_camera_drv->frame;
if (dvp_camera_drv->psram_dma_left != 0)
{
dvp_memcpy_by_chnl(frame->frame + frame->length,
dvp_camera_drv->index ? (dvp_camera_drv->buffer + FRAME_BUFFER_CACHE) : dvp_camera_drv->buffer,
dvp_camera_drv->psram_dma_left, dvp_camera_drv->psram_dma);
frame->length += dvp_camera_drv->psram_dma_left;
frame->sequence = dvp_camera_drv->frame_id++;
dvp_camera_drv->psram_dma_left = 0;
}
else
{
frame->length -= JPEG_CRC_SIZE;
#ifdef DVP_STRIP
frame->length = dvp_frame_strip(frame->frame, frame->length);
if (frame->length == 0)
{
dvp_camera_drv->index = 0;
dvp_camera_drv->eof = false;
if (dvp_state == MASTER_TURN_ON)
{
bk_dma_start(dvp_camera_dma_channel);
}
else
{
dvp_camera_config->fb_free(curr_encode_frame);
curr_encode_frame = NULL;
}
return;
}
#endif
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
media_debug->h264_length = frame->length;
media_debug->h264_kbps += frame->length;
}
else
{
media_debug->jpeg_length = frame->length;
media_debug->jpeg_kbps += frame->length;
}
dvp_camera_config->fb_complete(frame);
dvp_camera_drv->index = 0;
dvp_camera_drv->frame = NULL;
dvp_camera_drv->eof = false;
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_H264, CONFIG_H264_FRAME_SIZE);
}
else // JPEG
{
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_JPEG, CONFIG_JPEG_FRAME_SIZE);
}
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("alloc frame error\n");
return;
}
curr_encode_frame->width = dvp_camera_config->device->info.resolution.width;
curr_encode_frame->height = dvp_camera_config->device->info.resolution.height;
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
curr_encode_frame->type = dvp_camera_config->device->type;
bk_dma_start(dvp_camera_dma_channel);
}
}
}
bk_err_t dvp_memcpy_by_chnl(void *out, const void *in, uint32_t len, dma_id_t cpy_chnls)
{
dma_config_t dma_config = {0};
/* fix for psram 4bytes alignment */
if (len % 4)
{
len = (len / 4 + 1) * 4;
}
os_memset(&dma_config, 0, sizeof(dma_config_t));
dma_config.mode = DMA_WORK_MODE_SINGLE;
dma_config.chan_prio = 1;
dma_config.src.dev = DMA_DEV_DTCM;
dma_config.src.width = DMA_DATA_WIDTH_32BITS;
dma_config.src.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.src.start_addr = (uint32_t)in;
dma_config.src.end_addr = (uint32_t)(in + len);
dma_config.dst.dev = DMA_DEV_DTCM;
dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.dst.start_addr = (uint32_t)out;
dma_config.dst.end_addr = (uint32_t)(out + len);
dvp_camera_drv->psram_dma_busy = true;
BK_LOG_ON_ERR(bk_dma_init(cpy_chnls, &dma_config));
BK_LOG_ON_ERR(bk_dma_set_transfer_len(cpy_chnls, len));
#if (CONFIG_SPE)
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(cpy_chnls, DMA_ATTR_SEC));
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(cpy_chnls, DMA_ATTR_SEC));
#endif
BK_LOG_ON_ERR(bk_dma_register_isr(cpy_chnls, NULL, dvp_memcpy_finish_callback));
BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(cpy_chnls));
BK_LOG_ON_ERR(bk_dma_start(cpy_chnls));
//BK_WHILE (bk_dma_get_enable_status(cpy_chnl));
return BK_OK;
}
static void dvp_camera_dma_finish_callback(dma_id_t id)
{
DVP_JPEG_SDMA_ENTRY();
if (dvp_camera_drv->cached == true)
{
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("%s curr_encode_frame NULL\n");
return;
}
dvp_memcpy_by_chnl(curr_encode_frame->frame + curr_encode_frame->length,
dvp_camera_drv->index ? (dvp_camera_drv->buffer + FRAME_BUFFER_CACHE) : dvp_camera_drv->buffer,
FRAME_BUFFER_CACHE, dvp_camera_drv->psram_dma);
curr_encode_frame->length += FRAME_BUFFER_CACHE;
}
else
{
curr_encode_frame->length += FRAME_BUFFER_CACHE;
}
dvp_camera_drv->dma_length += FRAME_BUFFER_CACHE;
DVP_JPEG_SDMA_OUT();
}
static bk_err_t dvp_camera_dma_config(void)
{
bk_err_t ret = BK_OK;
dma_config_t dma_config = {0};
uint32_t encode_fifo_addr;
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_H264, CONFIG_H264_FRAME_SIZE);
}
else // MJPEG || MIX
{
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_JPEG, CONFIG_JPEG_FRAME_SIZE);
}
if (curr_encode_frame == NULL)
{
LOGE("malloc frame fail \r\n");
ret = BK_FAIL;
return ret;
}
curr_encode_frame->type = dvp_camera_config->device->type;
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
curr_encode_frame->width = dvp_camera_config->device->info.resolution.width;
curr_encode_frame->height = dvp_camera_config->device->info.resolution.height;
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
#if (CONFIG_H264)
bk_h264_get_fifo_addr(&encode_fifo_addr);
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
//dvp_camera_dma_channel = bk_dma_alloc(DMA_DEV_H264);
dvp_camera_dma_channel = bk_fixed_dma_alloc(DMA_DEV_H264, DMA_ID_8);
#endif
}
else // JPEG || MIX
{
bk_jpeg_enc_get_fifo_addr(&encode_fifo_addr);
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
#if (CONFIG_SOC_BK7236XX)
dvp_camera_dma_channel = bk_fixed_dma_alloc(DMA_DEV_JPEG, DMA_ID_8);
#else
dvp_camera_dma_channel = bk_dma_alloc(DMA_DEV_JPEG);
#endif
}
if ((dvp_camera_dma_channel < DMA_ID_0) || (dvp_camera_dma_channel >= DMA_ID_MAX))
{
LOGE("malloc dma fail \r\n");
ret = BK_FAIL;
return ret;
}
LOGI("dvp_dma id:%d \r\n", dvp_camera_dma_channel);
dma_config.mode = DMA_WORK_MODE_REPEAT;
dma_config.chan_prio = 0;
dma_config.src.width = DMA_DATA_WIDTH_32BITS;
dma_config.src.start_addr = encode_fifo_addr;
dma_config.dst.dev = DMA_DEV_DTCM;
dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.dst.addr_loop_en = DMA_ADDR_LOOP_ENABLE;
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
dma_config.src.dev = DMA_DEV_H264;
}
else // JPEG || MIX
{
dma_config.src.dev = DMA_DEV_JPEG;
}
// in bk7256 jpeg data cannot dma to psram direct, need copy to sram first, then copy to psram
if (dvp_camera_drv->cached)
{
dma_config.dst.start_addr = (uint32_t)dvp_camera_drv->buffer;
dma_config.dst.end_addr = (uint32_t)(dvp_camera_drv->buffer + FRAME_BUFFER_CACHE * 2);
BK_LOG_ON_ERR(bk_dma_init(dvp_camera_dma_channel, &dma_config));
BK_LOG_ON_ERR(bk_dma_set_transfer_len(dvp_camera_dma_channel, FRAME_BUFFER_CACHE));
}
else
{
dma_config.dst.start_addr = (uint32_t)curr_encode_frame->frame;
dma_config.dst.end_addr = (uint32_t)(curr_encode_frame->frame + curr_encode_frame->size);
BK_LOG_ON_ERR(bk_dma_init(dvp_camera_dma_channel, &dma_config));
BK_LOG_ON_ERR(bk_dma_set_transfer_len(dvp_camera_dma_channel, FRAME_BUFFER_CACHE));
}
LOGI("%s, %d, start-stop:%p-%p\r\n", __func__, dvp_camera_drv->cached, dma_config.dst.start_addr, dma_config.dst.end_addr);
BK_LOG_ON_ERR(bk_dma_register_isr(dvp_camera_dma_channel, NULL, dvp_camera_dma_finish_callback));
BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(dvp_camera_dma_channel));
#if (CONFIG_SPE)
BK_LOG_ON_ERR(bk_dma_set_src_burst_len(dvp_camera_dma_channel, BURST_LEN_SINGLE));
BK_LOG_ON_ERR(bk_dma_set_dest_burst_len(dvp_camera_dma_channel, BURST_LEN_INC16));
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(dvp_camera_dma_channel, DMA_ATTR_SEC));
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(dvp_camera_dma_channel, DMA_ATTR_SEC));
#endif
BK_LOG_ON_ERR(bk_dma_start(dvp_camera_dma_channel));
return ret;
}
#if CONFIG_YUV_BUF
static bk_err_t encode_yuv_dma_cpy(void *out, const void *in, uint32_t len, dma_id_t cpy_chnl)
{
dma_config_t dma_config = {0};
os_memset(&dma_config, 0, sizeof(dma_config_t));
dma_config.mode = DMA_WORK_MODE_SINGLE;
dma_config.chan_prio = 1;
dma_config.src.dev = DMA_DEV_DTCM;
dma_config.src.width = DMA_DATA_WIDTH_32BITS;
dma_config.src.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.src.start_addr = (uint32_t)in;
dma_config.src.end_addr = (uint32_t)(in + len);
dma_config.dst.dev = DMA_DEV_DTCM;
dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.dst.start_addr = (uint32_t)out;
dma_config.dst.end_addr = (uint32_t)(out + len);
BK_LOG_ON_ERR(bk_dma_init(cpy_chnl, &dma_config));
BK_LOG_ON_ERR(bk_dma_set_transfer_len(cpy_chnl, len));
#if (CONFIG_SPE && CONFIG_GDMA_HW_V2PX)
BK_LOG_ON_ERR(bk_dma_set_src_burst_len(cpy_chnl, 3));
BK_LOG_ON_ERR(bk_dma_set_dest_burst_len(cpy_chnl, 3));
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(cpy_chnl, DMA_ATTR_SEC));
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(cpy_chnl, DMA_ATTR_SEC));
#endif
return BK_OK;
}
#endif
static bk_err_t dvp_camera_init(yuv_mode_t mode)
{
if (bk_dvp_camera_enumerate() == NULL)
{
return BK_FAIL;
}
/* set current used camera config */
BK_RETURN_ON_ERR(dvp_camera_init_device(current_sensor));
return BK_OK;
}
static bk_err_t dvp_camera_deinit(void)
{
// step 1: deinit dvp gpio, data cannot transfer
bk_video_gpio_deinit(DVP_GPIO_ALL);
// step 2: deinit i2c
bk_i2c_deinit(CONFIG_DVP_CAMERA_I2C_ID);
// step 3: deinit hardware
if (current_sensor)
{
#if (CONFIG_YUV_BUF)
bk_yuv_buf_deinit();
bk_h264_encode_disable();
bk_h264_deinit();
#endif
bk_jpeg_enc_deinit();
}
bk_video_dvp_mclk_disable();
// step 4: power off
bk_video_power_off(CONFIG_CAMERA_CTRL_POWER_GPIO_ID, 1);
// step 5: stop/deinit/free fifo to sram(psram) dma
if (dvp_camera_config->device->mode != YUV_MODE && dvp_camera_config->device->mode != GRAY_MODE)
{
bk_dma_stop(dvp_camera_dma_channel);
bk_dma_deinit(dvp_camera_dma_channel);
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
bk_dma_free(DMA_DEV_H264, dvp_camera_dma_channel);
else
bk_dma_free(DMA_DEV_JPEG, dvp_camera_dma_channel);
dvp_camera_dma_channel = DMA_ID_MAX;
#if CONFIG_YUV_BUF
if (dvp_camera_config->device->mode == JPEG_YUV_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
if (encode_yuv_config)
{
bk_dma_stop(encode_yuv_config->dma_collect_yuv);
bk_dma_deinit(encode_yuv_config->dma_collect_yuv);
bk_dma_free(DMA_DEV_DTCM, encode_yuv_config->dma_collect_yuv);
}
os_free(encode_yuv_config);
encode_yuv_config = NULL;
}
#endif
}
// step 6: stop/deinit/free free sram->psram dma, and free dvp_camera_drv
if (dvp_camera_drv)
{
if (dvp_camera_drv->cached)
{
bk_dma_stop(dvp_camera_drv->psram_dma);
bk_dma_deinit(dvp_camera_drv->psram_dma);
bk_dma_free(DMA_DEV_DTCM, dvp_camera_drv->psram_dma);
if (dvp_camera_drv->buffer)
{
os_free(dvp_camera_drv->buffer);
dvp_camera_drv->buffer = NULL;
}
}
if (dvp_camera_drv->sem)
{
rtos_deinit_semaphore(&dvp_camera_drv->sem);
dvp_camera_drv->sem = NULL;
}
os_free(dvp_camera_drv);
dvp_camera_drv = NULL;
}
// step 7: free frame_buffer
if (curr_encode_frame)
{
dvp_camera_config->fb_free(curr_encode_frame);
curr_encode_frame = NULL;
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
dvp_camera_config->fb_clear(FB_INDEX_H264);
}
else
{
dvp_camera_config->fb_clear(FB_INDEX_JPEG);
}
}
if (curr_yuv_frame)
{
dvp_camera_config->fb_free(curr_yuv_frame);
}
// step 8: free dvp_camera_config
if (dvp_camera_config)
{
if (dvp_camera_config->device)
{
os_free(dvp_camera_config->device);
dvp_camera_config->device = NULL;
}
os_free(dvp_camera_config);
dvp_camera_config = NULL;
}
// step 9: free enode buffer
#if (!CONFIG_ENCODE_BUF_NOT_FREE)
if (dvp_camera_encode)
{
os_free(dvp_camera_encode);
dvp_camera_encode = NULL;
}
#endif
LOGI("%s complete!\r\n", __func__);
dvp_state = MASTER_TURN_OFF;
return BK_OK;
}
#if (CONFIG_YUV_BUF)
static void dvp_camera_reset_hardware_modules_handler(void)
{
if (dvp_camera_config->device->mode == JPEG_MODE || dvp_camera_config->device->mode == JPEG_YUV_MODE)
{
bk_jpeg_enc_soft_reset();
}
if (dvp_camera_config->device->mode == H264_MODE || dvp_camera_config->device->mode == H264_YUV_MODE)
{
bk_h264_config_reset();
bk_video_encode_start(H264_MODE);
}
bk_yuv_buf_soft_reset();
if (encode_yuv_config)
{
encode_yuv_config->yuv_data_offset = 0;
}
if (dvp_camera_dma_channel < DMA_ID_MAX)
{
bk_dma_stop(dvp_camera_dma_channel);
if (curr_encode_frame)
{
curr_encode_frame->length = 0;
}
bk_dma_start(dvp_camera_dma_channel);
}
}
static void dvp_camera_sensor_ppi_err_handler(yuv_buf_unit_t id, void *param)
{
DVP_PPI_ERROR_ENTRY();
if (!dvp_camera_drv->error)
{
dvp_camera_drv->error = true;
}
DVP_PPI_ERROR_OUT();
}
static void yuv_sm0_line_done(void *param)
{
if ((encode_yuv_config->yuv_data_offset + encode_yuv_config->yuv_pingpong_length) > curr_yuv_frame->length)
{
encode_yuv_config->yuv_data_offset = 0;
}
BK_WHILE(bk_dma_get_enable_status(encode_yuv_config->dma_collect_yuv));
bk_dma_stop(encode_yuv_config->dma_collect_yuv);
bk_dma_set_src_start_addr(encode_yuv_config->dma_collect_yuv,
(uint32_t)encode_yuv_config->yuv_em_addr);
bk_dma_set_dest_start_addr(encode_yuv_config->dma_collect_yuv,
(uint32_t)(curr_yuv_frame->frame + encode_yuv_config->yuv_data_offset));
bk_dma_start(encode_yuv_config->dma_collect_yuv);
encode_yuv_config->yuv_data_offset += encode_yuv_config->yuv_pingpong_length;
}
static void yuv_sm1_line_done(void *param)
{
if ((encode_yuv_config->yuv_data_offset + encode_yuv_config->yuv_pingpong_length) > curr_yuv_frame->length)
{
encode_yuv_config->yuv_data_offset = 0;
}
BK_WHILE(bk_dma_get_enable_status(encode_yuv_config->dma_collect_yuv));
bk_dma_stop(encode_yuv_config->dma_collect_yuv);
bk_dma_set_src_start_addr(encode_yuv_config->dma_collect_yuv,
(uint32_t)encode_yuv_config->yuv_em_addr + encode_yuv_config->yuv_pingpong_length);
bk_dma_set_dest_start_addr(encode_yuv_config->dma_collect_yuv,
(uint32_t)(curr_yuv_frame->frame + encode_yuv_config->yuv_data_offset));
bk_dma_start(encode_yuv_config->dma_collect_yuv);
encode_yuv_config->yuv_data_offset += encode_yuv_config->yuv_pingpong_length;
}
#endif // bk7236xx
static void dvp_camera_vsync_negedge_handler(jpeg_unit_t id, void *param)
{
DVP_JPEG_VSYNC_ENTRY();
if (dvp_state == MASTER_TURNING_OFF)
{
bk_video_encode_stop(YUV_MODE);
bk_video_encode_stop(JPEG_MODE);
bk_video_encode_stop(H264_MODE);
if (dvp_camera_drv->sem != NULL)
{
rtos_set_semaphore(&dvp_camera_drv->sem);
}
DVP_JPEG_VSYNC_OUT();
return;
}
#if (!CONFIG_YUV_BUF)
else
{
if (dvp_camera_config->device->mode == YUV_MODE)
{
bk_video_encode_stop(YUV_MODE);
bk_video_encode_start(YUV_MODE);
}
}
#else
if (dvp_camera_drv->error)
{
dvp_camera_drv->error = false;
dvp_camera_drv->sequence = 0;
dvp_camera_reset_hardware_modules_handler();
LOGI("reset OK \r\n");
DVP_JPEG_VSYNC_OUT();
return;
}
#endif
DVP_JPEG_VSYNC_OUT();
}
static void dvp_camera_yuv_eof_handler(jpeg_unit_t id, void *param)
{
frame_buffer_t *frame = NULL;
DVP_YUV_EOF_ENTRY();
if (dvp_state != MASTER_TURN_ON)
{
DVP_YUV_EOF_OUT();
return;
}
media_debug->isr_jpeg++;
curr_yuv_frame->sequence = dvp_camera_drv->frame_id++;
if (dvp_camera_config->device->mode == GRAY_MODE)
curr_yuv_frame->length = dvp_camera_config->device->info.resolution.width * dvp_camera_config->device->info.resolution.height;
else // YUV_MODE, and other carry yuv mode,jpeg_yuv/h264_yuv
curr_yuv_frame->length = dvp_camera_config->device->info.resolution.width * dvp_camera_config->device->info.resolution.height * 2;
dvp_camera_config->fb_complete(curr_yuv_frame);
curr_yuv_frame = NULL;
#if !CONFIG_YUV_BUF
if (dvp_camera_config->device->mode == JPEG_YUV_MODE)
{
bk_video_encode_stop(YUV_MODE);
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_JPEG, CONFIG_JPEG_FRAME_SIZE);
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("alloc frame error\n");
return;
}
curr_encode_frame->width = dvp_camera_config->device->info.resolution.width;
curr_encode_frame->height = dvp_camera_config->device->info.resolution.height;
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
curr_encode_frame->type = dvp_camera_config->device->type;
bk_dma_start(dvp_camera_dma_channel);
jpeg_config.mode = JPEG_MODE;
bk_jpeg_enc_mode_switch(&jpeg_config);
bk_jpeg_enc_start(JPEG_MODE);
}
else
#endif
{
uint32_t size = dvp_camera_config->device->info.resolution.width * dvp_camera_config->device->info.resolution.height * 2;
frame = dvp_camera_config->fb_malloc(FB_INDEX_DISPLAY, size);
if (frame != NULL)
{
curr_yuv_frame = frame;
curr_yuv_frame->width = dvp_camera_config->device->info.resolution.width;
curr_yuv_frame->height = dvp_camera_config->device->info.resolution.height;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->type = dvp_camera_config->device->type;
bk_jpeg_set_em_base_addr(curr_yuv_frame->frame);
#if (CONFIG_YUV_BUF)
bk_yuv_buf_set_em_base_addr((uint32_t)curr_yuv_frame->frame);
#endif
}
else
{
LOGE("%s malloc frame failed\n", __func__);
}
}
DVP_YUV_EOF_OUT();
}
static void dvp_camera_jpeg_eof_handler(jpeg_unit_t id, void *param)
{
DVP_JPEG_EOF_ENTRY();
uint32_t real_length = 0, recv_length = 0;
if (dvp_state != MASTER_TURN_ON)
{
DVP_JPEG_EOF_OUT();
return;
}
if (dvp_camera_drv->error)
{
curr_encode_frame->length = 0;
bk_dma_stop(dvp_camera_dma_channel);
dvp_camera_drv->dma_length = 0;
bk_dma_start(dvp_camera_dma_channel);
DVP_JPEG_EOF_OUT();
return;
}
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("curr_encode_frame NULL error\n");
goto error;
}
media_debug->isr_jpeg++;
bk_dma_flush_src_buffer(dvp_camera_dma_channel);
real_length = bk_jpeg_enc_get_frame_size();
recv_length = FRAME_BUFFER_CACHE - bk_dma_get_remain_len(dvp_camera_dma_channel);
bk_dma_stop(dvp_camera_dma_channel);
dvp_camera_drv->dma_length += recv_length - JPEG_CRC_SIZE;
if (dvp_camera_drv->dma_length != real_length)
{
LOGW("%s size no match:%d-%d=%d\r\n", __func__, real_length, dvp_camera_drv->dma_length, real_length - dvp_camera_drv->dma_length);
}
dvp_camera_drv->dma_length = 0;
if (dvp_camera_drv->cached)
{
if (dvp_camera_drv->psram_dma_busy == true)
{
media_debug->psram_busy++;
dvp_camera_drv->frame = curr_encode_frame;
dvp_camera_drv->eof = true;
dvp_camera_drv->psram_dma_left = recv_length;
}
else
{
dvp_camera_drv->frame = curr_encode_frame;
dvp_camera_drv->psram_dma_left = 0;
dvp_camera_drv->eof = true;
dvp_memcpy_by_chnl(curr_encode_frame->frame + curr_encode_frame->length,
dvp_camera_drv->index ? (dvp_camera_drv->buffer + FRAME_BUFFER_CACHE) : dvp_camera_drv->buffer,
recv_length, dvp_camera_drv->psram_dma);
curr_encode_frame->length += recv_length;
curr_encode_frame->sequence = dvp_camera_drv->frame_id++;
}
}
else
{
/*there not compare dma copy total length and read from jpeg register length, because register count is error*/
if (dvp_camera_config->device->mode == JPEG_YUV_MODE)
{
curr_encode_frame->mix = true;
}
curr_encode_frame->length = curr_encode_frame->length + recv_length - JPEG_CRC_SIZE;
if (curr_encode_frame->frame[curr_encode_frame->length - 2] == 0xFF
&& curr_encode_frame->frame[curr_encode_frame->length - 1] == 0xD9)
{
dvp_camera_drv->eof = true;
}
else if (curr_encode_frame->frame[real_length - 2] == 0xFF
&& curr_encode_frame->frame[real_length - 1] == 0xD9)
{
dvp_camera_drv->eof = true;
curr_encode_frame->length = real_length;
}
else
{
dvp_camera_drv->eof = false;
}
if (dvp_camera_drv->eof)
{
media_debug->jpeg_length = curr_encode_frame->length;
media_debug->jpeg_kbps += curr_encode_frame->length;
curr_encode_frame->sequence = dvp_camera_drv->frame_id++;
dvp_camera_config->fb_complete(curr_encode_frame);
curr_encode_frame = dvp_camera_config->fb_malloc(FB_INDEX_JPEG, CONFIG_JPEG_FRAME_SIZE);
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("alloc frame error\n");
return;
}
curr_encode_frame->width = dvp_camera_config->device->info.resolution.width;
curr_encode_frame->height = dvp_camera_config->device->info.resolution.height;
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
curr_encode_frame->type = dvp_camera_config->device->type;
}
else
{
curr_encode_frame->length = 0;
}
dvp_camera_drv->eof = false;
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("alloc frame error\n");
return;
}
bk_dma_set_dest_addr(dvp_camera_dma_channel, (uint32_t)curr_encode_frame->frame, (uint32_t)(curr_encode_frame->frame + curr_encode_frame->size));
bk_dma_start(dvp_camera_dma_channel);
if (dvp_camera_config->device->mode == JPEG_YUV_MODE)
{
DVP_YUV_EOF_ENTRY();
uint32_t size = dvp_camera_config->device->info.resolution.width * dvp_camera_config->device->info.resolution.height * 2;
encode_yuv_config->yuv_data_offset = 0;
bk_dma_flush_src_buffer(encode_yuv_config->dma_collect_yuv);
curr_yuv_frame->sequence = dvp_camera_drv->frame_id;
dvp_camera_config->fb_complete(curr_yuv_frame);
curr_yuv_frame = dvp_camera_config->fb_malloc(FB_INDEX_DISPLAY, size);
if (curr_yuv_frame != NULL)
{
curr_yuv_frame->width = dvp_camera_config->device->info.resolution.width;
curr_yuv_frame->height = dvp_camera_config->device->info.resolution.height;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->type = dvp_camera_config->device->type;
curr_yuv_frame->length = size;
}
else
{
LOGE("%s malloc frame failed\n", __func__);
}
DVP_YUV_EOF_OUT();
}
}
DVP_JPEG_EOF_OUT();
return;
error:
dvp_camera_drv->index = 0;
bk_dma_stop(dvp_camera_dma_channel);
bk_video_encode_stop(JPEG_MODE);
}
#if (CONFIG_H264)
static void dvp_camera_h264_eof_handler(h264_unit_t id, void *param)
{
uint32_t real_length = bk_h264_get_encode_count() * 4;
uint32_t remain_length = 0;
frame_buffer_t *new_frame = NULL;
#if (!CONFIG_H264_GOP_START_IDR_FRAME)
uint8_t sps_pps_fill = 0;
#endif
DVP_H264_EOF_ENTRY();
dvp_camera_drv->sequence++;
if (dvp_camera_drv->sequence > H264_GOP_FRAME_CNT)
{
dvp_camera_drv->sequence = 1;
}
if (dvp_camera_drv->sequence == 1)
{
dvp_camera_drv->i_frame = 1;
}
else
{
dvp_camera_drv->i_frame = 0;
}
if (dvp_state != MASTER_TURN_ON)
{
DVP_H264_EOF_OUT();
return;
}
if (curr_encode_frame == NULL
|| curr_encode_frame->frame == NULL)
{
LOGE("curr_encode_frame NULL error\n");
DVP_H264_EOF_OUT();
goto error;
}
#if (CONFIG_H264_GOP_START_IDR_FRAME)
if (dvp_camera_drv->sequence == H264_GOP_FRAME_CNT)
{
dvp_camera_drv->regenerate_idr = true;
}
#endif
if (real_length > CONFIG_H264_FRAME_SIZE - 0x20)
{
LOGE("%s size over h264 buffer range, %d\r\n", __func__, real_length);
dvp_camera_drv->error = true;
}
bk_dma_flush_src_buffer(dvp_camera_dma_channel);
remain_length = FRAME_BUFFER_CACHE - bk_dma_get_remain_len(dvp_camera_dma_channel);
bk_dma_stop(dvp_camera_dma_channel);
dvp_camera_drv->dma_length += remain_length;
if (dvp_camera_drv->dma_length != real_length)
{
uint32_t left_length = real_length - dvp_camera_drv->dma_length;
if (left_length != FRAME_BUFFER_CACHE)
{
LOGW("%s size no match:%d-%d=%d\r\n", __func__, real_length, dvp_camera_drv->dma_length, left_length);
dvp_camera_drv->error = true;
}
}
dvp_camera_drv->dma_length = 0;
if (dvp_camera_drv->error)
{
curr_encode_frame->length = 0;
dvp_camera_drv->sps_pps_flag = false;
dvp_camera_drv->sequence = 0;
dvp_camera_drv->offset = 0;
DVP_H264_EOF_OUT();
return;
}
media_debug->isr_h264++;
if (dvp_camera_drv->cached)
{
if (dvp_camera_drv->psram_dma_busy == true)
{
dvp_camera_drv->frame = curr_encode_frame;
dvp_camera_drv->psram_dma_left = remain_length;
dvp_camera_drv->eof = true;
media_debug->psram_busy++;
}
else
{
dvp_camera_drv->frame = curr_encode_frame;
dvp_camera_drv->psram_dma_left = 0;
dvp_camera_drv->eof = true;
dvp_memcpy_by_chnl(curr_encode_frame->frame + curr_encode_frame->length,
dvp_camera_drv->index ? (dvp_camera_drv->buffer + FRAME_BUFFER_CACHE) : dvp_camera_drv->buffer,
remain_length, dvp_camera_drv->psram_dma);
curr_encode_frame->length += remain_length;
curr_encode_frame->sequence = dvp_camera_drv->frame_id++;
}
}
else
{
if (dvp_camera_config->device->mode == H264_YUV_MODE)
{
curr_encode_frame->mix = true;
}
curr_encode_frame->length = real_length + dvp_camera_drv->offset;
media_debug->h264_length = curr_encode_frame->length;
media_debug->h264_kbps += curr_encode_frame->length;
curr_encode_frame->sequence = dvp_camera_drv->frame_id++;
#if (!CONFIG_H264_GOP_START_IDR_FRAME)
if (!dvp_camera_drv->sps_pps_flag)
{
if (curr_encode_frame->frame[4] == 0x67)
{
const uint8_t sei_fill_data[] = {
0x00, 0x00, 0x00, 0x01, 0x06, 0x05, 0x0F, 0x01,
0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01,
0x02, 0x03, 0x04, 0x01, 0x05, 0x00, 0x80
};
os_memcpy(dvp_camera_drv->sps_pps, curr_encode_frame->frame, H264_SPS_PPS_SIZE);
os_memcpy(&dvp_camera_drv->sps_pps[H264_SPS_PPS_SIZE], sei_fill_data, sizeof(dvp_camera_drv->sps_pps) - H264_SPS_PPS_SIZE);
dvp_camera_drv->sps_pps_flag = 1;
curr_encode_frame->h264_type |= (1 << H264_NAL_SPS) | (1 << H264_NAL_PPS);
}
else
{
LOGE("%s sps pps head miss\n", __func__);
}
}
#endif
if (dvp_camera_drv->i_frame)
{
curr_encode_frame->h264_type |= 1 << H264_NAL_I_FRAME;
#if (CONFIG_H264_GOP_START_IDR_FRAME)
curr_encode_frame->h264_type |= (1 << H264_NAL_SPS) | (1 << H264_NAL_PPS) | (1 << H264_NAL_IDR_SLICE);
#endif
}
else
{
curr_encode_frame->h264_type |= 1 << H264_NAL_P_FRAME;
#if (!CONFIG_H264_GOP_START_IDR_FRAME)
if (dvp_camera_drv->sequence == (CONFIG_H264_P_FRAME_CNT + 1)
&& dvp_camera_drv->sps_pps_flag)
{
sps_pps_fill = true;
}
#endif
}
curr_encode_frame->timestamp = dvp_camera_get_milliseconds();
#ifdef CONFIG_H264_ADD_SELF_DEFINE_SEI
curr_encode_frame->crc = hnd_crc8(curr_encode_frame->frame, curr_encode_frame->length, 0xFF);
curr_encode_frame->length += H264_SELF_DEFINE_SEI_SIZE;
os_memcpy(&dvp_camera_drv->sei[23], (uint8_t *)curr_encode_frame, sizeof(frame_buffer_t));
os_memcpy(&curr_encode_frame->frame[curr_encode_frame->length - H264_SELF_DEFINE_SEI_SIZE], &dvp_camera_drv->sei[0], H264_SELF_DEFINE_SEI_SIZE);
#endif
LOGD("%d, I:%d, p:%d\r\n", curr_encode_frame->length, (curr_encode_frame->h264_type & 0x1000020) > 0 ? 1 : 0, (curr_encode_frame->h264_type >> 23) & 0x1);
new_frame = dvp_camera_config->fb_malloc(FB_INDEX_H264, CONFIG_H264_FRAME_SIZE);
if (new_frame)
{
dvp_camera_config->fb_complete(curr_encode_frame);
curr_encode_frame = new_frame;
}
else
{
dvp_camera_drv->regenerate_idr = true;
}
curr_encode_frame->width = dvp_camera_config->device->info.resolution.width;
curr_encode_frame->height = dvp_camera_config->device->info.resolution.height;
curr_encode_frame->length = 0;
curr_encode_frame->fmt = dvp_camera_config->device->fmt;
curr_encode_frame->type = dvp_camera_config->device->type;
curr_encode_frame->h264_type = 0;
dvp_camera_drv->offset = 0;
#if (!CONFIG_H264_GOP_START_IDR_FRAME)
if (sps_pps_fill)
{
dvp_camera_drv->offset = sizeof(dvp_camera_drv->sps_pps);
os_memcpy(curr_encode_frame->frame, dvp_camera_drv->sps_pps, dvp_camera_drv->offset);
curr_encode_frame->length += dvp_camera_drv->offset;
curr_encode_frame->h264_type |= (1 << H264_NAL_SPS) | (1 << H264_NAL_PPS);
}
#endif
bk_dma_set_dest_addr(dvp_camera_dma_channel, (uint32_t)(curr_encode_frame->frame + dvp_camera_drv->offset), (uint32_t)(curr_encode_frame->frame + curr_encode_frame->size));
bk_dma_start(dvp_camera_dma_channel);
if (dvp_camera_config->device->mode == H264_YUV_MODE)
{
DVP_YUV_EOF_ENTRY();
uint32_t size = dvp_camera_config->device->info.resolution.width * dvp_camera_config->device->info.resolution.height * 2;
encode_yuv_config->yuv_data_offset = 0;
bk_dma_flush_src_buffer(encode_yuv_config->dma_collect_yuv);
curr_yuv_frame->sequence = dvp_camera_drv->frame_id;
dvp_camera_config->fb_complete(curr_yuv_frame);
curr_yuv_frame = dvp_camera_config->fb_malloc(FB_INDEX_DISPLAY, size);
if (curr_yuv_frame != NULL)
{
curr_yuv_frame->width = dvp_camera_config->device->info.resolution.width;
curr_yuv_frame->height = dvp_camera_config->device->info.resolution.height;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->type = dvp_camera_config->device->type;
curr_yuv_frame->length = size;
}
else
{
LOGE("%s malloc frame failed\n", __func__);
}
DVP_YUV_EOF_OUT();
}
}
if (dvp_camera_drv->regenerate_idr)
{
dvp_camera_drv->regenerate_idr = false;
dvp_camera_drv->sequence = 0;
bk_h264_soft_reset();
}
DVP_H264_EOF_OUT();
return;
error:
dvp_camera_drv->index = 0;
bk_dma_stop(dvp_camera_dma_channel);
bk_video_encode_stop(H264_MODE);
DVP_H264_EOF_OUT();
}
#endif // CONFIG_H264
static bk_err_t dvp_camera_jpeg_config_init(yuv_mode_t mode)
{
int ret = BK_OK;
if (mode == GRAY_MODE)
jpeg_config.x_pixel = dvp_camera_config->device->info.resolution.width / 8 / 2;
else
jpeg_config.x_pixel = dvp_camera_config->device->info.resolution.width / 8;
jpeg_config.y_pixel = dvp_camera_config->device->info.resolution.height / 8;
jpeg_config.vsync = current_sensor->vsync;
jpeg_config.hsync = current_sensor->hsync;
jpeg_config.clk = current_sensor->clk;
jpeg_config.mode = mode;
switch (current_sensor->fmt)
{
case PIXEL_FMT_YUYV:
jpeg_config.sensor_fmt = YUV_FORMAT_YUYV;
break;
case PIXEL_FMT_UYVY:
jpeg_config.sensor_fmt = YUV_FORMAT_UYVY;
break;
case PIXEL_FMT_YYUV:
jpeg_config.sensor_fmt = YUV_FORMAT_YYUV;
break;
case PIXEL_FMT_UVYY:
jpeg_config.sensor_fmt = YUV_FORMAT_UVYY;
break;
default:
LOGE("JPEG MODULE not support this sensor input format\r\n");
ret = kParamErr;
return ret;
}
ret = bk_jpeg_enc_init(&jpeg_config);
if (ret != BK_OK)
{
LOGE("jpeg init error\n");
}
return ret;
}
#if CONFIG_YUV_BUF
bk_err_t dvp_camera_yuv_buf_config_init(yuv_mode_t mode)
{
int ret = BK_OK;
yuv_buf_config_t yuv_mode_config = {0};
yuv_mode_config.work_mode = mode;
yuv_mode_config.mclk_div = YUV_MCLK_DIV_3;
if (mode != GRAY_MODE)
yuv_mode_config.x_pixel = dvp_camera_config->device->info.resolution.width / 8;
else
yuv_mode_config.x_pixel = dvp_camera_config->device->info.resolution.width / 8 / 2;
yuv_mode_config.y_pixel = dvp_camera_config->device->info.resolution.height / 8;
yuv_mode_config.yuv_mode_cfg.vsync = current_sensor->vsync;
yuv_mode_config.yuv_mode_cfg.hsync = current_sensor->hsync;
LOGI("%s, %d-%d, mode:%d\r\n", __func__, dvp_camera_config->device->info.resolution.width, dvp_camera_config->device->info.resolution.height, mode);
switch (current_sensor->fmt)
{
case PIXEL_FMT_YUYV:
yuv_mode_config.yuv_mode_cfg.yuv_format = YUV_FORMAT_YUYV;
break;
case PIXEL_FMT_UYVY:
yuv_mode_config.yuv_mode_cfg.yuv_format = YUV_FORMAT_UYVY;
break;
case PIXEL_FMT_YYUV:
yuv_mode_config.yuv_mode_cfg.yuv_format = YUV_FORMAT_YYUV;
break;
case PIXEL_FMT_UVYY:
yuv_mode_config.yuv_mode_cfg.yuv_format = YUV_FORMAT_UVYY;
break;
default:
LOGE("YUV_BUF MODULE not support this sensor input format\r\n");
ret = kParamErr;
}
if (ret != BK_OK)
{
return ret;
}
if (mode != GRAY_MODE && mode != YUV_MODE)
{
if (dvp_camera_encode == NULL)
{
dvp_camera_encode = dvp_camera_yuv_base_addr_init(dvp_camera_config->device->info.resolution, mode);
if (dvp_camera_encode == NULL)
{
return BK_ERR_NO_MEM;
}
}
LOGI("%s, encode_buf:0x%p\r\n", __func__, dvp_camera_encode);
yuv_mode_config.base_addr = dvp_camera_encode;
}
ret = bk_yuv_buf_init(&yuv_mode_config);
if (ret != BK_OK) {
LOGE("yuv_buf yuv mode init error\n");
}
return ret;
}
#endif
static bk_err_t dvp_camera_yuv_mode(dvp_camera_config_t *config)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
int ret = BK_OK;
uint32_t size = 0;
#if (CONFIG_YUV_BUF)
ret = dvp_camera_yuv_buf_config_init(YUV_MODE);
if (ret != BK_OK)
{
return ret;
}
#else
ret = dvp_camera_jpeg_config_init(YUV_MODE);
if (ret != BK_OK)
{
return ret;
}
#endif
config->fb_init(FB_INDEX_DISPLAY);
size = config->device->info.resolution.width * config->device->info.resolution.height * 2;
curr_yuv_frame = dvp_camera_config->fb_malloc(FB_INDEX_DISPLAY, size);
if (curr_yuv_frame == NULL)
{
LOGE("malloc frame fail \r\n");
ret = BK_FAIL;
}
curr_yuv_frame->width = config->device->info.resolution.width;
curr_yuv_frame->height = config->device->info.resolution.height;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->length = size;
bk_jpeg_set_em_base_addr(curr_yuv_frame->frame);
#if (CONFIG_YUV_BUF)
bk_yuv_buf_set_em_base_addr((uint32_t)curr_yuv_frame->frame);
#else
bk_jpeg_set_em_base_addr(curr_yuv_frame->frame);
#endif
return ret;
}
static bk_err_t dvp_camera_jpeg_mode(dvp_camera_config_t *config)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
int ret = BK_OK;
config->fb_init(FB_INDEX_JPEG);
ret = dvp_camera_dma_config();
if (ret != BK_OK)
{
LOGE("dma init failed\n");
return ret;
}
#if (CONFIG_YUV_BUF)
ret = dvp_camera_yuv_buf_config_init(JPEG_MODE);
if (ret != BK_OK)
{
return ret;
}
#endif
ret = dvp_camera_jpeg_config_init(JPEG_MODE);
if (ret != BK_OK)
{
return ret;
}
#if (CONFIG_YUV_BUF)
if (config->device->mode == JPEG_YUV_MODE)
{
uint32_t size = config->device->info.resolution.width * config->device->info.resolution.height * 2;
config->fb_init(FB_INDEX_DISPLAY);
curr_yuv_frame = config->fb_malloc(FB_INDEX_DISPLAY, size);
if(curr_yuv_frame == NULL)
{
LOGE("yuv_frame malloc failed!\r\n");
ret = BK_ERR_NO_MEM;
return ret;
}
curr_yuv_frame->width = config->device->info.resolution.width;
curr_yuv_frame->height = config->device->info.resolution.height;
curr_yuv_frame->type = dvp_camera_config->device->type;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->length = size;
if (encode_yuv_config == NULL)
{
encode_yuv_config = (encode_yuv_config_t *)os_malloc(sizeof(encode_yuv_config_t));
if (encode_yuv_config == NULL)
{
LOGE("encode_yuv_config malloc error! \r\n");
ret = BK_ERR_NO_MEM;
return ret;
}
}
encode_yuv_config->yuv_em_addr = bk_yuv_buf_get_em_base_addr();
LOGI("yuv buffer base addr:%08x\r\n", encode_yuv_config->yuv_em_addr);
encode_yuv_config->dma_collect_yuv = bk_dma_alloc(DMA_DEV_DTCM);
encode_yuv_config->yuv_pingpong_length = config->device->info.resolution.width * 8 * 2;
encode_yuv_config->yuv_data_offset = 0;
LOGI("dma_collect_yuv id is %d \r\n", encode_yuv_config->dma_collect_yuv);
encode_yuv_dma_cpy(curr_yuv_frame->frame,
(uint32_t *)encode_yuv_config->yuv_em_addr,
encode_yuv_config->yuv_pingpong_length,
encode_yuv_config->dma_collect_yuv);
}
#endif
return ret;
}
static bk_err_t dvp_camera_h264_mode(dvp_camera_config_t *config)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
int ret = BK_OK;
#if CONFIG_YUV_BUF
ret = dvp_camera_yuv_buf_config_init(H264_MODE);
if (ret != BK_OK)
{
return ret;
}
ret = bk_h264_init((config->device->info.resolution.width << 16) | config->device->info.resolution.height);
if (ret != BK_OK)
{
return ret;
}
config->fb_init(FB_INDEX_H264);
ret = dvp_camera_dma_config();
if (ret != BK_OK)
{
LOGE("dma init failed\n");
return ret;
}
#ifdef CONFIG_H264_ADD_SELF_DEFINE_SEI
os_memset(&dvp_camera_drv->sei[0], 0xFF, H264_SELF_DEFINE_SEI_SIZE);
h264_encode_sei_init(&dvp_camera_drv->sei[0]);
#endif
if (config->device->mode == H264_YUV_MODE)
{
uint32_t size = config->device->info.resolution.width * config->device->info.resolution.height * 2;
config->fb_init(FB_INDEX_DISPLAY);
curr_yuv_frame = config->fb_malloc(FB_INDEX_DISPLAY, size);
if(curr_yuv_frame == NULL)
{
LOGE("yuv_frame malloc failed!\r\n");
ret = BK_ERR_NO_MEM;
return ret;
}
curr_yuv_frame->width = config->device->info.resolution.width;
curr_yuv_frame->height = config->device->info.resolution.height;
curr_yuv_frame->fmt = current_sensor->fmt;
curr_yuv_frame->type = dvp_camera_config->device->type;
curr_yuv_frame->length = size;
if (encode_yuv_config == NULL)
{
encode_yuv_config = (encode_yuv_config_t *)os_malloc(sizeof(encode_yuv_config_t));
if (encode_yuv_config == NULL)
{
LOGE("encode_lcd_config malloc error! \r\n");
ret = BK_ERR_NO_MEM;
return ret;
}
}
encode_yuv_config->yuv_em_addr = bk_yuv_buf_get_em_base_addr();
LOGI("yuv buffer base addr:%08x\r\n", encode_yuv_config->yuv_em_addr);
encode_yuv_config->dma_collect_yuv = bk_dma_alloc(DMA_DEV_DTCM);
encode_yuv_config->yuv_pingpong_length = config->device->info.resolution.width * 16 * 2;
encode_yuv_config->yuv_data_offset = 0;
LOGI("dma_collect_yuv id is %d \r\n", encode_yuv_config->dma_collect_yuv);
encode_yuv_dma_cpy(curr_yuv_frame->frame,
(uint32_t *)encode_yuv_config->yuv_em_addr,
encode_yuv_config->yuv_pingpong_length,
encode_yuv_config->dma_collect_yuv);
}
#endif
return ret;
}
static void dvp_camera_register_isr_function(yuv_mode_t mode)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
switch (mode)
{
case GRAY_MODE:
case YUV_MODE:
#if CONFIG_YUV_BUF
bk_yuv_buf_register_isr(YUV_BUF_YUV_ARV, dvp_camera_yuv_eof_handler, NULL);
#else
bk_jpeg_enc_register_isr(JPEG_EOY, dvp_camera_yuv_eof_handler, NULL);
#endif
break;
case JPEG_YUV_MODE:
case JPEG_MODE:
bk_jpeg_enc_register_isr(JPEG_EOF, dvp_camera_jpeg_eof_handler, NULL);
#if CONFIG_YUV_BUF
bk_jpeg_enc_register_isr(JPEG_FRAME_ERR, dvp_camera_sensor_ppi_err_handler, NULL);
#endif
break;
case H264_YUV_MODE:
case H264_MODE:
#if CONFIG_H264
bk_h264_register_isr(H264_FINAL_OUT, dvp_camera_h264_eof_handler, NULL);
#endif
break;
default:
break;
}
#if CONFIG_YUV_BUF
if (mode == JPEG_YUV_MODE || mode == H264_YUV_MODE)
{
bk_yuv_buf_register_isr(YUV_BUF_SM0_WR, (yuv_buf_isr_t)yuv_sm0_line_done, NULL);
bk_yuv_buf_register_isr(YUV_BUF_SM1_WR, (yuv_buf_isr_t)yuv_sm1_line_done, NULL);
bk_yuv_buf_register_isr(YUV_BUF_YUV_ARV, dvp_camera_yuv_eof_handler, NULL);
}
bk_yuv_buf_register_isr(YUV_BUF_VSYNC_NEGEDGE, dvp_camera_vsync_negedge_handler, NULL);
bk_yuv_buf_register_isr(YUV_BUF_SEN_RESL, dvp_camera_sensor_ppi_err_handler, NULL);
bk_yuv_buf_register_isr(YUV_BUF_FULL, dvp_camera_sensor_ppi_err_handler, NULL);
bk_yuv_buf_register_isr(YUV_BUF_H264_ERR, dvp_camera_sensor_ppi_err_handler, NULL);
bk_yuv_buf_register_isr(YUV_BUF_ENC_SLOW, dvp_camera_sensor_ppi_err_handler, NULL);
#else
bk_jpeg_enc_register_isr(JPEG_VSYNC_NEGEDGE, dvp_camera_vsync_negedge_handler, NULL);
#endif
}
const dvp_sensor_config_t *bk_dvp_camera_enumerate(void)
{
i2c_config_t i2c_config = {0};
// step 1: power on video modules
bk_video_power_on(CONFIG_CAMERA_CTRL_POWER_GPIO_ID, 1);
// step 2: map gpio as MCLK, PCLK for i2c communicate with dvp
bk_video_gpio_init(DVP_GPIO_ALL);
// step 3: enable mclk for i2c communicate with dvp
bk_video_dvp_mclk_enable(YUV_MODE);
// step 4: init i2c
i2c_config.baud_rate = I2C_BAUD_RATE_100KHZ;
i2c_config.addr_mode = I2C_ADDR_MODE_7BIT;
bk_i2c_init(CONFIG_DVP_CAMERA_I2C_ID, &i2c_config);
// step 5: detect sensor
current_sensor = bk_dvp_get_sensor_auto_detect();
if (current_sensor == NULL) {
LOGE("%s no dvp camera found\n", __func__);
return NULL;
}
LOGI("auto detect success, dvp camera name:%s\r\n", current_sensor->name);
return current_sensor;
}
bk_err_t bk_dvp_camera_driver_init(dvp_camera_config_t *config)
{
int ret = BK_OK;
LOGI("%s\r\n", __func__);
if (dvp_state != MASTER_TURN_OFF)
{
LOGE("dvp init state error\r\n");
ret = BK_FAIL;
return ret;
}
dvp_state = MASTER_TURNING_ON;
DVP_DIAG_DEBUG_INIT();
if (dvp_camera_config == NULL)
{
dvp_camera_config = (dvp_camera_config_t *)os_malloc(sizeof(dvp_camera_config_t));
if (dvp_camera_config == NULL)
{
LOGE("%s, dvp_camera_config malloc failed!\r\n", __func__);
goto error;
}
#if !CONFIG_YUV_BUF
if (config->device->mode == JPEG_YUV_MODE)
config->device->mode = JPEG_MODE;
#endif
os_memcpy(dvp_camera_config, config, sizeof(dvp_camera_config_t));
dvp_camera_config->device = (media_camera_device_t *)os_malloc(sizeof(media_camera_device_t));
if (dvp_camera_config->device == NULL)
{
LOGE("%s, dvp_camera_config->device malloc failed!\r\n", __func__);
goto error;
}
os_memcpy(dvp_camera_config->device, config->device, sizeof(media_camera_device_t));
}
if (dvp_camera_drv == NULL)
{
dvp_camera_drv = (dvp_driver_t *)os_malloc(sizeof(dvp_driver_t));
if (dvp_camera_drv == NULL)
{
LOGE("%s, dvp_camera_drv malloc failed!\r\n", __func__);
goto error;
}
os_memset(dvp_camera_drv, 0, sizeof(dvp_driver_t));
ret = rtos_init_semaphore(&dvp_camera_drv->sem, 1);
if (ret != BK_OK)
{
LOGE("%s, dvp_camera_drv->sem malloc failed!\r\n", __func__);
goto error;
}
}
LOGI("%s, %d, mode:%d\r\n", __func__, __LINE__, dvp_camera_config->device->mode);
/*if need cache psram too solw, you need use dma copy fifo data to sram, than copy to psram*/
if (dvp_camera_config->device->mode == JPEG_MODE || dvp_camera_config->device->mode == JPEG_YUV_MODE)
{
#if !CONFIG_YUV_BUF
dvp_camera_drv->cached = true;
#endif
}
if (dvp_camera_drv->cached)
{
if (dvp_camera_drv->buffer == NULL)
{
dvp_camera_drv->buffer = (uint8_t *)os_malloc(FRAME_BUFFER_CACHE * 2);
}
dvp_camera_drv->psram_dma = bk_dma_alloc(DMA_DEV_DTCM);
if ((dvp_camera_drv->psram_dma < DMA_ID_0) || (dvp_camera_drv->psram_dma >= DMA_ID_MAX))
{
LOGE("malloc dvp_camera_drv->psram_dma fail \r\n");
ret = BK_FAIL;
goto error;
}
LOGI("dvp_camera_drv->psram_dma:%d \r\n", dvp_camera_drv->psram_dma);
}
// step 1: for camera sensor, init other device
ret = dvp_camera_init(dvp_camera_config->device->mode);
if (ret != BK_OK)
{
goto error;
}
// step 2: config video hardware modules, include dma
switch (dvp_camera_config->device->mode)
{
case YUV_MODE:
case GRAY_MODE:
ret = dvp_camera_yuv_mode(dvp_camera_config);
break;
case JPEG_MODE:
case JPEG_YUV_MODE:
ret = dvp_camera_jpeg_mode(dvp_camera_config);
break;
case H264_MODE:
case H264_YUV_MODE:
ret = dvp_camera_h264_mode(dvp_camera_config);
break;
default:
ret = BK_FAIL;
}
if (ret != BK_OK)
{
goto error;
}
// step 3: maybe need register isr_func
dvp_camera_register_isr_function(dvp_camera_config->device->mode);
// step 4: start hardware function in different mode
bk_video_set_mclk(current_sensor->clk);
bk_video_encode_start(dvp_camera_config->device->mode);
// step 5: init dvp camera sensor register
current_sensor->init();
current_sensor->set_ppi((dvp_camera_config->device->info.resolution.width << 16) | dvp_camera_config->device->info.resolution.height);
current_sensor->set_fps(dvp_camera_config->device->info.fps);
media_debug->isr_jpeg = 0;
media_debug->isr_h264 = 0;
media_debug->psram_busy = 0;
media_debug->jpeg_length = 0;
media_debug->h264_length = 0;
media_debug->jpeg_kbps = 0;
media_debug->h264_kbps = 0;
dvp_state = MASTER_TURN_ON;
return ret;
error:
dvp_camera_deinit();
return ret;
}
bk_err_t bk_dvp_camera_driver_deinit(void)
{
if (dvp_state == MASTER_TURN_OFF)
{
LOGI("%s, dvp have been closed!\r\n", __func__);
return BK_FAIL;
}
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
dvp_state = MASTER_TURNING_OFF;
GLOBAL_INT_RESTORE();
if (kNoErr != rtos_get_semaphore(&dvp_camera_drv->sem, 500))
{
LOGI("Not wait yuv vsync negedge!\r\n");
}
dvp_camera_deinit();
return BK_OK;
}
media_camera_device_t *bk_dvp_camera_get_device(void)
{
if (dvp_state == MASTER_TURN_ON)
return dvp_camera_config->device;
else
return NULL;
}
bk_err_t bk_dvp_camera_free_encode_mem(void)
{
#if (CONFIG_ENCODE_BUF_NOT_FREE)
if (dvp_camera_encode)
{
if (dvp_state == MASTER_TURN_OFF)
{
os_free(dvp_camera_encode);
dvp_camera_encode = NULL;
return BK_OK;
}
else
{
LOGI("camera is working, can not free\r\n");
return BK_FAIL;
}
}
else
{
LOGI("camera not malloc encode mem, can not free\r\n");
return BK_OK;
}
#else
LOGW("marco CONFIG_ENCODE_BUF_NOT_FREE not enable!\r\n");
return BK_FAIL;
#endif
}
bk_err_t bk_dvp_camera_h264_regenerate_idr_frame(void)
{
if (dvp_state != MASTER_TURN_ON)
{
LOGW("%s, %d dvp not open!\r\n", __func__, __LINE__);
return BK_FAIL;
}
if (dvp_camera_config == NULL
|| dvp_camera_drv == NULL
|| (dvp_camera_config->device->mode != H264_MODE && dvp_camera_config->device->mode != H264_YUV_MODE)
)
{
LOGW("%s, %d not support this encode mode!\r\n", __func__, __LINE__);
return BK_FAIL;
}
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
dvp_camera_drv->regenerate_idr = true;
GLOBAL_INT_RESTORE();
return BK_OK;
}