doubao_chat/apps/common/camera/byd3901/byd3901.c

478 lines
11 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "asm/iic.h"
#include "asm/isp_dev.h"
#include "byd3901.h"
#include "gpio.h"
#include "generic/jiffies.h"
#include "device/iic.h"
#include "device/device.h"
#include "app_config.h"
#ifdef CONFIG_VIDEO_ENABLE
static void *iic = NULL;
static u8 BYD3901_reset_io[2] = {-1, -1};
static u8 BYD3901_power_io[2] = {-1, -1};
#define BYD3901_DEVP_INPUT_W 240
#define BYD3901_DEVP_INPUT_H 320
#define BYD3901_WRCMD 0xdc
#define BYD3901_RDCMD 0xdd
#define CONFIG_INPUT_FPS 15
#define BYD3901_OUT_CLK 24 //24M 48M
#define DELAY_TIME 10
struct reginfo {
u8 reg;
u8 val;
};
static const struct reginfo sensor_init_data[] = {
//MTK SPI Mode
//XCLK:24M SCLK:48M MCLK:6M
//行长:320 帧长:240
//max fps:30fps
{0x12, 0x80},
{0x11, 0x30},
#if BYD3901_OUT_CLK == 48
{0x1b, 0x06},//SCLK:48M.MCLK:6M
#else
{0x1b, 0x80},//SCLK:24M.MCLK:6M
#endif
{0x0b, 0x03},
/*{0x6b, 0x01},//0x6b[6]=1,打开CCIR656编码方式。*/
{0x6b, 0x71},//0x6b[6]=1,打开CCIR656编码方式。
{0x12, 0x10},//0x12[5:4]=10
{0x3a, 0x00},
{0x15, 0x22},
{0x62, 0x81},//0x62[1:0]:2'01,SPI mode
{0x08, 0xa0},
{0x06, 0x68},
{0x2b, 0x00},
{0x27, 0x97},
/******240 * 320**********/
{0x17, 0x00},
{0x18, (u8)((BYD3901_DEVP_INPUT_W >> 1) & 0xFF)},
{0x19, 0x00},
{0x1a, (u8)((BYD3901_DEVP_INPUT_H >> 1) & 0xFF)},
{0x03, (u8)((((BYD3901_DEVP_INPUT_W & 0x1) << 1) | ((BYD3901_DEVP_INPUT_H & 0x1) << 3)) & 0xFF)},
/****************/
{0x13, 0x00},
{0x01, 0x13},
{0x02, 0x20},
{0x87, 0x16},
{0x8c, 0x01},
{0x8d, 0xcc},
{0x13, 0x07},
{0x33, 0x10},
{0x34, 0x1d},
{0x35, 0x46},
{0x36, 0x40},
{0x37, 0xa4},
{0x38, 0x7c},
{0x65, 0x46},
{0x66, 0x46},
{0x6e, 0x20},
{0x9b, 0xa4},
{0x9c, 0x7c},
{0xbc, 0x0c},
{0xbd, 0xa4},
{0xbe, 0x7c},
{0x20, 0x09},
/*{0x09, 0x03},*/
{0x72, 0x54},
{0x73, 0x27},
{0x74, 0x87},
{0x75, 0x12},
{0x79, 0x8c},
{0x7a, 0x00},
{0x7e, 0xfa},
{0x70, 0x0f},
{0x7c, 0x84},
{0x7d, 0xba},
{0x5b, 0xc2},
{0x76, 0x90},
{0x7b, 0x55},
{0x71, 0x46},
{0x77, 0xdd},
{0x13, 0x0f},
{0x8a, 0x10},
{0x8b, 0x20},
{0x8e, 0x21},
{0x8f, 0x40},
{0x94, 0x41},
{0x95, 0x7e},
{0x96, 0x7f},
{0x97, 0xf3},
{0x13, 0x07},
{0x24, 0x55}, //50 调亮度 50=V12 55=V13
{0x97, 0x48},
{0x25, 0x08},
{0x94, 0xb5},
{0x95, 0xc0},
{0x80, 0xf6},
{0x81, 0xe0},
{0x82, 0x1b},
{0x83, 0x37},
{0x84, 0x39},
{0x85, 0x58},
{0x86, 0xc0},
{0x8a, 0x5c},//33
{0xf1, 0x00},//33
#if CONFIG_INPUT_FPS == 15
//3d 、16 fps 0x2d=20fps 0x25=25fps
{0x89, 0x25},
#else
//10 fps
{0x89, 0x55},
{0x92, 0x6d},//10 fps
#endif
{0x8b, 0x4c},
{0x39, 0x80},
{0x3f, 0x80},
{0x90, 0xa0},
{0x91, 0xe0},
{0x40, 0x20},
{0x41, 0x28},
{0x42, 0x26},
{0x43, 0x25},
{0x44, 0x1f},
{0x45, 0x1a},
{0x46, 0x16},
{0x47, 0x12},
{0x48, 0x0f},
{0x49, 0x0d},
{0x4b, 0x0b},
{0x4c, 0x0a},
{0x4e, 0x08},
{0x4f, 0x06},
{0x50, 0x06},
{0x40, 0x17},
{0x41, 0x27},
{0x42, 0x25},
{0x43, 0x23},
{0x44, 0x20},
{0x45, 0x18},
{0x46, 0x16},
{0x47, 0x13},
{0x48, 0x0f},
{0x49, 0x0c},
{0x4b, 0x0b},
{0x4c, 0x0a},
{0x4e, 0x08},
{0x4f, 0x08},
{0x50, 0x06},
{0x5a, 0x56},
{0x51, 0x1b},
{0x52, 0x04},
{0x53, 0x4a},
{0x54, 0x26},
{0x57, 0x75},
{0x58, 0x2b},
{0x5a, 0xd6},
{0x51, 0x28},
{0x52, 0x1e},
{0x53, 0x9e},
{0x54, 0x70},
{0x57, 0x50},
{0x58, 0x07},
{0x5c, 0x28},
{0xb0, 0xe0},
{0xb1, 0x90},
{0xb2, 0x80},
{0xb3, 0x4f},
{0xb4, 0x63},
{0xb4, 0xe3},
{0xb1, 0x90},
{0xb2, 0xa0},
{0x55, 0x00},
{0x56, 0x40},
{0x96, 0x50},
{0x9a, 0x30},
{0x6a, 0x81},
{0x23, 0x11},
{0xa0, 0xd0},
{0xa1, 0x31},
{0xa6, 0x04},
{0xa2, 0x0f},
{0xa3, 0x2b},
{0xa4, 0x08},
{0xa5, 0x25},
{0xa7, 0x9a},
{0xa8, 0x1c},
{0xa9, 0x11},
{0xaa, 0x16},
{0xab, 0x16},
{0xac, 0x3c},
{0xad, 0xf0},
{0xae, 0x57},
{0xc6, 0xaa},
{0xd2, 0x78},
{0xd0, 0xb4},
{0xd1, 0x00},
{0xc8, 0x10},
{0xc9, 0x12},
{0xd3, 0x09},
{0xd4, 0x2a},
{0xee, 0x4c},
{0x7e, 0xfa},
{0x74, 0xa3},
{0x78, 0x4e},
{0x60, 0xe7},
{0x61, 0xc8},
{0x6d, 0x70},
{0x1e, 0x09}, //0x39 0x09 修改图像正反
{0x98, 0x1a},
{0xbb, 0x20},
{0x09, 0x03},
};
static s32 BYD3901_set_output_size(u16 *width, u16 *height, u8 *freq);
static unsigned char wrBYD3901Reg(unsigned char regID, unsigned char regDat)
{
u8 ret = 1;
dev_ioctl(iic, IIC_IOCTL_START, 0);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, BYD3901_WRCMD)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
if (dev_ioctl(iic, IIC_IOCTL_TX, regID)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_STOP_BIT, regDat)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
exit:
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
return ret;
}
static unsigned char rdBYD3901Reg(unsigned char regID, unsigned char *regDat)
{
u8 ret = 1;
dev_ioctl(iic, IIC_IOCTL_START, 0);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, BYD3901_WRCMD)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_STOP_BIT, regID)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, BYD3901_RDCMD)) {
ret = 0;
printf("iic write err!!! line : %d \n", __LINE__);
goto exit;
}
delay(DELAY_TIME);
dev_ioctl(iic, IIC_IOCTL_RX_WITH_STOP_BIT, (u32)regDat);
exit:
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
return ret;
}
static void BYD3901_test_mode(void)
{
#ifdef CONFIG_AUTO_PRODUCTION_ENABLE
int prodct_jpeg_test_get(void);
if (prodct_jpeg_test_get()) {
wrBYD3901Reg(0xb9, 0x80);
}
#endif
}
static void BYD3901_config_SENSOR(u16 *width, u16 *height, u8 *format, u8 *frame_freq)
{
int i;
for (i = 0; i < sizeof(sensor_init_data) / sizeof(sensor_init_data[0]); i++) {
wrBYD3901Reg(sensor_init_data[i].reg, sensor_init_data[i].val);
}
BYD3901_test_mode();
#if BYD3901_OUT_CLK == 48
os_time_dly(8);//24M务必延时130ms以上 ,48M务必延时80ms以上
#else
os_time_dly(13);//24M务必延时130ms以上 ,48M务必延时80ms以上
#endif
*format = SEN_IN_FORMAT_UYVY;
*frame_freq = CONFIG_INPUT_FPS;
}
static s32 BYD3901_set_output_size(u16 *width, u16 *height, u8 *freq)
{
u16 liv_width = *width;
u16 liv_height = *height;
return 0;
}
static s32 BYD3901_power_ctl(u8 isp_dev, u8 is_work)
{
return 0;
}
static s32 BYD3901_ID_check(void)
{
int ret;
u16 pid = 0x00;
u8 id0, id1;
ret = rdBYD3901Reg(0xfc, &id0);
rdBYD3901Reg(0xfd, &id1);
pid = (u16)((id0 << 8) | id1);
printf("BYD3901 Sensor ID : 0x%x\n", pid);
if (pid != 0x3901) {
return -1;
}
return 0;
}
static void BYD3901_powerio_ctl(u32 _power_gpio, u32 on_off)
{
gpio_direction_output(_power_gpio, on_off);
}
static void BYD3901_reset(u8 isp_dev)
{
u8 res_io;
u8 powd_io;
u8 id = 0;
puts("BYD3901 reset\n");
if (isp_dev == ISP_DEV_0) {
res_io = (u8)BYD3901_reset_io[0];
powd_io = (u8)BYD3901_power_io[0];
} else {
res_io = (u8)BYD3901_reset_io[1];
powd_io = (u8)BYD3901_power_io[1];
}
if (powd_io != (u8) - 1) {
BYD3901_powerio_ctl((u32)powd_io, 0);
}
if (res_io != (u8) - 1) {
gpio_direction_output(res_io, 1);
gpio_direction_output(res_io, 0);
os_time_dly(1);
gpio_direction_output(res_io, 1);
}
}
static s32 BYD3901_check(u8 isp_dev, u32 _reset_gpio, u32 _power_gpio)
{
if (!iic) {
if (isp_dev == ISP_DEV_0) {
iic = dev_open("iic0", 0);
} else {
iic = dev_open("iic1", 0);
}
BYD3901_reset_io[isp_dev] = (u8)_reset_gpio;
BYD3901_power_io[isp_dev] = (u8)_power_gpio;
}
if (iic == NULL) {
printf("BYD3901 iic open err!!!\n\n");
return -1;
}
BYD3901_reset(isp_dev);
if (0 != BYD3901_ID_check()) {
dev_close(iic);
iic = NULL;
printf("-------not BYD3901------\n\n");
return -1;
}
printf("-------hello BYD3901------\n\n");
return 0;
}
static s32 BYD3901_init(u8 isp_dev, u16 *width, u16 *height, u8 *format, u8 *frame_freq)
{
puts("\n\n BYD3901 \n\n");
if (0 != BYD3901_check(isp_dev, 0, 0)) {
return -1;
}
BYD3901_config_SENSOR(width, height, format, frame_freq);
return 0;
}
void set_rev_sensor_BYD3901(u16 rev_flag)
{
if (!rev_flag) {
wrBYD3901Reg(0x1e, 0x30);
} else {
wrBYD3901Reg(0x1e, 0x00);
}
}
u16 BYD3901_dvp_rd_reg(u16 addr)
{
u8 val;
rdBYD3901Reg((u8)addr, &val);
return val;
}
void BYD3901_dvp_wr_reg(u16 addr, u16 val)
{
wrBYD3901Reg((u8)addr, (u8)val);
}
// *INDENT-OFF*
REGISTER_CAMERA1(BYD3901) = {
.logo = "BYD3901",
.isp_dev = ISP_DEV_NONE,
.in_format = SEN_IN_FORMAT_YUYV,
.mbus_type = SEN_MBUS_BT656,
#ifdef CONFIG_CPU_WL82
.mbus_config = SEN_MBUS_DATA_WIDTH_1B | SEN_MBUS_PCLK_SAMPLE_FALLING,
#else
.mbus_config = 0,
#endif
.sync_config = 0,//WL82/AC791才可以H-V SYNC互换,请留意
.fps = CONFIG_INPUT_FPS,
.out_fps = CONFIG_INPUT_FPS,
.sen_size = {BYD3901_DEVP_INPUT_W, BYD3901_DEVP_INPUT_H},
.cap_fps = CONFIG_INPUT_FPS,
.sen_cap_size = {BYD3901_DEVP_INPUT_W, BYD3901_DEVP_INPUT_H},
.ops = {
.avin_fps = NULL,
.avin_valid_signal = NULL,
.avin_mode_det = NULL,
.sensor_check = BYD3901_check,
.init = BYD3901_init,
.set_size_fps = BYD3901_set_output_size,
.power_ctrl = BYD3901_power_ctl,
.sleep = NULL,
.wakeup = NULL,
.write_reg = BYD3901_dvp_wr_reg,
.read_reg = BYD3901_dvp_rd_reg,
.set_sensor_reverse = set_rev_sensor_BYD3901,
}
};
#endif