mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-24 04:58:54 +00:00
1061 lines
31 KiB
C
1061 lines
31 KiB
C
/*
|
|
* Copyright (c) 2024-2025, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: matteo <duanmt@artinchip.com>
|
|
*/
|
|
|
|
#define LOG_TAG "N5"
|
|
|
|
#include <drivers/i2c.h>
|
|
#include <drivers/pin.h>
|
|
|
|
#include "aic_core.h"
|
|
#include "mpp_types.h"
|
|
#include "mpp_img_size.h"
|
|
#include "mpp_vin.h"
|
|
|
|
#include "drv_camera.h"
|
|
#include "camera_inner.h"
|
|
struct n5_dev *sensor;
|
|
/* Default format configuration of NextChip N5 */
|
|
#define N5_DFT_MODE AHD_1080P_25HZ
|
|
#define N5_DFT_WIDTH HD_720_WIDTH
|
|
#define N5_DFT_HEIGHT HD_720_HEIGHT
|
|
#define N5_DFT_BUS_TYPE MEDIA_BUS_BT656
|
|
#define N5_DFT_CODE MEDIA_BUS_FMT_UYVY8_2X8
|
|
#define N5_DFT_CHAN 0
|
|
#define N5_TEST_MODE 0
|
|
#define READ_ID_TEST 1
|
|
#define N5_USE_RES_DETECT 0
|
|
#define N5_I2C_SLAVE_ID 0x32
|
|
#define N5_CHIP_ID 0xE0
|
|
|
|
enum n5_output_channel {
|
|
//CVBS
|
|
N5_OutMode_SD_Input_1_Output_1 =0,
|
|
N5_OutMode_SD_Input_1_Output_2,
|
|
N5_OutMode_SD_Input_2_Output_1,
|
|
N5_OutMode_SD_Input_2_Output_2,
|
|
//720P
|
|
N5_OutMode_HD_Input_1_Output_1,
|
|
N5_OutMode_HD_Input_1_Output_2,
|
|
N5_OutMode_HD_Input_2_Output_1,
|
|
N5_OutMode_HD_Input_2_Output_2,
|
|
//1080P
|
|
N5_OutMode_FHD_Input_1_Output_1,
|
|
N5_OutMode_FHD_Input_1_Output_2,
|
|
N5_OutMode_FHD_Input_2_Output_1,
|
|
N5_OutMode_FHD_Input_2_Output_2
|
|
};
|
|
|
|
enum n5_mode {
|
|
AHD_CVBS_NTSC = 0,
|
|
AHD_CVBS_PAL,
|
|
AHD_720P_25HZ,
|
|
AHD_720P_30HZ,
|
|
AHD_1080P_25HZ,
|
|
AHD_1080P_30HZ,
|
|
|
|
AHD_NOSIGNAL = 0xFF
|
|
};
|
|
|
|
#define N5_BRIGHTNESS_REG 0x0C
|
|
#define N5_SATURATION_REG 0x3C
|
|
#define N5_HUE_REG 0x40
|
|
#define N5_CONTRAST_REG 0x10
|
|
|
|
struct n5_dev {
|
|
struct rt_device dev;
|
|
struct rt_i2c_bus_device *i2c;
|
|
u32 rst_pin;
|
|
u32 pwdn_pin;
|
|
|
|
struct mpp_video_fmt fmt;
|
|
|
|
bool on;
|
|
bool streaming;
|
|
};
|
|
|
|
static struct n5_dev g_n5_dev = {0};
|
|
|
|
static struct reg8_info n5_common_regs[] = {
|
|
{0xff, 0x00},
|
|
{0x00, 0x10},
|
|
{0x01, 0x10},
|
|
{0x18, 0x3f},
|
|
{0x19, 0x3f},
|
|
{0x22, 0x0b},
|
|
{0x23, 0x41},
|
|
{0x26, 0x0b},
|
|
{0x27, 0x41},
|
|
{0x54, 0x00},
|
|
{0xa0, 0x05},
|
|
{0xa1, 0x05},
|
|
|
|
//{0x3C, 0x80},
|
|
|
|
{0xff, 0x01},
|
|
{0x97, 0x00},
|
|
{0x97, 0x0f},
|
|
{0x7A, 0x0f},
|
|
{0xB3, 0x0f}, // inv hs/vs MPP1_INV bit0/MPP2_INV bit1 /MPP3_INV bit2/MPP4_INV bit3
|
|
|
|
//0x90: CH1 BT601 Signal Mode though MPP1 and MPP2 pins
|
|
//0xA0: CH2 BT601 Signal Mode though MPP1 and MPP2 pins
|
|
//{0xA8, 0x90}, //h/v0 sync enabled
|
|
//0x90: CH1 BT601 Signal Mode though MPP3 and MPP4 pins
|
|
//0xA0: CH2 BT601 Signal Mode though MPP3 and MPP4 pins
|
|
//{0xA9, 0x90}, //h/v1 sync enabled
|
|
//{0xBC, 0x10}, //h/v0 swap enabled
|
|
//{0xBD, 0x10},
|
|
//{0xBE, 0x10}, //h/v1 swap enabled
|
|
//{0xBF, 0x10},
|
|
|
|
{0xff, 0x05},
|
|
{0x00, 0xd0},
|
|
{0x01, 0x62},
|
|
{0x05, 0x04},
|
|
{0x08, 0x55},
|
|
{0x1b, 0x08},
|
|
{0x25, 0xdc},
|
|
{0x28, 0x80},
|
|
{0x2f, 0x00},
|
|
{0x30, 0xe0},
|
|
{0x31, 0x43},
|
|
{0x32, 0xa2},
|
|
{0x57, 0x00},
|
|
{0x58, 0x77},
|
|
{0x5b, 0x41},
|
|
{0x5c, 0x78},
|
|
{0x5f, 0x00},
|
|
{0x7b, 0x11},
|
|
{0x7c, 0x01},
|
|
{0x7d, 0x80},
|
|
{0x80, 0x00},
|
|
{0x90, 0x01},
|
|
{0xa9, 0x00},
|
|
{0xb8, 0x39},
|
|
{0xb9, 0x72},
|
|
{0xd1, 0x00},
|
|
{0xd5, 0x80},
|
|
|
|
{0xff, 0x06},
|
|
{0x00, 0xd0},
|
|
{0x01, 0x62},
|
|
{0x05, 0x04},
|
|
{0x08, 0x55},
|
|
{0x1b, 0x08},
|
|
{0x25, 0xdc},
|
|
{0x28, 0x80},
|
|
{0x2f, 0x00},
|
|
{0x30, 0xe0},
|
|
{0x31, 0x43},
|
|
{0x32, 0xa2},
|
|
{0x57, 0x00},
|
|
{0x58, 0x77},
|
|
{0x5b, 0x41},
|
|
{0x5c, 0x78},
|
|
{0x5f, 0x00},
|
|
{0x7b, 0x11},
|
|
{0x7c, 0x01},
|
|
{0x7d, 0x80},
|
|
{0x80, 0x00},
|
|
{0x90, 0x01},
|
|
{0xa9, 0x00},
|
|
{0xb8, 0x39},
|
|
{0xb9, 0x72},
|
|
{0xd1, 0x00},
|
|
{0xd5, 0x80},
|
|
|
|
{0xff, 0x09},
|
|
{0x50, 0x30},
|
|
{0x51, 0x6f},
|
|
{0x52, 0x67},
|
|
{0x53, 0x48},
|
|
{0x54, 0x30},
|
|
{0x55, 0x6f},
|
|
{0x56, 0x67},
|
|
{0x57, 0x48},
|
|
{0x96, 0x00},
|
|
{0x9e, 0x00},
|
|
{0xb6, 0x00},
|
|
{0xbe, 0x00},
|
|
|
|
{0xff, 0x0a},
|
|
{0x25, 0x10},
|
|
{0x27, 0x1e},
|
|
{0x30, 0xac},
|
|
{0x31, 0x78},
|
|
{0x32, 0x17},
|
|
{0x33, 0xc1},
|
|
{0x34, 0x40},
|
|
{0x35, 0x00},
|
|
{0x36, 0xc3},
|
|
{0x37, 0x0a},
|
|
{0x38, 0x00},
|
|
{0x39, 0x02},
|
|
{0x3a, 0x00},
|
|
{0x3b, 0xb2},
|
|
{0xa5, 0x10},
|
|
{0xa7, 0x1e},
|
|
{0xb0, 0xac},
|
|
{0xb1, 0x78},
|
|
{0xb2, 0x17},
|
|
{0xb3, 0xc1},
|
|
{0xb4, 0x40},
|
|
{0xb5, 0x00},
|
|
{0xb6, 0xc3},
|
|
{0xb7, 0x0a},
|
|
{0xb8, 0x00},
|
|
{0xb9, 0x02},
|
|
{0xba, 0x00},
|
|
{0xbb, 0xb2},
|
|
{0x77, 0x8F},
|
|
{0xF7, 0x8F},
|
|
|
|
// {0xff, 0x13},
|
|
// {0x07, 0x47},
|
|
// {0x12, 0x04},
|
|
// {0x1e, 0x1f},
|
|
// {0x1f, 0x27},
|
|
// {0x2e, 0x10},
|
|
// {0x2f, 0xc8},
|
|
// {0x30, 0x00},
|
|
// {0x31, 0xff},
|
|
// {0x32, 0x00},
|
|
// {0x33, 0x00},
|
|
// {0x3a, 0xff},
|
|
// {0x3b, 0xff},
|
|
// {0x3c, 0xff},
|
|
// {0x3d, 0xff},
|
|
// {0x3e, 0xff},
|
|
// {0x3f, 0x0f},
|
|
// {0x70, 0x00},
|
|
// {0x72, 0x05},
|
|
// {0x7A, 0xf0},
|
|
|
|
{0xff, 0x13},
|
|
{0x05, 0xA0},
|
|
{0x07, 0x47},
|
|
{0x0d, 0x40},
|
|
{0x0f, 0x40},
|
|
{0x12, 0x04},
|
|
{0x1e, 0x1f},
|
|
{0x1f, 0x27},
|
|
{0x2e, 0x10},
|
|
{0x2f, 0xc8},
|
|
{0x30, 0x00},
|
|
{0x31, 0xff},
|
|
{0x32, 0x00},
|
|
{0x33, 0x00},
|
|
{0x3a, 0x00},
|
|
{0x3b, 0x00},
|
|
{0x3c, 0x00},
|
|
{0x3d, 0x00},
|
|
{0x3e, 0x00},
|
|
{0x3f, 0x00},
|
|
{0x70, 0x00},
|
|
{0x72, 0x05},
|
|
{0x73, 0x23},
|
|
{0x7A, 0xf0},
|
|
|
|
|
|
{0xff, 0x00}, //8x8 color block test pattern
|
|
{0x78, 0xaa},//When No-Video, BackGround Color
|
|
#if N5_TEST_MODE
|
|
// Test mode
|
|
{0xff, 0x05},
|
|
{0x2c, 0x08},
|
|
{0x6a, 0x80},
|
|
{0xff, 0x06},
|
|
{0x2c, 0x08},
|
|
{0x6a, 0x80},
|
|
#endif
|
|
};
|
|
|
|
static int n5_write_reg(struct rt_i2c_bus_device *i2c, u8 reg, u8 val)
|
|
{
|
|
if (rt_i2c_write_reg(i2c, N5_I2C_SLAVE_ID, reg, &val, 1) != 1) {
|
|
LOG_E("%s: error: reg = 0x%x, val = 0x%x", __func__, reg, val);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static u8 n5_read_reg(struct rt_i2c_bus_device *i2c, u8 reg)
|
|
{
|
|
u8 val = 0;
|
|
|
|
if (rt_i2c_read_reg(i2c, N5_I2C_SLAVE_ID, reg, &val, 1) != 1) {
|
|
LOG_E("%s: error: reg = 0x%x, val = 0x%x", __func__, reg, val);
|
|
return -1;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
#if READ_ID_TEST
|
|
void nvp6158_dump_bank(int bank)
|
|
{
|
|
#if 1
|
|
u32 reg_addr=0;
|
|
u32 reg_value2[16];
|
|
int j,i;
|
|
|
|
printf("--------------------[BANK = 0x%02x]----------------------\n",bank);
|
|
printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
|
|
printf("----------------------------------------------------\n");
|
|
|
|
n5_write_reg(sensor->i2c, 0xFF, bank);
|
|
|
|
for(j = 0 ; j < 16; j++) {
|
|
for(i = 0; i < 16; i++) {
|
|
reg_addr = i+(0x10*j);
|
|
reg_value2[i] = n5_read_reg(sensor->i2c, reg_addr);
|
|
if (i==15) {
|
|
printf("%02x | %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x ", j*0x10, \
|
|
reg_value2[0], reg_value2[1], reg_value2[2], reg_value2[3], reg_value2[4], reg_value2[5], reg_value2[6], reg_value2[7], \
|
|
reg_value2[8], reg_value2[9], reg_value2[10], reg_value2[11], reg_value2[12], reg_value2[13], reg_value2[14], reg_value2[15]);
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
}
|
|
#endif
|
|
static void n5_selchannel_portmode(struct n5_dev *sensor, u8 ch, u8 MuxMode)
|
|
{
|
|
u8 val_1xc8, val_1xca, val_0x54;
|
|
u8 clk_freq_array[4] = {0x89,0x09,0x49,0x69}; //clk_freq: 0~3:37.125M/74.25M/148.5M/297M
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
val_0x54 = n5_read_reg(sensor->i2c, 0x54);
|
|
val_0x54 &= 0xFE;
|
|
n5_write_reg(sensor->i2c, 0x54, val_0x54);
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
val_1xc8 = n5_read_reg(sensor->i2c, 0xc8);
|
|
|
|
n5_write_reg(sensor->i2c, 0xA0, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xA1, 0x00);
|
|
|
|
switch(MuxMode)
|
|
{
|
|
// CVBS
|
|
case N5_OutMode_SD_Input_1_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[0]);
|
|
break;
|
|
|
|
case N5_OutMode_SD_Input_1_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[0]);
|
|
break;
|
|
|
|
case N5_OutMode_SD_Input_2_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[0]);
|
|
break;
|
|
|
|
case N5_OutMode_SD_Input_2_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[0]);
|
|
break;
|
|
|
|
//720P
|
|
case N5_OutMode_HD_Input_1_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[1]);
|
|
break;
|
|
|
|
case N5_OutMode_HD_Input_1_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[1]);
|
|
break;
|
|
|
|
case N5_OutMode_HD_Input_2_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[1]);
|
|
break;
|
|
|
|
case N5_OutMode_HD_Input_2_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[1]);
|
|
break;
|
|
|
|
// 1080P
|
|
case N5_OutMode_FHD_Input_1_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[2]);
|
|
break;
|
|
|
|
case N5_OutMode_FHD_Input_1_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[2]);
|
|
break;
|
|
|
|
case N5_OutMode_FHD_Input_2_Output_1:
|
|
n5_write_reg(sensor->i2c, 0xC0, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[2]);
|
|
break;
|
|
|
|
case N5_OutMode_FHD_Input_2_Output_2:
|
|
n5_write_reg(sensor->i2c, 0xC2, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xCC + ch, clk_freq_array[2]);
|
|
break;
|
|
}
|
|
val_1xc8 &= (1 == ch? 0x0F : 0xF0);
|
|
n5_write_reg(sensor->i2c, 0xC8, val_1xc8);
|
|
val_1xca = n5_read_reg(sensor->i2c, 0xCA);
|
|
val_1xca |= (0x11 << ch); //enable port
|
|
n5_write_reg(sensor->i2c, 0xCA, val_1xca);
|
|
}
|
|
|
|
static void n5_set_chn_720h_ntsc(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08 + ch, 0xa0);
|
|
n5_write_reg(sensor->i2c, 0x34 + ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81 + ch, 0x60);
|
|
n5_write_reg(sensor->i2c, 0x85 + ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54) | (0x10 << ch));
|
|
n5_write_reg(sensor->i2c, 0x64 + ch, 0xa1);
|
|
n5_write_reg(sensor->i2c, 0x89 + ch, 0x10);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x2f);
|
|
n5_write_reg(sensor->i2c, 0x30 + ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0 + ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84 + ch, 0x06);
|
|
n5_write_reg(sensor->i2c, 0x8c + ch, 0x86);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed) & (~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05 + ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xdc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x47, 0x04);
|
|
n5_write_reg(sensor->i2c, 0x50, 0x84);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0xb9);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c + ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10 + ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40 + ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44 + ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48 + ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C + ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50 + ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18 + ch, 0x08); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58 + ch, 0x90); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c + ch, 0xbe); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05 + ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x90);
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_set_chn_720h_pal(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08 + ch, 0xdd);
|
|
n5_write_reg(sensor->i2c, 0x34 + ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81 + ch, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x85 + ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54)&(~(0x10<<ch)));
|
|
n5_write_reg(sensor->i2c, 0x64 + ch, 0xa0);
|
|
n5_write_reg(sensor->i2c, 0x89 + ch, 0x10);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x2e);
|
|
n5_write_reg(sensor->i2c, 0x30 + ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0 + ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84 + ch, 0x06);
|
|
n5_write_reg(sensor->i2c, 0x8c + ch, 0x86);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed)&(~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05 + ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xcc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x47, 0x04);
|
|
n5_write_reg(sensor->i2c, 0x50, 0x84);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x00);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0xb9);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c + ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10 + ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40 + ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44 + ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48 + ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C + ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50 + ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18 + ch, 0x3f); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58 + ch, 0x80); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c + ch, 0xbe); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05 + ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x90);
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_set_chn_720p_30(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x34+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81+ch, 0x06);
|
|
n5_write_reg(sensor->i2c, 0x85+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54)&(~(0x10<<ch)));
|
|
n5_write_reg(sensor->i2c, 0x64+ch, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x89+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x30+ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0+ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84+ch, 0x08);
|
|
n5_write_reg(sensor->i2c, 0x8c+ch, 0x08);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed)&(~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xdc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0xa8);
|
|
n5_write_reg(sensor->i2c, 0x47, 0xee);
|
|
n5_write_reg(sensor->i2c, 0x50, 0xc6);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0x39);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c+ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10+ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40+ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44+ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48+ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C+ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50+ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18+ch, 0x3f); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58+ch, 0x80); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c+ch, 0x80); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_set_chn_720p_25(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x34+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81+ch, 0x07);
|
|
n5_write_reg(sensor->i2c, 0x85+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54)&(~(0x10<<ch)));
|
|
n5_write_reg(sensor->i2c, 0x64+ch, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x89+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x30+ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0+ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84+ch, 0x08);
|
|
n5_write_reg(sensor->i2c, 0x8c+ch, 0x08);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed)&(~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xdc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0xa8);
|
|
n5_write_reg(sensor->i2c, 0x47, 0xee);
|
|
n5_write_reg(sensor->i2c, 0x50, 0xc6);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0x39);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c+ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10+ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40+ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44+ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48+ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C+ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50+ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18+ch, 0x3f); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58+ch, 0x80); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c+ch, 0x80); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_set_chn_1080p_30(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x34+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81+ch, 0x02);
|
|
n5_write_reg(sensor->i2c, 0x85+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54)&(~(0x10<<ch)));
|
|
n5_write_reg(sensor->i2c, 0x64+ch, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x89+ch, 0x10);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x30+ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0+ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x8c+ch, 0x40);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed)&(~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xdc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0xa8);
|
|
n5_write_reg(sensor->i2c, 0x47, 0xee);
|
|
n5_write_reg(sensor->i2c, 0x50, 0xc6);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0x39);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c+ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10+ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40+ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44+ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48+ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C+ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50+ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18+ch, 0x3f); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58+ch, 0x82); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c+ch, 0x80); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_set_chn_1080p_25(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x08+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x34+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x81+ch, 0x03);
|
|
n5_write_reg(sensor->i2c, 0x85+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x54, n5_read_reg(sensor->i2c, 0x54)&(~(0x10<<ch)));
|
|
n5_write_reg(sensor->i2c, 0x64+ch, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x89+ch, 0x10);
|
|
n5_write_reg(sensor->i2c, ch+0x8e, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x30+ch, 0x12);
|
|
n5_write_reg(sensor->i2c, 0xa0+ch, 0x05);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x01);
|
|
n5_write_reg(sensor->i2c, 0x84+ch, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x8c+ch, 0x40);
|
|
n5_write_reg(sensor->i2c, 0xed, n5_read_reg(sensor->i2c, 0xed)&(~(0x01<<ch)));
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x25, 0xdc);
|
|
n5_write_reg(sensor->i2c, 0x2b, 0xa8);
|
|
n5_write_reg(sensor->i2c, 0x47, 0xee);
|
|
n5_write_reg(sensor->i2c, 0x50, 0xc6);
|
|
n5_write_reg(sensor->i2c, 0x69, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x7b, 0x11);
|
|
n5_write_reg(sensor->i2c, 0xb8, 0x39);
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x0c+ch, 0x00); //bright
|
|
n5_write_reg(sensor->i2c, 0x10+ch, 0x80); //contrast
|
|
n5_write_reg(sensor->i2c, 0x40+ch, 0x00); //hue
|
|
n5_write_reg(sensor->i2c, 0x44+ch, 0x00); //uGain
|
|
n5_write_reg(sensor->i2c, 0x48+ch, 0x10); //vGain
|
|
n5_write_reg(sensor->i2c, 0x4C+ch, 0x00); //uoffset
|
|
n5_write_reg(sensor->i2c, 0x50+ch, 0x00); //voffset
|
|
n5_write_reg(sensor->i2c, 0x18+ch, 0x3f); //Y_Peak
|
|
n5_write_reg(sensor->i2c, 0x58+ch, 0x82); //H_Delay
|
|
n5_write_reg(sensor->i2c, 0x5c+ch, 0x80); //V_Delay
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0x20, 0x80); //0x84//0xA0//0x84 //0x70 // black level
|
|
n5_write_reg(sensor->i2c, 0x28, 0x80);
|
|
n5_write_reg(sensor->i2c, 0x58, 0x70);
|
|
n5_write_reg(sensor->i2c, 0x5C, 0x78);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x62);
|
|
}
|
|
|
|
static void n5_setoutchannel_mode(struct n5_dev *sensor, u8 ch, enum n5_mode mode)
|
|
{
|
|
switch (mode) {
|
|
case AHD_CVBS_NTSC:
|
|
LOG_I(" >>> NTSC");
|
|
n5_set_chn_720h_ntsc(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_SD_Input_2_Output_1:N5_OutMode_SD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_CVBS_PAL:
|
|
LOG_I(" >>> PAL");
|
|
n5_set_chn_720h_pal(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_SD_Input_2_Output_1:N5_OutMode_SD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_720P_25HZ:
|
|
LOG_I(" >>> AHD_720P_25PFS");
|
|
n5_set_chn_720p_25(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_HD_Input_2_Output_1:N5_OutMode_HD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_NOSIGNAL:
|
|
LOG_I(" >>> AHD_720P_25PFS");
|
|
n5_set_chn_720p_25(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_HD_Input_2_Output_1:N5_OutMode_HD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_720P_30HZ:
|
|
LOG_I(" >>> AHD_720P_30PFS");
|
|
n5_set_chn_720p_30(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_HD_Input_2_Output_1:N5_OutMode_HD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_1080P_25HZ:
|
|
LOG_I(" >>> AHD_1080P_25PFS");
|
|
n5_set_chn_1080p_25(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_FHD_Input_2_Output_1:N5_OutMode_FHD_Input_1_Output_1);
|
|
break;
|
|
|
|
case AHD_1080P_30HZ:
|
|
LOG_I(" >>> AHD_1080P_30PFS");
|
|
n5_set_chn_1080p_30(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_FHD_Input_2_Output_1:N5_OutMode_FHD_Input_1_Output_1);
|
|
break;
|
|
|
|
default:
|
|
LOG_I(" >>> Default AHD_1080P_25PFS");
|
|
n5_set_chn_1080p_25(sensor, ch);
|
|
n5_selchannel_portmode(sensor, 0, ch?N5_OutMode_FHD_Input_2_Output_1:N5_OutMode_FHD_Input_1_Output_1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void n5_auto_detect_mode(struct n5_dev *sensor)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x13);
|
|
n5_write_reg(sensor->i2c, 0x30, 0x7f);
|
|
n5_write_reg(sensor->i2c, 0x70, 0x30);
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
n5_write_reg(sensor->i2c, 0x00, 0x18);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x18);
|
|
n5_write_reg(sensor->i2c, 0x02, 0x18);
|
|
n5_write_reg(sensor->i2c, 0x03, 0x18);
|
|
n5_write_reg(sensor->i2c, 0x00, 0x10);
|
|
n5_write_reg(sensor->i2c, 0x01, 0x10);
|
|
n5_write_reg(sensor->i2c, 0x02, 0x10);
|
|
n5_write_reg(sensor->i2c, 0x03, 0x10);
|
|
}
|
|
|
|
static void n5_video_format_unknown(struct n5_dev *sensor, u32 ch)
|
|
{
|
|
n5_setoutchannel_mode(sensor, ch, AHD_1080P_25HZ);
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05+ch);
|
|
n5_write_reg(sensor->i2c, 0xB8, 0xB8);
|
|
n5_write_reg(sensor->i2c, 0xff, 0x13);
|
|
n5_write_reg(sensor->i2c, 0x70, n5_read_reg(sensor->i2c, 0x70)&(~(0x01<<ch)));
|
|
}
|
|
|
|
static void n5_init_common(struct n5_dev *sensor)
|
|
{
|
|
struct reg8_info *info = n5_common_regs;
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(n5_common_regs); i++, info++)
|
|
n5_write_reg(sensor->i2c, info->reg, info->val);
|
|
}
|
|
#if N5_USE_RES_DETECT
|
|
static u8 n5_resolutiondetect(struct n5_dev *sensor, u8 ch)
|
|
{
|
|
u8 detCamera = 0;
|
|
u8 detFormat = 0;
|
|
|
|
n5_write_reg(sensor->i2c, 0xff, 0x00);
|
|
detCamera = (n5_read_reg(sensor->i2c, 0xa8) & (0x01 << ch));
|
|
LOG_I("detCamera = %x",detCamera);
|
|
if (detCamera == 0x00) {
|
|
n5_write_reg(sensor->i2c, 0xff, 0x05 + ch%2);
|
|
detFormat = n5_read_reg(sensor->i2c, 0xf0);
|
|
LOG_I("detFormat = %x", detFormat);
|
|
|
|
if (detFormat == 0x00) // NTSC
|
|
{
|
|
LOG_I("AHD_CVBS_NTSC");
|
|
return AHD_CVBS_NTSC;
|
|
}
|
|
else if (detFormat == 0x10) //PAL
|
|
{
|
|
LOG_I("AHD_CVBS_PAL");
|
|
return AHD_CVBS_PAL;
|
|
}
|
|
else if (detFormat == 0x21) //720p_25fps
|
|
{
|
|
LOG_I("AHD_720P_25HZ");
|
|
return AHD_720P_25HZ;
|
|
}
|
|
else if (detFormat == 0x20) //720P_30fps
|
|
{
|
|
LOG_I("AHD_720P_30HZ");
|
|
return AHD_720P_30HZ;
|
|
}
|
|
else if (detFormat == 0x31) // 1080P_25fps
|
|
{
|
|
LOG_I("AHD_1080P_25HZ");
|
|
return AHD_1080P_25HZ;
|
|
}
|
|
else if (detFormat == 0x30) //1080P_30fps
|
|
{
|
|
LOG_I("AHD_1080P_30HZ");
|
|
return AHD_1080P_30HZ;
|
|
}
|
|
} else {
|
|
LOG_I("No camera found");
|
|
}
|
|
return AHD_NOSIGNAL;
|
|
}
|
|
#endif
|
|
static bool n5_is_open(struct n5_dev *sensor)
|
|
{
|
|
return sensor->on;
|
|
}
|
|
|
|
static void n5_power_on(struct n5_dev *sensor)
|
|
{
|
|
if (sensor->on)
|
|
return;
|
|
|
|
camera_pin_set_high(sensor->rst_pin);
|
|
aicos_msleep(300);
|
|
camera_pin_set_low(sensor->rst_pin);
|
|
aicos_msleep(300);
|
|
camera_pin_set_high(sensor->rst_pin);
|
|
aicos_msleep(300);
|
|
|
|
LOG_I("Power on");
|
|
sensor->on = true;
|
|
}
|
|
|
|
static void n5_power_off(struct n5_dev *sensor)
|
|
{
|
|
if (!sensor->on)
|
|
return;
|
|
|
|
if (sensor->rst_pin)
|
|
camera_pin_set_low(sensor->rst_pin);
|
|
|
|
LOG_I("Power off");
|
|
sensor->on = false;
|
|
}
|
|
|
|
static int n5_probe(struct n5_dev *sensor)
|
|
{
|
|
u8 id = 0;
|
|
int Chn = 0;
|
|
|
|
n5_power_on(sensor);
|
|
n5_write_reg(sensor->i2c, 0xff, 0);
|
|
id = n5_read_reg(sensor->i2c, 0xf4);
|
|
if (id != N5_CHIP_ID) {
|
|
LOG_E("Invalid chip ID: %02x\n", id);
|
|
return -1;
|
|
}
|
|
|
|
n5_init_common(sensor);
|
|
n5_video_format_unknown(sensor, 0);
|
|
n5_video_format_unknown(sensor, 1);
|
|
n5_auto_detect_mode(sensor);
|
|
for(Chn = 0; Chn < 2; Chn++)
|
|
{
|
|
n5_write_reg(sensor->i2c, 0xff, 0x13);
|
|
n5_write_reg(sensor->i2c, 0x70, n5_read_reg(sensor->i2c, 0x70)|(0x01<<Chn));
|
|
n5_write_reg(sensor->i2c, 0x71, n5_read_reg(sensor->i2c, 0x71)|(0x01<<Chn));
|
|
n5_set_chn_1080p_25(sensor, Chn);
|
|
}
|
|
#if N5_USE_RES_DETECT
|
|
if (n5_resolutiondetect(sensor, N5_DFT_CHAN) == AHD_NOSIGNAL)
|
|
return -1;
|
|
#endif
|
|
aicos_msleep(200);
|
|
n5_selchannel_portmode(sensor, 0, N5_OutMode_FHD_Input_1_Output_1);
|
|
aic_mdelay(200);
|
|
return 0;
|
|
}
|
|
|
|
static rt_err_t n5_init(rt_device_t dev)
|
|
{
|
|
struct n5_dev *sensor = (struct n5_dev *)dev;
|
|
|
|
sensor->i2c = camera_i2c_get();
|
|
if (!sensor->i2c)
|
|
return -RT_EINVAL;
|
|
|
|
sensor->fmt.code = N5_DFT_CODE;
|
|
sensor->fmt.width = N5_DFT_WIDTH;
|
|
sensor->fmt.height = N5_DFT_HEIGHT;
|
|
sensor->fmt.bus_type = N5_DFT_BUS_TYPE;
|
|
sensor->fmt.flags = MEDIA_SIGNAL_HSYNC_ACTIVE_HIGH |
|
|
MEDIA_SIGNAL_VSYNC_ACTIVE_HIGH |
|
|
MEDIA_SIGNAL_PCLK_SAMPLE_FALLING;//|
|
|
//MEDIA_SIGNAL_INTERLACED_MODE;
|
|
|
|
sensor->rst_pin = camera_rst_pin_get();
|
|
if (!sensor->rst_pin)
|
|
return -RT_EINVAL;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t n5_open(rt_device_t dev, rt_uint16_t oflag)
|
|
{
|
|
sensor = (struct n5_dev *)dev;
|
|
if (n5_is_open(sensor))
|
|
return RT_EOK;
|
|
|
|
if (n5_probe(sensor))
|
|
return -RT_ERROR;
|
|
|
|
LOG_I("Open N5");
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t n5_close(rt_device_t dev)
|
|
{
|
|
struct n5_dev *sensor = (struct n5_dev *)dev;
|
|
|
|
if (!n5_is_open(sensor))
|
|
return -RT_ERROR;
|
|
|
|
n5_power_off(sensor);
|
|
LOG_D("Close N5");
|
|
return RT_EOK;
|
|
}
|
|
|
|
static int n5_get_fmt(struct n5_dev *sensor, struct mpp_video_fmt *cfg)
|
|
{
|
|
cfg->code = sensor->fmt.code;
|
|
cfg->width = sensor->fmt.width;
|
|
cfg->height = sensor->fmt.height;
|
|
cfg->flags = sensor->fmt.flags;
|
|
cfg->bus_type = sensor->fmt.bus_type;
|
|
return RT_EOK;
|
|
}
|
|
|
|
static int n5_start(rt_device_t dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_stop(rt_device_t dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_pause(rt_device_t dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_resume(rt_device_t dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_set_brightness(struct n5_dev *sensor, u32 percent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_set_saturation(struct n5_dev *sensor, u32 percent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_set_hue(struct n5_dev *sensor, u32 percent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int n5_set_contrast(struct n5_dev *sensor, u32 percent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static rt_err_t n5_control(rt_device_t dev, int cmd, void *args)
|
|
{
|
|
struct n5_dev *sensor = (struct n5_dev *)dev;
|
|
|
|
switch (cmd) {
|
|
case CAMERA_CMD_START:
|
|
return n5_start(dev);
|
|
case CAMERA_CMD_STOP:
|
|
return n5_stop(dev);
|
|
case CAMERA_CMD_PAUSE:
|
|
return n5_pause(dev);
|
|
case CAMERA_CMD_RESUME:
|
|
return n5_resume(dev);
|
|
case CAMERA_CMD_GET_FMT:
|
|
return n5_get_fmt(sensor, (struct mpp_video_fmt *)args);
|
|
case CAMERA_CMD_SET_CONTRAST:
|
|
return n5_set_contrast(sensor, *(u32 *)args);
|
|
case CAMERA_CMD_SET_BRIGHTNESS:
|
|
return n5_set_brightness(sensor, *(u32 *)args);
|
|
case CAMERA_CMD_SET_HUE:
|
|
return n5_set_hue(sensor, *(u32 *)args);
|
|
case CAMERA_CMD_SET_SATURATION:
|
|
return n5_set_saturation(sensor, *(u32 *)args);
|
|
default:
|
|
LOG_I("Unsupported cmd: 0x%x", cmd);
|
|
return -RT_EINVAL;
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
static const struct rt_device_ops n5_ops =
|
|
{
|
|
.init = n5_init,
|
|
.open = n5_open,
|
|
.close = n5_close,
|
|
.control = n5_control,
|
|
};
|
|
#endif
|
|
|
|
int rt_hw_n5_init(void)
|
|
{
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
g_n5_dev.dev.ops = &n5_ops;
|
|
#else
|
|
g_n5_dev.dev.init = n5_init;
|
|
g_n5_dev.dev.open = n5_open;
|
|
g_n5_dev.dev.close = n5_close;
|
|
g_n5_dev.dev.control = n5_control;
|
|
#endif
|
|
g_n5_dev.dev.type = RT_Device_Class_CAMERA;
|
|
|
|
rt_device_register(&g_n5_dev.dev, CAMERA_DEV_NAME, 0);
|
|
return 0;
|
|
}
|
|
INIT_DEVICE_EXPORT(rt_hw_n5_init);
|