/* * A V4L2 driver for ov5640 cameras. * */ #include #include #include #include #include #include #include #include #include #include #include #include "camera.h" #include "sensor_helper.h" MODULE_AUTHOR("raymonxiu"); MODULE_DESCRIPTION("A low-level driver for ov5640_video1 sensors"); MODULE_LICENSE("GPL"); #define AF_WIN_NEW_COORD #define DEV_DBG_EN 0 #if (DEV_DBG_EN == 1) #define sensor_dbg(x, arg...) printk("[ov5640_video1]"x, ##arg) #else #define sensor_dbg(x, arg...) do { } while (0) #endif #define sensor_err(x, arg...) printk("[ov5640_video1]"x, ##arg) #define sensor_print(x, arg...) printk("[ov5640_video1]"x, ##arg) #define CAP_BDG 0 #if (CAP_BDG == 1) #define sensor_cap_dbg(x, arg...) printk("[OV5640_CAP_DBG]"x, ##arg) #else #define sensor_cap_dbg(x, arg...) do { } while (0) #endif #define LOG_ERR_RET(x) { \ int ret; \ ret = x; \ if (ret < 0) {\ sensor_err("error at %s\n", __func__); \ return ret; \ } \ } #define MCLK (24*1000*1000) static int MCLK_DIV = 1; #ifdef CONFIG_ARCH_SUN9IW1P1 int A80_VERSION; #endif #define VREF_POL V4L2_MBUS_VSYNC_ACTIVE_HIGH #define HREF_POL V4L2_MBUS_HSYNC_ACTIVE_HIGH #define CLK_POL V4L2_MBUS_PCLK_SAMPLE_FALLING #define V4L2_IDENT_SENSOR 0x5640 #define SENSOR_NAME "ov5640_video1" #ifdef _FLASH_FUNC_ #include "../flash_light/flash.h" static unsigned int to_flash; static unsigned int flash_auto_level = 0x1c; #endif #define CONTINUEOUS_AF #define DENOISE_LV_AUTO #define SHARPNESS 0x18 #ifndef DENOISE_LV_AUTO #define DENOISE_LV 0x8 #endif #define AE_CW 1 static unsigned int night_mode; static unsigned int Nfrms = 1; static unsigned int cap_manual_gain = 0x10; #define CAP_GAIN_CAL 0 #define CAP_MULTI_FRAMES #ifdef CAP_MULTI_FRAMES #define MAX_FRM_CAP 4 #else #define MAX_FRM_CAP 1 #endif /* * Our nominal (default) frame rate. */ #define SENSOR_FRAME_RATE 30 /* * The ov5640 sits on i2c with ID 0x78 */ #define I2C_ADDR 0x78 static struct v4l2_subdev *glb_sd; /* * Information we maintain about a known sensor. */ struct sensor_format_struct; /* coming later */ struct cfg_array { /* coming later */ struct regval_list *regs; int size; }; static inline struct sensor_info *to_state(struct v4l2_subdev *sd) { return container_of(sd, struct sensor_info, sd); } /* * The default register settings * */ static struct regval_list sensor_default_regs[] = { {0x3103, 0x11}, {0x3008, 0x82}, {REG_DLY, 0x1e}, {0x3008, 0x42}, {0x3103, 0x03}, {0x3017, 0x00}, {0x3018, 0x00}, {0x3034, 0x18}, {0x3035, 0x21}, {0x3036, 0x46}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {0x3630, 0x36}, {0x3631, 0x0e}, {0x3632, 0xe2}, {0x3633, 0x12}, {0x3621, 0xe0}, {0x3704, 0xa0}, {0x3703, 0x5a}, {0x3715, 0x78}, {0x3717, 0x01}, {0x370b, 0x60}, {0x3705, 0x1a}, {0x3905, 0x02}, {0x3906, 0x10}, {0x3901, 0x0a}, {0x3731, 0x12}, {0x3600, 0x08}, {0x3601, 0x33}, {0x3620, 0x52}, {0x371b, 0x20}, {0x471c, 0x50}, {0x3a13, 0x43}, {0x3a18, 0x00}, {0x3a19, 0x88}, {0x3635, 0x13}, {0x3636, 0x03}, {0x3634, 0x40}, {0x3622, 0x01}, {0x3c01, 0x34}, {0x3c04, 0x28}, {0x3c05, 0x98}, {0x3c06, 0x00}, {0x3c07, 0x08}, {0x3c08, 0x00}, {0x3c09, 0x1c}, {0x3c0a, 0x9c}, {0x3c0b, 0x40}, {0x3814, 0x31}, {0x3815, 0x31}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x04}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9b}, {0x3808, 0x02}, {0x3809, 0x80}, {0x380a, 0x01}, {0x380b, 0xe0}, {0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, {0x380f, 0xd8}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x06}, {0x3618, 0x00}, {0x3612, 0x29}, {0x3708, 0x64}, {0x3709, 0x52}, {0x370c, 0x03}, {0x3a00, 0x78}, {0x3a02, 0x03}, {0x3a03, 0xd8}, {0x3a08, 0x01}, {0x3a09, 0x27}, {0x3a0a, 0x00}, {0x3a0b, 0xf6}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, {0x3a14, 0x03}, {0x3a15, 0xd8}, {0x4001, 0x02}, {0x4004, 0x02}, {0x3000, 0x00}, {0x3002, 0x1c}, {0x3004, 0xff}, {0x3006, 0xc3}, {0x300e, 0x58}, {0x302c, 0x42}, {0x4300, 0x30}, {0x501f, 0x00}, {0x4713, 0x03}, {0x4407, 0x04}, {0x440e, 0x00}, {0x460b, 0x35}, {0x460c, 0x20}, {0x4837, 0x22}, {0x5000, 0xa7}, {0x5001, 0xa3}, {0x4740, 0x21}, {0x3406, 0x00}, {0x5180, 0xff}, {0x5181, 0xf2}, {0x5182, 0x00}, {0x5183, 0x14}, {0x5184, 0x25}, {0x5185, 0x24}, {0x5186, 0x16}, {0x5187, 0x16}, {0x5188, 0x16}, {0x5189, 0x6e}, {0x518a, 0x68}, {0x518b, 0xe0}, {0x518c, 0xb2}, {0x518d, 0x42}, {0x518e, 0x3e}, {0x518f, 0x4c}, {0x5190, 0x56}, {0x5191, 0xf8}, {0x5192, 0x04}, {0x5193, 0x70}, {0x5194, 0xf0}, {0x5195, 0xf0}, {0x5196, 0x03}, {0x5197, 0x01}, {0x5198, 0x04}, {0x5199, 0x12}, {0x519a, 0x04}, {0x519b, 0x00}, {0x519c, 0x06}, {0x519d, 0x82}, {0x519e, 0x38}, {0x5381, 0x1e}, {0x5382, 0x5b}, {0x5383, 0x14}, {0x5384, 0x05}, {0x5385, 0x77}, {0x5386, 0x7c}, {0x5387, 0x72}, {0x5388, 0x58}, {0x5389, 0x1a}, {0x538a, 0x01}, {0x538b, 0x98}, {0x5300, 0x08}, {0x5301, 0x30}, {0x5302, 0x30}, {0x5303, 0x10}, {0x5308, 0x25}, {0x5304, 0x08}, {0x5305, 0x30}, {0x5306, 0x1c}, {0x5307, 0x2c}, {0x5309, 0x08}, {0x530a, 0x30}, {0x530b, 0x04}, {0x530c, 0x06}, {0x5480, 0x01}, {0x5481, 0x06}, {0x5482, 0x12}, {0x5483, 0x1e}, {0x5484, 0x4a}, {0x5485, 0x58}, {0x5486, 0x65}, {0x5487, 0x72}, {0x5488, 0x7d}, {0x5489, 0x88}, {0x548a, 0x92}, {0x548b, 0xa3}, {0x548c, 0xb2}, {0x548d, 0xc8}, {0x548e, 0xdd}, {0x548f, 0xf0}, {0x5490, 0x15}, {0x5580, 0x06}, {0x5583, 0x40}, {0x5584, 0x10}, {0x5589, 0x10}, {0x558a, 0x00}, {0x558b, 0xf8}, {0x501d, 0x40}, {0x5800, 0x15}, {0x5801, 0x10}, {0x5802, 0x0D}, {0x5803, 0x0D}, {0x5804, 0x0F}, {0x5805, 0x15}, {0x5806, 0x0A}, {0x5807, 0x07}, {0x5808, 0x05}, {0x5809, 0x05}, {0x580A, 0x07}, {0x580B, 0x0B}, {0x580C, 0x07}, {0x580D, 0x03}, {0x580E, 0x01}, {0x580F, 0x01}, {0x5810, 0x03}, {0x5811, 0x07}, {0x5812, 0x07}, {0x5813, 0x03}, {0x5814, 0x01}, {0x5815, 0x01}, {0x5816, 0x03}, {0x5817, 0x06}, {0x5818, 0x0D}, {0x5819, 0x08}, {0x581A, 0x06}, {0x581B, 0x06}, {0x581C, 0x07}, {0x581D, 0x0B}, {0x581E, 0x14}, {0x581F, 0x13}, {0x5820, 0x0E}, {0x5821, 0x0E}, {0x5822, 0x12}, {0x5823, 0x12}, {0x5824, 0x46}, {0x5825, 0x26}, {0x5826, 0x06}, {0x5827, 0x46}, {0x5828, 0x44}, {0x5829, 0x26}, {0x582A, 0x24}, {0x582B, 0x42}, {0x582C, 0x24}, {0x582D, 0x46}, {0x582E, 0x24}, {0x582F, 0x42}, {0x5830, 0x60}, {0x5831, 0x42}, {0x5832, 0x24}, {0x5833, 0x26}, {0x5834, 0x24}, {0x5835, 0x24}, {0x5836, 0x24}, {0x5837, 0x46}, {0x5838, 0x44}, {0x5839, 0x46}, {0x583A, 0x26}, {0x583B, 0x48}, {0x583C, 0x44}, {0x583D, 0xBF}, {0x3a0f, 0x30}, {0x3a10, 0x28}, {0x3a1b, 0x30}, {0x3a1e, 0x26}, {0x3a11, 0x60}, {0x3a1f, 0x14}, {0x5025, 0x00}, {0x3031, 0x08}, {0x503d, 0x00}, {0x3008, 0x02}, }; static struct regval_list sensor_qsxga_regs[] = { {0x3820, 0x40}, {0x3821, 0x06}, {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x21}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x0a}, {0x3809, 0x20}, {0x380a, 0x07}, {0x380b, 0x90}, {0x380c, 0x0b}, {0x380d, 0x1c}, {0x380e, 0x07}, {0x380f, 0xb0}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #else {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #endif {0x3503, 0x07}, {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0xc5}, {0x4005, 0x1a}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x4004, 0x06}, {0x4837, 0x2c}, {0x5001, 0xa3}, {0x302c, 0x42}, }; static struct regval_list sensor_qxga_regs[] = { {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x21}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x08}, {0x3809, 0x00}, {0x380a, 0x06}, {0x380b, 0x00}, {0x380c, 0x0b}, {0x380d, 0x1c}, {0x380e, 0x07}, {0x380f, 0xb0}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #else {0x3a08, 0x00}, {0x3a09, 0x49}, {0x3a0a, 0x00}, {0x3a0b, 0x3d}, {0x3a0e, 0x1a}, {0x3a0d, 0x20}, #endif {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0xc5}, {0x4005, 0x1a}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x4004, 0x06}, {0x4837, 0x2c}, {0x5001, 0xa3}, {0x302c, 0x42}, }; static struct regval_list sensor_uxga_regs[] = { {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x21}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x06}, {0x3809, 0x40}, {0x380a, 0x04}, {0x380b, 0xb0}, {0x380c, 0x0b}, {0x380d, 0x1c}, {0x380e, 0x07}, {0x380f, 0xb0}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #else {0x3a08, 0x00}, {0x3a09, 0x49}, {0x3a0a, 0x00}, {0x3a0b, 0x3d}, {0x3a0e, 0x1a}, {0x3a0d, 0x20}, #endif {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0xc5}, {0x4005, 0x12}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x4004, 0x06}, {0x4837, 0x2c}, {0x5001, 0xa3}, {0x302c, 0x42}, }; static struct regval_list sensor_sxga_regs[] = { {0x3820, 0x40}, {0x3821, 0x06}, {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x11}, #else {0x3035, 0x21}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x05}, {0x3809, 0x00}, {0x380a, 0x03}, {0x380b, 0xc0}, {0x380c, 0x0b}, {0x380d, 0x1c}, {0x380e, 0x07}, {0x380f, 0xb0}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0x94}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x06}, {0x3a0d, 0x08}, #else {0x3a08, 0x00}, {0x3a09, 0x94}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x06}, {0x3a0d, 0x08}, #endif {0x3503, 0x00}, {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0xc5}, {0x4005, 0x12}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x4004, 0x06}, {0x4837, 0x2c}, {0x5001, 0xa3}, {0x302c, 0x42}, {0x3a18, 0x00}, {0x3a19, 0xf8}, }; static struct regval_list sensor_xga_regs[] = { {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x21}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x04}, {0x3809, 0x00}, {0x380a, 0x03}, {0x380b, 0x00}, {0x380c, 0x0b}, {0x380d, 0x1c}, {0x380e, 0x07}, {0x380f, 0xb0}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #else {0x3a08, 0x00}, {0x3a09, 0x49}, {0x3a0a, 0x00}, {0x3a0b, 0x3d}, {0x3a0e, 0x1a}, {0x3a0d, 0x20}, #endif {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0xc5}, {0x4005, 0x12}, {0x3618, 0x00}, {0x3612, 0x29}, {0x3709, 0x52}, {0x370c, 0x03}, {0x3a02, 0x03}, {0x3a03, 0xd8}, {0x3a14, 0x03}, {0x3a15, 0xd8}, {0x4004, 0x02}, {0x4837, 0x22}, {0x5001, 0xa3}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x4004, 0x06}, {0x4837, 0x2c}, {0x5001, 0xa3}, {0x302c, 0x42}, }; static struct regval_list sensor_1080p_regs[] = { {0x3820, 0x40}, {0x3821, 0x06}, {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x11}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x07}, {0x3809, 0x80}, {0x380a, 0x04}, {0x380b, 0x38}, {0x380c, 0x09}, {0x380d, 0xc4}, {0x380e, 0x04}, {0x380f, 0x60}, #ifndef FPGA_VER {0x3a08, 0x01}, {0x3a09, 0x50}, {0x3a0a, 0x01}, {0x3a0b, 0x18}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, #else {0x3a08, 0x00}, {0x3a09, 0x54}, {0x3a0a, 0x00}, {0x3a0b, 0x46}, {0x3a0e, 0x0d}, {0x3a0d, 0x10}, #endif {0x3503, 0x00}, {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3800, 0x01}, {0x3801, 0x50}, {0x3802, 0x01}, {0x3803, 0xb2}, {0x3804, 0x08}, {0x3805, 0xef}, {0x3806, 0x05}, {0x3807, 0xf1}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0x45}, {0x4005, 0x18}, {0x3618, 0x04}, {0x3612, 0x2b}, {0x3709, 0x12}, {0x370c, 0x00}, {0x3a02, 0x04}, {0x3a03, 0x60}, {0x3a14, 0x04}, {0x3a15, 0x60}, {0x4004, 0x06}, {0x3002, 0x1c}, {0x3006, 0xc3}, {0x460b, 0x37}, {0x460c, 0x20}, {0x4837, 0x16}, {0x5001, 0x83}, {0x302c, 0x42}, {0x3a18, 0x00}, {0x3a19, 0x80}, }; static struct regval_list sensor_720p_regs[] = { {0x3820, 0x41}, {0x3821, 0x07}, {0x3034, 0x18}, #ifndef FPGA_VER {0x3035, 0x21}, #else {0x3035, 0x41}, #endif {0x3036, 0x54}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x05}, {0x3809, 0x00}, {0x380a, 0x02}, {0x380b, 0xd0}, {0x380c, 0x07}, {0x380d, 0x64}, {0x380e, 0x02}, {0x380f, 0xe4}, #ifndef FPGA_VER {0x3a08, 0x00}, {0x3a09, 0xdd}, {0x3a0a, 0x00}, {0x3a0b, 0xb8}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, #else {0x3a08, 0x00}, {0x3a09, 0xdd}, {0x3a0a, 0x00}, {0x3a0b, 0xb8}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, #endif {0x3503, 0x00}, {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x07}, {0x3814, 0x31}, {0x3815, 0x31}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0xfa}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x06}, {0x3807, 0xa9}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, {0x4002, 0x45}, {0x4005, 0x18}, {0x3618, 0x00}, {0x3612, 0x29}, {0x3709, 0x52}, {0x370c, 0x03}, {0x3a02, 0x02}, {0x3a03, 0xe0}, {0x3a14, 0x02}, {0x3a15, 0xe0}, {0x4004, 0x02}, {0x3002, 0x1c}, {0x3006, 0xc3}, {0x460b, 0x37}, {0x460c, 0x20}, {0x4837, 0x16}, {0x5001, 0x83}, {0x302c, 0x42}, {0x3a18, 0x00}, {0x3a19, 0xd8}, }; static struct regval_list sensor_svga_regs[] = { {0x3034, 0x1a}, #ifndef FPGA_VER {0x3035, 0x11}, #else {0x3035, 0x21}, #endif {0x3036, 0x46}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x3}, {0x3809, 0x20}, {0x380a, 0x2}, {0x380b, 0x58}, {0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, {0x380f, 0xd8}, #ifndef FPGA_VER {0x3a08, 0x01}, {0x3a09, 0x27}, {0x3a0a, 0x00}, {0x3a0b, 0xf6}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, #else {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x06}, {0x3a0d, 0x08}, #endif {0x3c07, 0x08}, {0x3814, 0x31}, {0x3815, 0x31}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x04}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9b}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x06}, {0x4002, 0x45}, {0x4005, 0x18}, {0x3618, 0x00}, {0x3612, 0x29}, {0x3709, 0x52}, {0x370c, 0x03}, {0x3a02, 0x03}, {0x3a03, 0xd8}, {0x3a14, 0x03}, {0x3a15, 0xd8}, {0x4004, 0x02}, {0x4837, 0x22}, {0x5001, 0xa3}, {0x302c, 0x42}, }; static struct regval_list sensor_vga_regs[] = { {0x3820, 0x41}, {0x3821, 0x07}, {0x3034, 0x1a}, #ifndef FPGA_VER {0x3035, 0x11}, #else {0x3035, 0x41}, #endif {0x3036, 0x46}, {0x3037, 0x13}, {0x3108, 0x01}, {0x3824, 0x01}, {REG_DLY, 0x05}, {0x3808, 0x02}, {0x3809, 0x80}, {0x380a, 0x01}, {0x380b, 0xe0}, {0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, {0x380f, 0xd8}, #ifndef FPGA_VER {0x3a08, 0x01}, {0x3a09, 0x27}, {0x3a0a, 0x00}, {0x3a0b, 0xf6}, {0x3a0e, 0x03}, {0x3a0d, 0x04}, #else {0x3a08, 0x00}, {0x3a09, 0x93}, {0x3a0a, 0x00}, {0x3a0b, 0x7b}, {0x3a0e, 0x06}, {0x3a0d, 0x08}, #endif {0x3618, 0x00}, {0x3612, 0x29}, {0x3709, 0x52}, {0x370c, 0x03}, {0x3a02, 0x03}, {0x3a03, 0xd8}, {0x3a14, 0x03}, {0x3a15, 0xd8}, {0x4004, 0x02}, {0x3503, 0x00}, {0x350c, 0x00}, {0x350d, 0x00}, {0x3c07, 0x08}, {0x3814, 0x31}, {0x3815, 0x31}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x04}, {0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9b}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x06}, {0x4002, 0x45}, {0x4005, 0x18}, {0x4837, 0x22}, {0x5001, 0xa3}, #ifndef FPGA_VER {0x302c, 0x02}, #else {0x302c, 0x02}, #endif {0x3a18, 0x00}, {0x3a19, 0xf8}, }; #ifdef AUTO_FPS static struct regval_list sensor_auto_fps_mode[] = { {0x3008, 0x42}, {0x3a00, 0x7c}, {0x3a02, 0x07}, {0x3a03, 0xb0}, {0x3a14, 0x07}, {0x3a15, 0xb0}, {0x3008, 0x02}, }; static struct regval_list sensor_fix_fps_mode[] = { {0x3a00, 0x78}, }; #endif static struct regval_list sensor_oe_disable_regs[] = { {0x3017, 0x00}, {0x3018, 0x00}, }; static struct regval_list sensor_oe_enable_regs[] = { {0x3017, 0x7f}, {0x3018, 0xf0}, }; static struct regval_list sensor_sw_stby_on_regs[] = { {0x3008, 0x42}, }; static struct regval_list sensor_sw_stby_off_regs[] = { {0x3008, 0x02}, }; static unsigned char sensor_af_fw_regs[] = { 0x02, 0x0f, 0xd6, 0x02, 0x0a, 0x39, 0xc2, 0x01, 0x22, 0x22, 0x00, 0x02, 0x0f, 0xb2, 0xe5, 0x1f, 0x70, 0x72, 0xf5, 0x1e, 0xd2, 0x35, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe4, 0xf6, 0x08, 0xf6, 0x0f, 0xbf, 0x34, 0xf2, 0x90, 0x0e, 0x93, 0xe4, 0x93, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x04, 0x7f, 0x05, 0x80, 0x02, 0x7f, 0xfb, 0x78, 0xbd, 0xa6, 0x07, 0x12, 0x0f, 0x04, 0x40, 0x04, 0x7f, 0x03, 0x80, 0x02, 0x7f, 0x30, 0x78, 0xbc, 0xa6, 0x07, 0xe6, 0x18, 0xf6, 0x08, 0xe6, 0x78, 0xb9, 0xf6, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xbf, 0x76, 0x33, 0xe4, 0x08, 0xf6, 0x78, 0xb8, 0x76, 0x01, 0x75, 0x4a, 0x02, 0x78, 0xb6, 0xf6, 0x08, 0xf6, 0x74, 0xff, 0x78, 0xc1, 0xf6, 0x08, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0xbc, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x12, 0x0a, 0xff, 0xc2, 0x37, 0x22, 0x78, 0xb8, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x02, 0x16, 0x22, 0xe5, 0x1f, 0xb4, 0x05, 0x23, 0xe4, 0xf5, 0x1f, 0xc2, 0x01, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x90, 0x30, 0x28, 0xf0, 0x75, 0x1e, 0x10, 0xd2, 0x35, 0x22, 0xe5, 0x4b, 0x75, 0xf0, 0x05, 0x84, 0x78, 0xbc, 0xf6, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0xff, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x78, 0xbc, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0xef, 0x12, 0x0f, 0x0b, 0xd3, 0x78, 0xb7, 0x96, 0xee, 0x18, 0x96, 0x40, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xb9, 0xf6, 0x78, 0xb6, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x12, 0x0f, 0x0b, 0xc3, 0x78, 0xc2, 0x96, 0xee, 0x18, 0x96, 0x50, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xc1, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xc3, 0x78, 0xc2, 0x96, 0xff, 0xee, 0x18, 0x96, 0x78, 0xc3, 0xf6, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x95, 0xe4, 0x18, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x78, 0xbc, 0xe6, 0x08, 0x26, 0x08, 0xf6, 0xe5, 0x1f, 0x64, 0x01, 0x70, 0x4a, 0xe6, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xdf, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x39, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xfe, 0x80, 0x02, 0x7f, 0x02, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x24, 0x03, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x24, 0xfd, 0x78, 0xc0, 0xf6, 0x12, 0x0f, 0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, 0x07, 0x75, 0x1f, 0x02, 0x78, 0xb8, 0x76, 0x01, 0x02, 0x02, 0x4a, 0xe5, 0x1f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x02, 0x2a, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x08, 0x12, 0x0e, 0xda, 0x50, 0x03, 0x02, 0x02, 0x28, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xff, 0x80, 0x02, 0x7f, 0x01, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x04, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x14, 0x78, 0xc0, 0xf6, 0x18, 0x12, 0x0f, 0x04, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x00, 0x78, 0xbf, 0xa6, 0x07, 0xd3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x00, 0x78, 0xc0, 0xa6, 0x07, 0xc3, 0x18, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xbf, 0xa6, 0x07, 0xc3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xc0, 0xa6, 0x07, 0x12, 0x0f, 0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, 0x07, 0x75, 0x1f, 0x03, 0x78, 0xb8, 0x76, 0x01, 0x80, 0x20, 0xe5, 0x1f, 0x64, 0x03, 0x70, 0x26, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x09, 0x78, 0xb9, 0xe6, 0x78, 0xbe, 0xf6, 0x75, 0x1f, 0x04, 0x78, 0xbe, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x02, 0x0a, 0xff, 0xe5, 0x1f, 0xb4, 0x04, 0x10, 0x90, 0x0e, 0x94, 0xe4, 0x78, 0xc3, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x75, 0x1f, 0x05, 0x22, 0x30, 0x01, 0x03, 0x02, 0x04, 0xc0, 0x30, 0x02, 0x03, 0x02, 0x04, 0xc0, 0x90, 0x51, 0xa5, 0xe0, 0x78, 0x93, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xe5, 0x1f, 0x70, 0x3c, 0x75, 0x1e, 0x20, 0xd2, 0x35, 0x12, 0x0c, 0x7a, 0x78, 0x7e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xa6, 0x09, 0x18, 0x76, 0x01, 0x12, 0x0c, 0x5b, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xe6, 0x78, 0x6e, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0x93, 0xe6, 0x78, 0x90, 0xf6, 0x78, 0x94, 0xe6, 0x78, 0x91, 0xf6, 0x78, 0x95, 0xe6, 0x78, 0x92, 0xf6, 0x22, 0x79, 0x90, 0xe7, 0xd3, 0x78, 0x93, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x93, 0xe7, 0x78, 0x90, 0x96, 0xff, 0x78, 0x88, 0x76, 0x00, 0x08, 0xa6, 0x07, 0x79, 0x91, 0xe7, 0xd3, 0x78, 0x94, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x94, 0xe7, 0x78, 0x91, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x79, 0x92, 0xe7, 0xd3, 0x78, 0x95, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x95, 0xe7, 0x78, 0x92, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x12, 0x0c, 0x5b, 0x78, 0x8a, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8a, 0xe6, 0x24, 0x6e, 0xf8, 0xa6, 0x09, 0x78, 0x8a, 0xe6, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xd3, 0xef, 0x94, 0x0f, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0x7f, 0x00, 0x80, 0x05, 0x78, 0x8a, 0xe6, 0x04, 0xff, 0x78, 0x8a, 0xa6, 0x07, 0xe5, 0x1f, 0xb4, 0x01, 0x0a, 0xe6, 0x60, 0x03, 0x02, 0x04, 0xc0, 0x75, 0x1f, 0x02, 0x22, 0x12, 0x0c, 0x7a, 0x78, 0x80, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x12, 0x0c, 0x7a, 0x78, 0x82, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x6e, 0xe6, 0x78, 0x8c, 0xf6, 0x78, 0x6e, 0xe6, 0x78, 0x8d, 0xf6, 0x7f, 0x01, 0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xc3, 0x78, 0x81, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x50, 0x0a, 0x12, 0x0c, 0x82, 0x78, 0x80, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8c, 0xe6, 0xc3, 0x97, 0x50, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8c, 0xf6, 0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xd3, 0x78, 0x83, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x40, 0x0a, 0x12, 0x0c, 0x82, 0x78, 0x82, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8d, 0xe6, 0xd3, 0x97, 0x40, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8d, 0xf6, 0x0f, 0xef, 0x64, 0x10, 0x70, 0x9e, 0xc3, 0x79, 0x81, 0xe7, 0x78, 0x83, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0x78, 0x84, 0xf6, 0x08, 0xa6, 0x07, 0xc3, 0x79, 0x8c, 0xe7, 0x78, 0x8d, 0x96, 0x08, 0xf6, 0xd3, 0x79, 0x81, 0xe7, 0x78, 0x7f, 0x96, 0x19, 0xe7, 0x18, 0x96, 0x40, 0x05, 0x09, 0xe7, 0x08, 0x80, 0x06, 0xc3, 0x79, 0x7f, 0xe7, 0x78, 0x81, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0xfe, 0x78, 0x86, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x79, 0x8c, 0xe7, 0xd3, 0x78, 0x8b, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x8b, 0xe7, 0x78, 0x8c, 0x96, 0xff, 0x78, 0x8f, 0xa6, 0x07, 0xe5, 0x1f, 0x64, 0x02, 0x70, 0x69, 0x90, 0x0e, 0x91, 0x93, 0xff, 0x18, 0xe6, 0xc3, 0x9f, 0x50, 0x72, 0x12, 0x0c, 0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8e, 0x12, 0x0c, 0x38, 0x78, 0x80, 0x12, 0x0c, 0x6b, 0x7b, 0x04, 0x12, 0x0c, 0x1d, 0xc3, 0x12, 0x06, 0x45, 0x50, 0x56, 0x90, 0x0e, 0x92, 0xe4, 0x93, 0xff, 0x78, 0x8f, 0xe6, 0x9f, 0x40, 0x02, 0x80, 0x11, 0x90, 0x0e, 0x90, 0xe4, 0x93, 0xff, 0xd3, 0x78, 0x89, 0xe6, 0x9f, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x1f, 0x05, 0x12, 0x0c, 0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8f, 0x12, 0x0c, 0x38, 0x78, 0x7e, 0x12, 0x0c, 0x6b, 0x7b, 0x40, 0x12, 0x0c, 0x1d, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x18, 0x75, 0x1f, 0x05, 0x22, 0xe5, 0x1f, 0xb4, 0x05, 0x0f, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, 0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, 0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, 0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, 0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, 0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, 0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, 0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, 0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, 0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, 0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, 0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe4, 0x93, 0xfc, 0x74, 0x01, 0x93, 0xfd, 0x74, 0x02, 0x93, 0xfe, 0x74, 0x03, 0x93, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x38, 0x04, 0x78, 0x52, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x00, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x10, 0x12, 0x0b, 0x92, 0x90, 0x38, 0x06, 0x78, 0x54, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x02, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x12, 0x12, 0x0b, 0x92, 0xa3, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x52, 0x79, 0x52, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x14, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x53, 0xf7, 0xee, 0x19, 0xf7, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x54, 0x79, 0x54, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x54, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x55, 0xf7, 0xee, 0x19, 0xf7, 0x79, 0x52, 0x12, 0x0b, 0xd9, 0x09, 0x12, 0x0b, 0xd9, 0xaf, 0x47, 0x12, 0x0b, 0xb2, 0xe5, 0x44, 0xfb, 0x7a, 0x00, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5a, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x45, 0x12, 0x0b, 0xb2, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x56, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x48, 0x78, 0x54, 0x12, 0x0b, 0xb4, 0xe5, 0x43, 0xfb, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5c, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x46, 0x7e, 0x00, 0x78, 0x54, 0x12, 0x0b, 0xb6, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x58, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xc3, 0x78, 0x5b, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, 0x08, 0x76, 0x08, 0xc3, 0x78, 0x5d, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, 0x08, 0x76, 0x08, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0xff, 0xd3, 0x78, 0x57, 0xe6, 0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5a, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x57, 0x12, 0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x78, 0x5e, 0x12, 0x0b, 0xbe, 0xff, 0xd3, 0x78, 0x59, 0xe6, 0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5c, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x59, 0x12, 0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe4, 0xfc, 0xfd, 0x78, 0x62, 0x12, 0x06, 0x99, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0x78, 0x57, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0x78, 0x66, 0x12, 0x0b, 0xbe, 0x78, 0x59, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0xe4, 0xfc, 0xfd, 0x78, 0x6a, 0x12, 0x06, 0x99, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x08, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x99, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x0a, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, 0x06, 0x99, 0x78, 0x61, 0xe6, 0x90, 0x60, 0x01, 0xf0, 0x78, 0x65, 0xe6, 0xa3, 0xf0, 0x78, 0x69, 0xe6, 0xa3, 0xf0, 0x78, 0x55, 0xe6, 0xa3, 0xf0, 0x7d, 0x01, 0x78, 0x61, 0x12, 0x0b, 0xe9, 0x24, 0x01, 0x12, 0x0b, 0xa6, 0x78, 0x65, 0x12, 0x0b, 0xe9, 0x24, 0x02, 0x12, 0x0b, 0xa6, 0x78, 0x69, 0x12, 0x0b, 0xe9, 0x24, 0x03, 0x12, 0x0b, 0xa6, 0x78, 0x6d, 0x12, 0x0b, 0xe9, 0x24, 0x04, 0x12, 0x0b, 0xa6, 0x0d, 0xbd, 0x05, 0xd4, 0xc2, 0x0e, 0xc2, 0x06, 0x22, 0x85, 0x08, 0x41, 0x90, 0x30, 0x24, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0, 0xf5, 0x3e, 0xa3, 0xe0, 0xf5, 0x3f, 0xa3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x3c, 0xd2, 0x34, 0xe5, 0x41, 0x12, 0x06, 0xb1, 0x09, 0x31, 0x03, 0x09, 0x35, 0x04, 0x09, 0x3b, 0x05, 0x09, 0x3e, 0x06, 0x09, 0x41, 0x07, 0x09, 0x4a, 0x08, 0x09, 0x5b, 0x12, 0x09, 0x73, 0x18, 0x09, 0x89, 0x19, 0x09, 0x5e, 0x1a, 0x09, 0x6a, 0x1b, 0x09, 0xad, 0x80, 0x09, 0xb2, 0x81, 0x0a, 0x1d, 0x8f, 0x0a, 0x09, 0x90, 0x0a, 0x1d, 0x91, 0x0a, 0x1d, 0x92, 0x0a, 0x1d, 0x93, 0x0a, 0x1d, 0x94, 0x0a, 0x1d, 0x98, 0x0a, 0x17, 0x9f, 0x0a, 0x1a, 0xec, 0x00, 0x00, 0x0a, 0x38, 0x12, 0x0f, 0x74, 0x22, 0x12, 0x0f, 0x74, 0xd2, 0x03, 0x22, 0xd2, 0x03, 0x22, 0xc2, 0x03, 0x22, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x02, 0x0a, 0x1d, 0xc2, 0x01, 0xc2, 0x02, 0xc2, 0x03, 0x12, 0x0d, 0x0d, 0x75, 0x1e, 0x70, 0xd2, 0x35, 0x02, 0x0a, 0x1d, 0x02, 0x0a, 0x04, 0x85, 0x40, 0x4a, 0x85, 0x3c, 0x4b, 0x12, 0x0a, 0xff, 0x02, 0x0a, 0x1d, 0x85, 0x4a, 0x40, 0x85, 0x4b, 0x3c, 0x02, 0x0a, 0x1d, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x40, 0x31, 0x85, 0x3f, 0x30, 0x85, 0x3e, 0x2f, 0x85, 0x3d, 0x2e, 0x12, 0x0f, 0x46, 0x80, 0x1f, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, 0x74, 0xff, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, 0x2a, 0x12, 0x0f, 0x46, 0x85, 0x2d, 0x40, 0x85, 0x2c, 0x3f, 0x85, 0x2b, 0x3e, 0x85, 0x2a, 0x3d, 0xe4, 0xf5, 0x3c, 0x80, 0x70, 0x12, 0x0f, 0x16, 0x80, 0x6b, 0x85, 0x3d, 0x45, 0x85, 0x3e, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xe5, 0x45, 0xc3, 0x9f, 0x50, 0x02, 0x8f, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xe5, 0x46, 0xc3, 0x9f, 0x50, 0x02, 0x8f, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x45, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x44, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x44, 0x9f, 0xf5, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x46, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x43, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x43, 0x9f, 0xf5, 0x46, 0x12, 0x06, 0xd7, 0x80, 0x14, 0x85, 0x40, 0x48, 0x85, 0x3f, 0x47, 0x85, 0x3e, 0x46, 0x85, 0x3d, 0x45, 0x80, 0x06, 0x02, 0x06, 0xd7, 0x12, 0x0d, 0x7e, 0x90, 0x30, 0x24, 0xe5, 0x3d, 0xf0, 0xa3, 0xe5, 0x3e, 0xf0, 0xa3, 0xe5, 0x3f, 0xf0, 0xa3, 0xe5, 0x40, 0xf0, 0xa3, 0xe5, 0x3c, 0xf0, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x90, 0x3f, 0x0c, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x30, 0xe3, 0x74, 0x30, 0x36, 0x66, 0x90, 0x60, 0x19, 0xe0, 0xf5, 0x0a, 0xa3, 0xe0, 0xf5, 0x0b, 0x90, 0x60, 0x1d, 0xe0, 0xf5, 0x14, 0xa3, 0xe0, 0xf5, 0x15, 0x90, 0x60, 0x21, 0xe0, 0xf5, 0x0c, 0xa3, 0xe0, 0xf5, 0x0d, 0x90, 0x60, 0x29, 0xe0, 0xf5, 0x0e, 0xa3, 0xe0, 0xf5, 0x0f, 0x90, 0x60, 0x31, 0xe0, 0xf5, 0x10, 0xa3, 0xe0, 0xf5, 0x11, 0x90, 0x60, 0x39, 0xe0, 0xf5, 0x12, 0xa3, 0xe0, 0xf5, 0x13, 0x30, 0x01, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x09, 0x30, 0x02, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x30, 0x33, 0x0c, 0x30, 0x03, 0x09, 0x20, 0x02, 0x06, 0x20, 0x01, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0b, 0x90, 0x30, 0x01, 0xe0, 0x44, 0x40, 0xf0, 0xe0, 0x54, 0xbf, 0xf0, 0xe5, 0x32, 0x30, 0xe1, 0x14, 0x30, 0x34, 0x11, 0x90, 0x30, 0x22, 0xe0, 0xf5, 0x08, 0xe4, 0xf0, 0x30, 0x00, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x08, 0xe5, 0x32, 0x30, 0xe5, 0x12, 0x90, 0x56, 0xa1, 0xe0, 0xf5, 0x09, 0x30, 0x31, 0x09, 0x30, 0x05, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0d, 0x90, 0x3f, 0x0c, 0xe5, 0x32, 0xf0, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x7e, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, 0xc3, 0x90, 0x0e, 0x7c, 0x74, 0x01, 0x93, 0x9f, 0xff, 0xe4, 0x93, 0x9e, 0xfe, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xab, 0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xaf, 0x4b, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x12, 0x0d, 0xe1, 0xe4, 0x7b, 0xff, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xb3, 0x12, 0x0d, 0xe1, 0x90, 0x0e, 0x69, 0xe4, 0x12, 0x0d, 0xf6, 0x12, 0x0d, 0xe1, 0xe4, 0x85, 0x4a, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0xa3, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0xe5, 0x3b, 0x45, 0x37, 0xf5, 0x3b, 0xe5, 0x3a, 0x45, 0x36, 0xf5, 0x3a, 0xe5, 0x39, 0x45, 0x35, 0xf5, 0x39, 0xe5, 0x38, 0x45, 0x34, 0xf5, 0x38, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x3b, 0x31, 0x85, 0x3a, 0x30, 0x85, 0x39, 0x2f, 0x85, 0x38, 0x2e, 0x02, 0x0f, 0x46, 0xe0, 0xa3, 0xe0, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0, 0xc3, 0x08, 0xe6, 0x9f, 0xf6, 0x18, 0xe6, 0x9e, 0xf6, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0x60, 0x8f, 0x82, 0xf5, 0x83, 0xec, 0xf0, 0x22, 0x78, 0x52, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x02, 0x04, 0xc1, 0xe4, 0xfc, 0xfd, 0x12, 0x06, 0x99, 0x78, 0x5c, 0xe6, 0xc3, 0x13, 0xfe, 0x08, 0xe6, 0x13, 0x22, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0xe7, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0x68, 0xf7, 0x09, 0xe7, 0xc4, 0x54, 0x0f, 0x48, 0xf7, 0x22, 0xe6, 0xfc, 0xed, 0x75, 0xf0, 0x04, 0xa4, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x8c, 0x45, 0x22, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xee, 0xf6, 0xed, 0x08, 0xf6, 0x22, 0x13, 0xff, 0xc3, 0xe6, 0x9f, 0xff, 0x18, 0xe6, 0x9e, 0xfe, 0x22, 0xe6, 0xc3, 0x13, 0xf7, 0x08, 0xe6, 0x13, 0x09, 0xf7, 0x22, 0xad, 0x39, 0xac, 0x38, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0x28, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0xab, 0x37, 0xaa, 0x36, 0xa9, 0x35, 0xa8, 0x34, 0x22, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x22, 0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0x8f, 0x37, 0x8e, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0x22, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0x22, 0x78, 0x4e, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x22, 0x78, 0x89, 0xef, 0x26, 0xf6, 0x18, 0xe4, 0x36, 0xf6, 0x22, 0x75, 0x89, 0x03, 0x75, 0xa8, 0x01, 0x75, 0xb8, 0x04, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x15, 0x75, 0x37, 0x0d, 0x12, 0x0e, 0x9a, 0x12, 0x00, 0x09, 0x12, 0x0f, 0x16, 0x12, 0x00, 0x06, 0xd2, 0x00, 0xd2, 0x34, 0xd2, 0xaf, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x49, 0x75, 0x37, 0x03, 0x12, 0x0e, 0x9a, 0x30, 0x08, 0x09, 0xc2, 0x34, 0x12, 0x08, 0xcb, 0xc2, 0x08, 0xd2, 0x34, 0x30, 0x0b, 0x09, 0xc2, 0x36, 0x12, 0x02, 0x6c, 0xc2, 0x0b, 0xd2, 0x36, 0x30, 0x09, 0x09, 0xc2, 0x36, 0x12, 0x00, 0x0e, 0xc2, 0x09, 0xd2, 0x36, 0x30, 0x0e, 0x03, 0x12, 0x06, 0xd7, 0x30, 0x35, 0xd3, 0x90, 0x30, 0x29, 0xe5, 0x1e, 0xf0, 0xb4, 0x10, 0x05, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0xc2, 0x35, 0x80, 0xc1, 0xe4, 0xf5, 0x4b, 0x90, 0x0e, 0x7a, 0x93, 0xff, 0xe4, 0x8f, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0x90, 0x0e, 0x6a, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x90, 0x0e, 0x72, 0x12, 0x06, 0x7c, 0xef, 0x45, 0x37, 0xf5, 0x37, 0xee, 0x45, 0x36, 0xf5, 0x36, 0xed, 0x45, 0x35, 0xf5, 0x35, 0xec, 0x45, 0x34, 0xf5, 0x34, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x37, 0x31, 0x85, 0x36, 0x30, 0x85, 0x35, 0x2f, 0x85, 0x34, 0x2e, 0x12, 0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x72, 0x12, 0x0d, 0xea, 0x12, 0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x6e, 0x12, 0x0d, 0xea, 0x02, 0x0f, 0x46, 0xe5, 0x40, 0x24, 0xf2, 0xf5, 0x37, 0xe5, 0x3f, 0x34, 0x43, 0xf5, 0x36, 0xe5, 0x3e, 0x34, 0xa2, 0xf5, 0x35, 0xe5, 0x3d, 0x34, 0x28, 0xf5, 0x34, 0xe5, 0x37, 0xff, 0xe4, 0xfe, 0xfd, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x69, 0x8f, 0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x37, 0x54, 0xa0, 0xff, 0xe5, 0x36, 0xfe, 0xe4, 0xfd, 0xfc, 0x78, 0x07, 0x12, 0x06, 0x56, 0x78, 0x10, 0x12, 0x0f, 0x9a, 0xe4, 0xff, 0xfe, 0xe5, 0x35, 0xfd, 0xe4, 0xfc, 0x78, 0x0e, 0x12, 0x06, 0x56, 0x12, 0x0f, 0x9d, 0xe4, 0xff, 0xfe, 0xfd, 0xe5, 0x34, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x56, 0x78, 0x08, 0x12, 0x0f, 0x9a, 0x22, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x31, 0x8e, 0x30, 0x8d, 0x2f, 0x8c, 0x2e, 0x22, 0x93, 0xf9, 0xf8, 0x02, 0x06, 0x69, 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x17, 0x08, 0x31, 0x15, 0x53, 0x54, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x01, 0x10, 0x01, 0x56, 0x40, 0x1a, 0x30, 0x29, 0x7e, 0x00, 0x30, 0x04, 0x20, 0xdf, 0x30, 0x05, 0x40, 0xbf, 0x50, 0x03, 0x00, 0xfd, 0x50, 0x27, 0x01, 0xfe, 0x60, 0x00, 0x11, 0x00, 0x3f, 0x05, 0x30, 0x00, 0x3f, 0x06, 0x22, 0x00, 0x3f, 0x01, 0x2a, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x36, 0x06, 0x07, 0x00, 0x3f, 0x0b, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x40, 0xbf, 0x30, 0x01, 0x00, 0xbf, 0x30, 0x29, 0x70, 0x00, 0x3a, 0x00, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x36, 0x03, 0x36, 0x02, 0x41, 0x44, 0x58, 0x20, 0x18, 0x10, 0x0a, 0x04, 0x04, 0x00, 0x03, 0xff, 0x64, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x00, 0x03, 0x51, 0x00, 0x7a, 0x50, 0x3c, 0x28, 0x1e, 0x10, 0x10, 0x50, 0x2d, 0x28, 0x16, 0x10, 0x10, 0x02, 0x00, 0x10, 0x0c, 0x10, 0x04, 0x0c, 0x6e, 0x06, 0x05, 0x00, 0xa5, 0x5a, 0x00, 0xae, 0x35, 0xaf, 0x36, 0xe4, 0xfd, 0xed, 0xc3, 0x95, 0x37, 0x50, 0x33, 0x12, 0x0f, 0xe2, 0xe4, 0x93, 0xf5, 0x38, 0x74, 0x01, 0x93, 0xf5, 0x39, 0x45, 0x38, 0x60, 0x23, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xe0, 0xfc, 0x12, 0x0f, 0xe2, 0x74, 0x03, 0x93, 0x52, 0x04, 0x12, 0x0f, 0xe2, 0x74, 0x02, 0x93, 0x42, 0x04, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xec, 0xf0, 0x0d, 0x80, 0xc7, 0x22, 0x78, 0xbe, 0xe6, 0xd3, 0x08, 0xff, 0xe6, 0x64, 0x80, 0xf8, 0xef, 0x64, 0x80, 0x98, 0x22, 0x93, 0xff, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x04, 0xc1, 0x78, 0xc1, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x22, 0x78, 0xbd, 0xd3, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe5, 0x3c, 0xd3, 0x94, 0x00, 0x40, 0x0b, 0x90, 0x0e, 0x88, 0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x86, 0x80, 0x09, 0x90, 0x0e, 0x82, 0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x80, 0xe4, 0x93, 0xf5, 0x44, 0xa3, 0xe4, 0x93, 0xf5, 0x43, 0xd2, 0x06, 0x30, 0x06, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0e, 0x22, 0xa2, 0xaf, 0x92, 0x32, 0xc2, 0xaf, 0xe5, 0x23, 0x45, 0x22, 0x90, 0x0e, 0x5d, 0x60, 0x0e, 0x12, 0x0f, 0xcb, 0xe0, 0xf5, 0x2c, 0x12, 0x0f, 0xc8, 0xe0, 0xf5, 0x2d, 0x80, 0x0c, 0x12, 0x0f, 0xcb, 0xe5, 0x30, 0xf0, 0x12, 0x0f, 0xc8, 0xe5, 0x31, 0xf0, 0xa2, 0x32, 0x92, 0xaf, 0x22, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, 0xd2, 0x01, 0xc2, 0x02, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0x22, 0xfb, 0xd3, 0xed, 0x9b, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x22, 0x12, 0x06, 0x69, 0xe5, 0x40, 0x2f, 0xf5, 0x40, 0xe5, 0x3f, 0x3e, 0xf5, 0x3f, 0xe5, 0x3e, 0x3d, 0xf5, 0x3e, 0xe5, 0x3d, 0x3c, 0xf5, 0x3d, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x3f, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x33, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x5f, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0xcd, 0x02, 0x0c, 0x98, 0x8f, 0x82, 0x8e, 0x83, 0x75, 0xf0, 0x04, 0xed, 0x02, 0x06, 0xa5, }; /* * The white balance settings * Here only tune the R G B channel gain. * The white balance enalbe bit is modified in sensor_s_autowb and sensor_s_wb */ static struct regval_list sensor_wb_manual[] = { {0x3406, 0x1}, }; static struct regval_list sensor_wb_auto_regs[] = { {0x3406, 0x00}, }; static struct regval_list sensor_wb_incandescence_regs[] = { {0x3406, 0x1}, {0x3400, 0x5}, {0x3401, 0x48}, {0x3402, 0x4}, {0x3403, 0x0}, {0x3404, 0x7}, {0x3405, 0xcf}, }; static struct regval_list sensor_wb_fluorescent_regs[] = { {0x3406, 0x1}, {0x3400, 0x5}, {0x3401, 0x48}, {0x3402, 0x4}, {0x3403, 0x0}, {0x3404, 0x7}, {0x3405, 0xcf}, }; static struct regval_list sensor_wb_tungsten_regs[] = { {0x3406, 0x1}, {0x3400, 0x4}, {0x3401, 0x10}, {0x3402, 0x4}, {0x3403, 0x0}, {0x3404, 0x8}, {0x3405, 0xb6}, }; static struct regval_list sensor_wb_horizon[] = { }; static struct regval_list sensor_wb_daylight_regs[] = { {0x3406, 0x1}, {0x3400, 0x6}, {0x3401, 0x1c}, {0x3402, 0x4}, {0x3403, 0x0}, {0x3404, 0x4}, {0x3405, 0xf3}, }; static struct regval_list sensor_wb_flash[] = { }; static struct regval_list sensor_wb_cloud_regs[] = { {0x3406, 0x1}, {0x3400, 0x6}, {0x3401, 0x48}, {0x3402, 0x4}, {0x3403, 0x0}, {0x3404, 0x4}, {0x3405, 0xd3}, }; static struct regval_list sensor_wb_shade[] = { }; static struct cfg_array sensor_wb[] = { { .regs = sensor_wb_manual, .size = ARRAY_SIZE(sensor_wb_manual), }, { .regs = sensor_wb_auto_regs, .size = ARRAY_SIZE(sensor_wb_auto_regs), }, { .regs = sensor_wb_incandescence_regs, .size = ARRAY_SIZE(sensor_wb_incandescence_regs), }, { .regs = sensor_wb_fluorescent_regs, .size = ARRAY_SIZE(sensor_wb_fluorescent_regs), }, { .regs = sensor_wb_tungsten_regs, .size = ARRAY_SIZE(sensor_wb_tungsten_regs), }, { .regs = sensor_wb_horizon, .size = ARRAY_SIZE(sensor_wb_horizon), }, { .regs = sensor_wb_daylight_regs, .size = ARRAY_SIZE(sensor_wb_daylight_regs), }, { .regs = sensor_wb_flash, .size = ARRAY_SIZE(sensor_wb_flash), }, { .regs = sensor_wb_cloud_regs, .size = ARRAY_SIZE(sensor_wb_cloud_regs), }, { .regs = sensor_wb_shade, .size = ARRAY_SIZE(sensor_wb_shade), }, }; /* * The color effect settings */ static struct regval_list sensor_colorfx_none_regs[] = { {0x5580, 0x06}, {0x5583, 0x40}, {0x5584, 0x10}, }; static struct regval_list sensor_colorfx_bw_regs[] = { {0x5580, 0x1e}, {0x5583, 0x80}, {0x5584, 0x80}, }; static struct regval_list sensor_colorfx_sepia_regs[] = { {0x5580, 0x1e}, {0x5583, 0x40}, {0x5584, 0xa0}, }; static struct regval_list sensor_colorfx_negative_regs[] = { {0x5580, 0x46}, }; static struct regval_list sensor_colorfx_emboss_regs[] = { {0x5580, 0x1e}, {0x5583, 0x80}, {0x5584, 0xc0}, }; static struct regval_list sensor_colorfx_sketch_regs[] = { {0x5580, 0x1e}, {0x5583, 0x80}, {0x5584, 0xc0}, }; static struct regval_list sensor_colorfx_sky_blue_regs[] = { {0x5580, 0x1e}, {0x5583, 0xa0}, {0x5584, 0x40}, }; static struct regval_list sensor_colorfx_grass_green_regs[] = { {0x5580, 0x1e}, {0x5583, 0x60}, {0x5584, 0x60}, }; static struct regval_list sensor_colorfx_skin_whiten_regs[] = { }; static struct regval_list sensor_colorfx_vivid_regs[] = { }; static struct regval_list sensor_colorfx_aqua_regs[] = { }; static struct regval_list sensor_colorfx_art_freeze_regs[] = { }; static struct regval_list sensor_colorfx_silhouette_regs[] = { }; static struct regval_list sensor_colorfx_solarization_regs[] = { }; static struct regval_list sensor_colorfx_antique_regs[] = { }; static struct regval_list sensor_colorfx_set_cbcr_regs[] = { }; static struct cfg_array sensor_colorfx[] = { { .regs = sensor_colorfx_none_regs, .size = ARRAY_SIZE(sensor_colorfx_none_regs), }, { .regs = sensor_colorfx_bw_regs, .size = ARRAY_SIZE(sensor_colorfx_bw_regs), }, { .regs = sensor_colorfx_sepia_regs, .size = ARRAY_SIZE(sensor_colorfx_sepia_regs), }, { .regs = sensor_colorfx_negative_regs, .size = ARRAY_SIZE(sensor_colorfx_negative_regs), }, { .regs = sensor_colorfx_emboss_regs, .size = ARRAY_SIZE(sensor_colorfx_emboss_regs), }, { .regs = sensor_colorfx_sketch_regs, .size = ARRAY_SIZE(sensor_colorfx_sketch_regs), }, { .regs = sensor_colorfx_sky_blue_regs, .size = ARRAY_SIZE(sensor_colorfx_sky_blue_regs), }, { .regs = sensor_colorfx_grass_green_regs, .size = ARRAY_SIZE(sensor_colorfx_grass_green_regs), }, { .regs = sensor_colorfx_skin_whiten_regs, .size = ARRAY_SIZE(sensor_colorfx_skin_whiten_regs), }, { .regs = sensor_colorfx_vivid_regs, .size = ARRAY_SIZE(sensor_colorfx_vivid_regs), }, { .regs = sensor_colorfx_aqua_regs, .size = ARRAY_SIZE(sensor_colorfx_aqua_regs), }, { .regs = sensor_colorfx_art_freeze_regs, .size = ARRAY_SIZE(sensor_colorfx_art_freeze_regs), }, { .regs = sensor_colorfx_silhouette_regs, .size = ARRAY_SIZE(sensor_colorfx_silhouette_regs), }, { .regs = sensor_colorfx_solarization_regs, .size = ARRAY_SIZE(sensor_colorfx_solarization_regs), }, { .regs = sensor_colorfx_antique_regs, .size = ARRAY_SIZE(sensor_colorfx_antique_regs), }, { .regs = sensor_colorfx_set_cbcr_regs, .size = ARRAY_SIZE(sensor_colorfx_set_cbcr_regs), }, }; #if 1 static struct regval_list sensor_sharpness_auto_regs[] = { {0x5308, 0x25}, {0x5300, 0x08}, {0x5301, 0x30}, {0x5302, 0x10}, {0x5303, 0x00}, {0x5304, 0x08}, {0x5305, 0x30}, {0x5306, 0x08}, {0x5307, 0x16}, {0x5309, 0x08}, {0x530a, 0x30}, {0x530b, 0x04}, {0x530c, 0x06}, }; #endif #if 1 static struct regval_list sensor_denoise_auto_regs[] = { {0x5304, 0x08}, {0x5305, 0x30}, {0x5306, 0x1c}, {0x5307, 0x2c}, }; #endif /* * The brightness setttings */ static struct regval_list sensor_brightness_neg4_regs[] = { }; static struct regval_list sensor_brightness_neg3_regs[] = { }; static struct regval_list sensor_brightness_neg2_regs[] = { }; static struct regval_list sensor_brightness_neg1_regs[] = { }; static struct regval_list sensor_brightness_zero_regs[] = { }; static struct regval_list sensor_brightness_pos1_regs[] = { }; static struct regval_list sensor_brightness_pos2_regs[] = { }; static struct regval_list sensor_brightness_pos3_regs[] = { }; static struct regval_list sensor_brightness_pos4_regs[] = { }; static struct cfg_array sensor_brightness[] = { { .regs = sensor_brightness_neg4_regs, .size = ARRAY_SIZE(sensor_brightness_neg4_regs), }, { .regs = sensor_brightness_neg3_regs, .size = ARRAY_SIZE(sensor_brightness_neg3_regs), }, { .regs = sensor_brightness_neg2_regs, .size = ARRAY_SIZE(sensor_brightness_neg2_regs), }, { .regs = sensor_brightness_neg1_regs, .size = ARRAY_SIZE(sensor_brightness_neg1_regs), }, { .regs = sensor_brightness_zero_regs, .size = ARRAY_SIZE(sensor_brightness_zero_regs), }, { .regs = sensor_brightness_pos1_regs, .size = ARRAY_SIZE(sensor_brightness_pos1_regs), }, { .regs = sensor_brightness_pos2_regs, .size = ARRAY_SIZE(sensor_brightness_pos2_regs), }, { .regs = sensor_brightness_pos3_regs, .size = ARRAY_SIZE(sensor_brightness_pos3_regs), }, { .regs = sensor_brightness_pos4_regs, .size = ARRAY_SIZE(sensor_brightness_pos4_regs), }, }; /* * The contrast setttings */ static struct regval_list sensor_contrast_neg4_regs[] = { }; static struct regval_list sensor_contrast_neg3_regs[] = { }; static struct regval_list sensor_contrast_neg2_regs[] = { }; static struct regval_list sensor_contrast_neg1_regs[] = { }; static struct regval_list sensor_contrast_zero_regs[] = { }; static struct regval_list sensor_contrast_pos1_regs[] = { }; static struct regval_list sensor_contrast_pos2_regs[] = { }; static struct regval_list sensor_contrast_pos3_regs[] = { }; static struct regval_list sensor_contrast_pos4_regs[] = { }; static struct cfg_array sensor_contrast[] = { { .regs = sensor_contrast_neg4_regs, .size = ARRAY_SIZE(sensor_contrast_neg4_regs), }, { .regs = sensor_contrast_neg3_regs, .size = ARRAY_SIZE(sensor_contrast_neg3_regs), }, { .regs = sensor_contrast_neg2_regs, .size = ARRAY_SIZE(sensor_contrast_neg2_regs), }, { .regs = sensor_contrast_neg1_regs, .size = ARRAY_SIZE(sensor_contrast_neg1_regs), }, { .regs = sensor_contrast_zero_regs, .size = ARRAY_SIZE(sensor_contrast_zero_regs), }, { .regs = sensor_contrast_pos1_regs, .size = ARRAY_SIZE(sensor_contrast_pos1_regs), }, { .regs = sensor_contrast_pos2_regs, .size = ARRAY_SIZE(sensor_contrast_pos2_regs), }, { .regs = sensor_contrast_pos3_regs, .size = ARRAY_SIZE(sensor_contrast_pos3_regs), }, { .regs = sensor_contrast_pos4_regs, .size = ARRAY_SIZE(sensor_contrast_pos4_regs), }, }; /* * The saturation setttings */ static struct regval_list sensor_saturation_neg4_regs[] = { }; static struct regval_list sensor_saturation_neg3_regs[] = { }; static struct regval_list sensor_saturation_neg2_regs[] = { }; static struct regval_list sensor_saturation_neg1_regs[] = { }; static struct regval_list sensor_saturation_zero_regs[] = { }; static struct regval_list sensor_saturation_pos1_regs[] = { }; static struct regval_list sensor_saturation_pos2_regs[] = { }; static struct regval_list sensor_saturation_pos3_regs[] = { }; static struct regval_list sensor_saturation_pos4_regs[] = { }; static struct cfg_array sensor_saturation[] = { { .regs = sensor_saturation_neg4_regs, .size = ARRAY_SIZE(sensor_saturation_neg4_regs), }, { .regs = sensor_saturation_neg3_regs, .size = ARRAY_SIZE(sensor_saturation_neg3_regs), }, { .regs = sensor_saturation_neg2_regs, .size = ARRAY_SIZE(sensor_saturation_neg2_regs), }, { .regs = sensor_saturation_neg1_regs, .size = ARRAY_SIZE(sensor_saturation_neg1_regs), }, { .regs = sensor_saturation_zero_regs, .size = ARRAY_SIZE(sensor_saturation_zero_regs), }, { .regs = sensor_saturation_pos1_regs, .size = ARRAY_SIZE(sensor_saturation_pos1_regs), }, { .regs = sensor_saturation_pos2_regs, .size = ARRAY_SIZE(sensor_saturation_pos2_regs), }, { .regs = sensor_saturation_pos3_regs, .size = ARRAY_SIZE(sensor_saturation_pos3_regs), }, { .regs = sensor_saturation_pos4_regs, .size = ARRAY_SIZE(sensor_saturation_pos4_regs), }, }; /* * The exposure target setttings */ static struct regval_list sensor_ev_neg4_regs[] = { {0x3a0f, 0x10}, {0x3a10, 0x08}, {0x3a1b, 0x10}, {0x3a1e, 0x08}, {0x3a11, 0x20}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_neg3_regs[] = { {0x3a0f, 0x18}, {0x3a10, 0x10}, {0x3a1b, 0x18}, {0x3a1e, 0x10}, {0x3a11, 0x30}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_neg2_regs[] = { {0x3a0f, 0x20}, {0x3a10, 0x18}, {0x3a1b, 0x20}, {0x3a1e, 0x18}, {0x3a11, 0x41}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_neg1_regs[] = { {0x3a0f, 0x28}, {0x3a10, 0x20}, {0x3a1b, 0x28}, {0x3a1e, 0x20}, {0x3a11, 0x51}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_zero_regs[] = { {0x3a0f, 0x30}, {0x3a10, 0x28}, {0x3a1b, 0x30}, {0x3a1e, 0x28}, {0x3a11, 0x61}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_pos1_regs[] = { {0x3a0f, 0x38}, {0x3a10, 0x30}, {0x3a1b, 0x38}, {0x3a1e, 0x30}, {0x3a11, 0x61}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_pos2_regs[] = { {0x3a0f, 0x40}, {0x3a10, 0x38}, {0x3a1b, 0x40}, {0x3a1e, 0x38}, {0x3a11, 0x71}, {0x3a1f, 0x10}, }; static struct regval_list sensor_ev_pos3_regs[] = { {0x3a0f, 0x48}, {0x3a10, 0x40}, {0x3a1b, 0x48}, {0x3a1e, 0x40}, {0x3a11, 0x80}, {0x3a1f, 0x20}, }; static struct regval_list sensor_ev_pos4_regs[] = { {0x3a0f, 0x50}, {0x3a10, 0x48}, {0x3a1b, 0x50}, {0x3a1e, 0x48}, {0x3a11, 0x90}, {0x3a1f, 0x20}, }; static struct cfg_array sensor_ev[] = { { .regs = sensor_ev_neg4_regs, .size = ARRAY_SIZE(sensor_ev_neg4_regs), }, { .regs = sensor_ev_neg3_regs, .size = ARRAY_SIZE(sensor_ev_neg3_regs), }, { .regs = sensor_ev_neg2_regs, .size = ARRAY_SIZE(sensor_ev_neg2_regs), }, { .regs = sensor_ev_neg1_regs, .size = ARRAY_SIZE(sensor_ev_neg1_regs), }, { .regs = sensor_ev_zero_regs, .size = ARRAY_SIZE(sensor_ev_zero_regs), }, { .regs = sensor_ev_pos1_regs, .size = ARRAY_SIZE(sensor_ev_pos1_regs), }, { .regs = sensor_ev_pos2_regs, .size = ARRAY_SIZE(sensor_ev_pos2_regs), }, { .regs = sensor_ev_pos3_regs, .size = ARRAY_SIZE(sensor_ev_pos3_regs), }, { .regs = sensor_ev_pos4_regs, .size = ARRAY_SIZE(sensor_ev_pos4_regs), }, }; /* * Here we'll try to encapsulate the changes for just the output * video format. * */ static struct regval_list sensor_fmt_yuv422_yuyv[] = { {0x4300, 0x30}, }; static struct regval_list sensor_fmt_yuv422_yvyu[] = { {0x4300, 0x31}, }; static struct regval_list sensor_fmt_yuv422_vyuy[] = { {0x4300, 0x33}, }; static struct regval_list sensor_fmt_yuv422_uyvy[] = { {0x4300, 0x32}, }; static struct regval_list ae_average_tbl[] = { /* Whole Image Average */ {0x5688, 0x11}, /* Zone 1/Zone 0 weight */ {0x5689, 0x11}, /* Zone 3/Zone 2 weight */ {0x569a, 0x11}, /* Zone 5/Zone 4 weight */ {0x569b, 0x11}, /* Zone 7/Zone 6 weight */ {0x569c, 0x11}, /* Zone 9/Zone 8 weight */ {0x569d, 0x11}, /* Zone b/Zone a weight */ {0x569e, 0x11}, /* Zone d/Zone c weight */ {0x569f, 0x11}, /* Zone f/Zone e weight */ }; static struct regval_list ae_centerweight_tbl[] = { /* Whole Image Center More weight */ {0x5688, 0x62}, {0x5689, 0x26}, {0x568a, 0xe6}, {0x568b, 0x6e}, {0x568c, 0xea}, {0x568d, 0xae}, {0x568e, 0xa6}, {0x568f, 0x6a}, }; static data_type current_lum = 0xff; static data_type sensor_get_lum(struct v4l2_subdev *sd) { sensor_read(sd, 0x56a1, ¤t_lum); sensor_cap_dbg("check luminance=0x%x\n", current_lum); return current_lum; } /* stuff about exposure when capturing image and video*/ static int sensor_s_denoise_value(struct v4l2_subdev *sd, data_type value); static data_type ogain, oexposurelow, oexposuremid, oexposurehigh; static unsigned int preview_exp_line, preview_fps; static unsigned long preview_pclk; static unsigned int cal_cap_gain(data_type prv_gain, data_type lum) { unsigned int gain_ret = 0x18; sensor_cap_dbg("current_lum=0x%x\n", lum); if (current_lum > 0xa0) { if (ogain > 0x40) gain_ret = 0x20; else if (ogain > 0x20) gain_ret = 0x18; else gain_ret = 0x10; } else if (current_lum > 0x80) { if (ogain > 0x40) gain_ret = 0x30; else if (ogain > 0x20) gain_ret = 0x28; else gain_ret = 0x20; } else if (current_lum > 0x40) { if (ogain > 0x60) gain_ret = ogain / 3; else if (ogain > 0x40) gain_ret = ogain / 2; else gain_ret = ogain; } else if (current_lum > 0x20) { if (ogain > 0x60) gain_ret = ogain / 6; else if (ogain > 0x20) gain_ret = ogain / 2; else gain_ret = ogain; } else { sensor_cap_dbg("low_light=0x%x\n", lum); if (ogain > 0xf0) { gain_ret = 0x10; } else if (ogain > 0xe0) { gain_ret = 0x14; } else { gain_ret = 0x18; } } if (gain_ret < 0x10) gain_ret = 0x10; sensor_cap_dbg("gain return=0x%x\n", gain_ret); return gain_ret; } static int sensor_set_capture_exposure(struct v4l2_subdev *sd) { unsigned long lines_10ms; unsigned int cap_expLines; unsigned int pre_explines; unsigned long prevExp; unsigned long cap_Exp; unsigned long cap_exp_gain; unsigned long capture_gain; data_type gain, explow, expmid, exphigh; unsigned int cap_vts = 0; unsigned int cap_vts_diff = 0; unsigned int bd_step = 1; unsigned int cap_fps; data_type rdval; struct sensor_info *info = to_state(sd); #ifndef FPGA_VER cap_fps = 75 / MCLK_DIV; #else cap_fps = 37; #endif sensor_dbg("sensor_set_capture_exposure\n"); preview_fps = preview_fps * 10; if (info->low_speed == 1) cap_fps = cap_fps / 2; pre_explines = preview_exp_line; cap_expLines = 1968; if (info->band_filter == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) lines_10ms = cap_fps * cap_expLines * 1000 / 12000; else lines_10ms = cap_fps * cap_expLines * 1000 / 10000; prevExp = ((unsigned int)(oexposurehigh)) << 12; prevExp += ((unsigned int)oexposuremid) << 4; prevExp += (oexposurelow >> 4); sensor_cap_dbg("prevExp=0x%x\n", prevExp); if (0 == pre_explines || 0 == lines_10ms) return 0; if (pre_explines == 0 || preview_fps == 0) return -EFAULT; if (night_mode == 0) { cap_Exp = 1 * prevExp * cap_fps * cap_expLines / (pre_explines * preview_fps); sensor_cap_dbg("cal from prv: cap_Exp=0x%x\n", cap_Exp); } else { cap_Exp = night_mode * prevExp * cap_fps * cap_expLines / (pre_explines * preview_fps); } sensor_dbg("cap_Exp=0x%lx\n", cap_Exp); if (CAP_GAIN_CAL == 0) { capture_gain = (unsigned long)cal_cap_gain(ogain, current_lum); cap_Exp = cap_Exp * ogain / capture_gain; cap_exp_gain = cap_Exp * capture_gain; if (cap_Exp > Nfrms * cap_expLines) { capture_gain = cap_exp_gain / (Nfrms * cap_expLines); cap_Exp = Nfrms * cap_expLines; } if (capture_gain > 0xf8) capture_gain = 0xf8; } else { capture_gain = cap_manual_gain; cap_Exp = cap_Exp * ogain / capture_gain; } if (cap_Exp * 1000 > lines_10ms) { sensor_cap_dbg("lines_10ms=0x%x\n", lines_10ms); bd_step = cap_Exp * 1000 / lines_10ms; sensor_cap_dbg("bd_step=0x%x\n", bd_step); } if (cap_Exp == 0) cap_Exp = 1; sensor_dbg("cap_Exp = 0x%lx\n", cap_Exp); if ((1000 * cap_Exp - bd_step * lines_10ms) * 16 > lines_10ms) capture_gain = cap_exp_gain / cap_Exp; if (cap_Exp > 1968) { cap_vts = cap_Exp; cap_vts_diff = cap_Exp - 1968; } else { cap_vts = 1968; cap_vts_diff = 0; } explow = ((data_type) cap_Exp) << 4; expmid = (data_type) (cap_Exp >> 4) & 0xff; exphigh = (data_type) (cap_Exp >> 12); gain = (data_type) capture_gain; sensor_read(sd, 0x3503, &rdval); #ifdef DENOISE_LV_AUTO sensor_s_denoise_value(sd, 1 + gain * gain / 0x100); #else sensor_s_denoise_value(sd, DENOISE_LV); #endif sensor_write(sd, 0x380e, (data_type) (cap_vts >> 8)); sensor_write(sd, 0x380f, (data_type) (cap_vts)); sensor_write(sd, 0x350c, (data_type) ((cap_vts_diff) >> 8)); sensor_write(sd, 0x350d, (data_type) (cap_vts_diff)); sensor_write(sd, 0x350b, gain); sensor_write(sd, 0x3502, explow); sensor_write(sd, 0x3501, expmid); sensor_write(sd, 0x3500, exphigh); return 0; } static int sensor_get_pclk(struct v4l2_subdev *sd) { unsigned long pclk; data_type pre_div, mul, sys_div, pll_rdiv, bit_div, sclk_rdiv; sensor_read(sd, 0x3037, &pre_div); pre_div = pre_div & 0x0f; if (pre_div == 0) pre_div = 1; sensor_read(sd, 0x3036, &mul); if (mul >= 128) mul = mul / 2 * 2; sensor_read(sd, 0x3035, &sys_div); sys_div = (sys_div & 0xf0) >> 4; sensor_read(sd, 0x3037, &pll_rdiv); pll_rdiv = (pll_rdiv & 0x10) >> 4; pll_rdiv = pll_rdiv + 1; sensor_read(sd, 0x3034, &bit_div); bit_div = (bit_div & 0x0f); sensor_read(sd, 0x3108, &sclk_rdiv); sclk_rdiv = (sclk_rdiv & 0x03); sclk_rdiv = sclk_rdiv << sclk_rdiv; if ((pre_div && sys_div && pll_rdiv && sclk_rdiv) == 0) return -EFAULT; if (bit_div == 8) pclk = MCLK / MCLK_DIV / pre_div * mul / sys_div / pll_rdiv / 2 / sclk_rdiv; else if (bit_div == 10) pclk = MCLK / MCLK_DIV / pre_div * mul / sys_div / pll_rdiv * 2 / 5 / sclk_rdiv; else pclk = MCLK / MCLK_DIV / pre_div * mul / sys_div / pll_rdiv / 1 / sclk_rdiv; sensor_dbg("pclk = %ld\n", pclk); preview_pclk = pclk; return 0; } static int sensor_get_fps(struct v4l2_subdev *sd) { data_type vts_low, vts_high, hts_low, hts_high, vts_extra_high, vts_extra_low; unsigned long vts, hts, vts_extra; sensor_read(sd, 0x380c, &hts_high); sensor_read(sd, 0x380d, &hts_low); sensor_read(sd, 0x380e, &vts_high); sensor_read(sd, 0x380f, &vts_low); sensor_read(sd, 0x350c, &vts_extra_high); sensor_read(sd, 0x350d, &vts_extra_low); hts = hts_high * 256 + hts_low; vts = vts_high * 256 + vts_low; vts_extra = vts_extra_high * 256 + vts_extra_low; if ((hts && (vts + vts_extra)) == 0) return -EFAULT; if (sensor_get_pclk(sd)) sensor_err("get pclk error!\n"); preview_fps = preview_pclk / ((vts_extra + vts) * hts); sensor_dbg("preview fps = %d\n", preview_fps); return 0; } static int sensor_get_preview_exposure(struct v4l2_subdev *sd) { data_type vts_low, vts_high, vts_extra_high, vts_extra_low; unsigned long vts, vts_extra; sensor_read(sd, 0x350b, &ogain); sensor_read(sd, 0x3502, &oexposurelow); sensor_read(sd, 0x3501, &oexposuremid); sensor_read(sd, 0x3500, &oexposurehigh); sensor_read(sd, 0x380e, &vts_high); sensor_read(sd, 0x380f, &vts_low); sensor_read(sd, 0x350c, &vts_extra_high); sensor_read(sd, 0x350d, &vts_extra_low); vts = vts_high * 256 + vts_low; vts_extra = vts_extra_high * 256 + vts_extra_low; preview_exp_line = vts + vts_extra; sensor_dbg("preview_exp_line = %d\n", preview_exp_line); return 0; } static int sensor_set_preview_exposure(struct v4l2_subdev *sd) { data_type rdval; sensor_read(sd, 0x3503, &rdval); sensor_write(sd, 0x350b, ogain); sensor_write(sd, 0x3502, oexposurelow); sensor_write(sd, 0x3501, oexposuremid); sensor_write(sd, 0x3500, oexposurehigh); return 0; } #ifdef _FLASH_FUNC_ void check_to_flash(struct v4l2_subdev *sd) { struct sensor_info *info = to_state(sd); if (info->flash_mode == V4L2_FLASH_LED_MODE_FLASH) { to_flash = 1; } else if (info->flash_mode == V4L2_FLASH_LED_MODE_AUTO) { sensor_get_lum(sd); if (current_lum < flash_auto_level) to_flash = 1; else to_flash = 0; } else { to_flash = 0; } sensor_dbg("to_flash=%d\n", to_flash); } #endif /* stuff about auto focus */ static int sensor_download_af_fw(struct v4l2_subdev *sd) { int ret, cnt; data_type rdval; int reload_cnt = 0; struct regval_list af_fw_reset_reg[] = { {0x3000, 0x20}, }; struct regval_list af_fw_start_reg[] = { {0x3022, 0x00}, {0x3023, 0x00}, {0x3024, 0x00}, {0x3025, 0x00}, {0x3026, 0x00}, {0x3027, 0x00}, {0x3028, 0x00}, {0x3029, 0x7f}, {0x3000, 0x00}, }; ret = sensor_write_array(sd, af_fw_reset_reg, ARRAY_SIZE(af_fw_reset_reg)); if (ret < 0) { sensor_err("reset sensor MCU error\n"); return ret; } ret = cci_write_a16_d8_continuous_helper(sd, 0x8000, sensor_af_fw_regs, ARRAY_SIZE(sensor_af_fw_regs)); if (ret < 0) { sensor_err("download af fw error\n"); return ret; } ret = sensor_write_array(sd, af_fw_start_reg, ARRAY_SIZE(af_fw_start_reg)); if (ret < 0) { sensor_err("start af firmware error\n"); return ret; } msleep(10); rdval = 0xff; cnt = 0; recheck_af_fw: while (rdval != 0x70) { ret = sensor_read(sd, 0x3029, &rdval); if (ret < 0) { sensor_err ("sensor check the af firmware status err !\n"); return ret; } cnt++; if (cnt > 3) { sensor_err("AF firmware check status time out !\n"); reload_cnt++; if (reload_cnt <= 2) { sensor_err("AF firmware reload retry %d\n", reload_cnt); vfe_gpio_write(sd, PWDN, CSI_GPIO_HIGH); usleep_range(10000, 12000); vfe_gpio_write(sd, PWDN, CSI_GPIO_LOW); usleep_range(10000, 12000); goto recheck_af_fw; } return -EFAULT; } usleep_range(5000, 10000); } sensor_print("AF firmware check status complete, 0x3029 = 0x%x\n", rdval); return 0; } static int sensor_g_single_af(struct v4l2_subdev *sd) { data_type rdval; struct sensor_info *info = to_state(sd); if (info->focus_status != 1) return V4L2_AUTO_FOCUS_STATUS_IDLE; rdval = 0xff; LOG_ERR_RET(sensor_read(sd, 0x3029, &rdval)) if (rdval == 0x10) { int ret = 0; info->focus_status = 0; sensor_read(sd, 0x3028, &rdval); if (rdval == 0) { sensor_print("Single AF focus fail, 0x3028 = 0x%x\n", rdval); ret = V4L2_AUTO_FOCUS_STATUS_FAILED; } else { sensor_dbg("Single AF focus ok, 0x3028 = 0x%x\n", rdval); ret = V4L2_AUTO_FOCUS_STATUS_REACHED; } #ifdef _FLASH_FUNC_ if (info->flash_mode != V4L2_FLASH_LED_MODE_NONE) { sensor_print("shut flash when af fail/ok\n"); io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF); } #endif return ret; } else if (rdval == 0x70) { info->focus_status = 0; #ifdef _FLASH_FUNC_ if (info->flash_mode != V4L2_FLASH_LED_MODE_NONE) { sensor_print("shut flash when af idle 2\n"); io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF); } #endif return V4L2_AUTO_FOCUS_STATUS_IDLE; } else if (rdval == 0x00) { info->focus_status = 1; return V4L2_AUTO_FOCUS_STATUS_BUSY; } return V4L2_AUTO_FOCUS_STATUS_BUSY; } static int sensor_g_contin_af(struct v4l2_subdev *sd) { data_type rdval; struct sensor_info *info = to_state(sd); rdval = 0xff; LOG_ERR_RET(sensor_read(sd, 0x3029, &rdval)) if (rdval == 0x20 || rdval == 0x10) { info->focus_status = 0; sensor_read(sd, 0x3028, &rdval); if (rdval == 0) return V4L2_AUTO_FOCUS_STATUS_FAILED; else return V4L2_AUTO_FOCUS_STATUS_REACHED; } else if (rdval == 0x00) { info->focus_status = 1; return V4L2_AUTO_FOCUS_STATUS_BUSY; } else info->focus_status = 0; return V4L2_AUTO_FOCUS_STATUS_IDLE; } static int sensor_g_af_status(struct v4l2_subdev *sd) { int ret = 0; struct sensor_info *info = to_state(sd); if (info->auto_focus == 1) ret = sensor_g_contin_af(sd); else ret = sensor_g_single_af(sd); return ret; } static int sensor_g_3a_lock(struct v4l2_subdev *sd) { struct sensor_info *info = to_state(sd); return ((info->auto_focus == 0) ? V4L2_LOCK_FOCUS : ~V4L2_LOCK_FOCUS | (info->autowb == 0) ? V4L2_LOCK_WHITE_BALANCE : ~V4L2_LOCK_WHITE_BALANCE | (~V4L2_LOCK_EXPOSURE)); } static int sensor_s_init_af(struct v4l2_subdev *sd) { int ret; struct sensor_info *info = to_state(sd); ret = sensor_download_af_fw(sd); if (ret == 0) info->af_first_flag = 0; return ret; } static int sensor_s_single_af(struct v4l2_subdev *sd) { int ret; struct sensor_info *info = to_state(sd); data_type rdval = 0xff; unsigned int cnt = 0; sensor_print("sensor_s_single_af\n"); info->focus_status = 0; sensor_write(sd, 0x3023, 0x01); ret = sensor_write(sd, 0x3022, 0x03); if (ret < 0) { sensor_err("sensor tigger single af err !\n"); return ret; } while (rdval != 0 && cnt < 10) { usleep_range(1000, 1200); ret = sensor_read(sd, 0x3023, &rdval); cnt++; } if (cnt > 10) sensor_dbg("set single af timeout\n"); #ifdef _FLASH_FUNC_ if (info->flash_mode != V4L2_FLASH_LED_MODE_NONE) { check_to_flash(sd); if (to_flash == 1) { sensor_print("open torch when start single af\n"); io_set_flash_ctrl(sd, SW_CTRL_TORCH_ON); } } #endif info->focus_status = 1; info->auto_focus = 0; return 0; } static int sensor_s_continueous_af(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); sensor_print("sensor_s_continueous_af[0x%x]\n", value); if (info->focus_status == 1) { sensor_err("continous focus not accepted when single focus\n"); return -1; } if ((info->auto_focus == value)) { sensor_dbg("already in same focus mode\n"); return 0; } if (value == 1) { LOG_ERR_RET(sensor_write(sd, 0x3022, 0x04)) LOG_ERR_RET(sensor_write(sd, 0x3022, 0x80)) info->auto_focus = 1; } else { LOG_ERR_RET(sensor_write(sd, 0x3022, 0x06)) info->auto_focus = 0; } return 0; } static int sensor_s_pause_af(struct v4l2_subdev *sd) { sensor_print("sensor_s_pause_af\n"); LOG_ERR_RET(sensor_write(sd, 0x3022, 0x06)) return 0; } static int sensor_s_release_af(struct v4l2_subdev *sd) { sensor_print("sensor_s_release_af\n"); LOG_ERR_RET(sensor_write(sd, 0x3022, 0x08)) return 0; } #if 1 static int sensor_s_relaunch_af_zone(struct v4l2_subdev *sd) { sensor_print("sensor_s_relaunch_af_zone\n"); LOG_ERR_RET(sensor_write(sd, 0x3023, 0x01)) LOG_ERR_RET(sensor_write(sd, 0x3022, 0x80)) usleep_range(5000, 6000); return 0; } #endif #if 0 static int sensor_s_af_zone(struct v4l2_subdev *sd, struct v4l2_win_coordinate *win_c) { struct sensor_info *info = to_state(sd); int ret; int x1, y1, x2, y2; unsigned int xc, yc; unsigned int prv_x, prv_y; sensor_print("sensor_s_af_zone\n"); if (info->width == 0 || info->height == 0) { sensor_err("current width or height is zero!\n"); return -EINVAL; } prv_x = (int)info->width; prv_y = (int)info->height; x1 = win_c->x1; y1 = win_c->y1; x2 = win_c->x2; y2 = win_c->y2; #ifdef AF_WIN_NEW_COORD xc = prv_x * ((unsigned int)(2000 + x1 + x2) / 2) / 2000; yc = (prv_y * ((unsigned int)(2000 + y1 + y2) / 2) / 2000); #else xc = (x1 + x2) / 2; yc = (y1 + y2) / 2; #endif sensor_dbg("af zone input xc=%d,yc=%d\n", xc, yc); if (x1 > x2 || y1 > y2 || xc > info->width || yc > info->height) { sensor_dbg("invalid af win![%d,%d][%d,%d] prv[%d/%d]\n", x1, y1, x2, y2, prv_x, prv_y); return -EINVAL; } if (info->focus_status == 1) return 0; xc = (xc * 80 * 2 / info->width + 1) / 2; if ((info->width == HD720_WIDTH && info->height == HD720_HEIGHT) || (info->width == HD1080_WIDTH && info->height == HD1080_HEIGHT)) { yc = (yc * 45 * 2 / info->height + 1) / 2; } else { yc = (yc * 60 * 2 / info->height + 1) / 2; } sensor_dbg("af zone after xc=%d,yc=%d\n", xc, yc); ret = sensor_write(sd, 0x3024, xc); if (ret < 0) { sensor_err("sensor_s_af_zone_xc error!\n"); return ret; } ret = sensor_write(sd, 0x3025, yc); if (ret < 0) { sensor_err("sensor_s_af_zone_yc error!\n"); return ret; } ret = sensor_write(sd, 0x3023, 0x01); ret |= sensor_write(sd, 0x3022, 0x81); if (ret < 0) { sensor_err("sensor_s_af_zone error!\n"); return ret; } sensor_s_relaunch_af_zone(sd); return 0; } #endif static int sensor_s_3a_lock(struct v4l2_subdev *sd, int value) { int ret; value = !((value & V4L2_LOCK_FOCUS) >> 2); if (value == 0) ret = sensor_s_pause_af(sd); else ret = sensor_s_relaunch_af_zone(sd); return ret; } static int sensor_s_sharpness_auto(struct v4l2_subdev *sd) { data_type rdval; sensor_read(sd, 0x5308, &rdval); sensor_write(sd, 0x5308, rdval & 0xbf); return sensor_write_array(sd, sensor_sharpness_auto_regs, ARRAY_SIZE(sensor_sharpness_auto_regs)); } static int sensor_s_sharpness_value(struct v4l2_subdev *sd, data_type value) { data_type rdval; sensor_read(sd, 0x5308, &rdval); sensor_write(sd, 0x5308, rdval | 0x40); return sensor_write(sd, 0x5302, value); } static int sensor_s_denoise_auto(struct v4l2_subdev *sd) { data_type rdval; sensor_read(sd, 0x5308, &rdval); sensor_write(sd, 0x5308, rdval & 0xef); return sensor_write_array(sd, sensor_denoise_auto_regs, ARRAY_SIZE(sensor_denoise_auto_regs)); } static int sensor_s_denoise_value(struct v4l2_subdev *sd, data_type value) { data_type rdval; sensor_read(sd, 0x5308, &rdval); sensor_write(sd, 0x5308, rdval | 0x10); return sensor_write(sd, 0x5306, value); } static int sensor_g_hflip(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3821, &rdval)) rdval &= (1 << 1); rdval >>= 1; *value = rdval; info->hflip = *value; return 0; } static int sensor_s_hflip(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); data_type rdval; if (info->hflip == value) return 0; LOG_ERR_RET(sensor_read(sd, 0x3821, &rdval)) switch (value) { case 0: rdval &= 0xf9; break; case 1: rdval |= 0x06; break; default: return -EINVAL; } LOG_ERR_RET(sensor_write(sd, 0x3821, rdval)) usleep_range(10000, 12000); info->hflip = value; return 0; } static int sensor_g_vflip(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3820, &rdval)) rdval &= (1 << 1); *value = rdval; rdval >>= 1; info->vflip = *value; return 0; } static int sensor_s_vflip(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); data_type rdval; if (info->vflip == value) return 0; LOG_ERR_RET(sensor_read(sd, 0x3820, &rdval)) switch (value) { case 0: rdval &= 0xf9; break; case 1: rdval |= 0x06; break; default: return -EINVAL; } LOG_ERR_RET(sensor_write(sd, 0x3820, rdval)) usleep_range(10000, 12000); info->vflip = value; return 0; } static int sensor_g_autogain(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3503, &rdval)) if ((rdval & 0x02) == 0x02) *value = 0; else *value = 1; info->autogain = *value; return 0; } static int sensor_s_autogain(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3503, &rdval)) switch (value) { case 0: rdval |= 0x02; break; case 1: rdval &= 0xfd; break; default: return -EINVAL; } LOG_ERR_RET(sensor_write(sd, 0x3503, rdval)) info->autogain = value; return 0; } static int sensor_g_autoexp(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3503, &rdval)) if ((rdval & 0x01) == 0x01) *value = V4L2_EXPOSURE_MANUAL; else *value = V4L2_EXPOSURE_AUTO; info->autoexp = *value; return 0; } static int sensor_s_autoexp(struct v4l2_subdev *sd, enum v4l2_exposure_auto_type value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3503, &rdval)) switch (value) { case V4L2_EXPOSURE_AUTO: rdval &= 0xfe; break; case V4L2_EXPOSURE_MANUAL: rdval |= 0x01; break; case V4L2_EXPOSURE_SHUTTER_PRIORITY: return -EINVAL; case V4L2_EXPOSURE_APERTURE_PRIORITY: return -EINVAL; default: return -EINVAL; } LOG_ERR_RET(sensor_write(sd, 0x3503, rdval)) info->autoexp = value; return 0; } static int sensor_g_autowb(struct v4l2_subdev *sd, int *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3406, &rdval)) rdval &= (1 << 1); rdval = rdval >> 1; *value = (rdval == 1) ? 0 : 1; info->autowb = *value; return 0; } static int sensor_s_autowb(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); data_type rdval; if (info->autowb == value) return 0; LOG_ERR_RET(sensor_write_array (sd, sensor_wb_auto_regs, ARRAY_SIZE(sensor_wb_auto_regs))) LOG_ERR_RET(sensor_read(sd, 0x3406, &rdval)) switch (value) { case 0: rdval |= 0x01; break; case 1: rdval &= 0xfe; break; default: break; } LOG_ERR_RET(sensor_write(sd, 0x3406, rdval)) info->autowb = value; return 0; } static int sensor_g_hue(struct v4l2_subdev *sd, __s32 *value) { return -EINVAL; } static int sensor_s_hue(struct v4l2_subdev *sd, int value) { return -EINVAL; } static int sensor_g_gain(struct v4l2_subdev *sd, __s32 *value) { return -EINVAL; } static int sensor_s_gain(struct v4l2_subdev *sd, int value) { return -EINVAL; } static int sensor_g_band_filter(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x3a00, &rdval)) if ((rdval & (1<<5)) == (1<<5)) info->band_filter = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED; else { LOG_ERR_RET(sensor_read(sd, 0x3c00, &rdval)) if ((rdval & (1 << 2)) == (1 << 2)) info->band_filter = V4L2_CID_POWER_LINE_FREQUENCY_50HZ; else info->band_filter = V4L2_CID_POWER_LINE_FREQUENCY_60HZ; } return 0; } static int sensor_s_band_filter(struct v4l2_subdev *sd, enum v4l2_power_line_frequency value) { struct sensor_info *info = to_state(sd); data_type rdval; if (info->band_filter == value) return 0; switch (value) { case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED: LOG_ERR_RET(sensor_read(sd, 0x3a00, &rdval)) LOG_ERR_RET(sensor_write(sd, 0x3a00, rdval & 0xdf)) break; case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: LOG_ERR_RET(sensor_write(sd, 0x3c00, 0x04)) LOG_ERR_RET(sensor_write(sd, 0x3c01, 0x80)) LOG_ERR_RET(sensor_read(sd, 0x3a00, &rdval)) LOG_ERR_RET(sensor_write(sd, 0x3a00, rdval | 0x20)) break; case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: LOG_ERR_RET(sensor_write(sd, 0x3c00, 0x00)) LOG_ERR_RET(sensor_write(sd, 0x3c01, 0x80)) LOG_ERR_RET(sensor_read(sd, 0x3a00, &rdval)) LOG_ERR_RET(sensor_write(sd, 0x3a00, rdval | 0x20)) break; case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: break; default: break; } info->band_filter = value; return 0; } /* ********************************end of ******************************* */ static int sensor_g_brightness(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); *value = info->brightness; return 0; } static int sensor_s_brightness(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); if (info->brightness == value) return 0; if (value < -4 || value > 4) return -ERANGE; LOG_ERR_RET(sensor_write_array (sd, sensor_brightness[value + 4].regs, sensor_brightness[value + 4].size)) info->brightness = value; return 0; } static int sensor_g_contrast(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); *value = info->contrast; return 0; } static int sensor_s_contrast(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); if (info->contrast == value) return 0; if (value < -4 || value > 4) return -ERANGE; LOG_ERR_RET(sensor_write_array (sd, sensor_contrast[value + 4].regs, sensor_contrast[value + 4].size)) info->contrast = value; return 0; } static int sensor_g_saturation(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); *value = info->saturation; return 0; } static int sensor_s_saturation(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); if (info->saturation == value) return 0; if (value < -4 || value > 4) return -ERANGE; LOG_ERR_RET(sensor_write_array (sd, sensor_saturation[value + 4].regs, sensor_saturation[value + 4].size)) info->saturation = value; return 0; } static int sensor_g_exp_bias(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); *value = info->exp_bias; return 0; } static int sensor_s_exp_bias(struct v4l2_subdev *sd, int value) { struct sensor_info *info = to_state(sd); if (info->exp_bias == value) return 0; if (value < -4 || value > 4) return -ERANGE; sensor_write(sd, 0x3503, 0x07); sensor_get_preview_exposure(sd); sensor_write(sd, 0x3503, 0x00); LOG_ERR_RET(sensor_write_array (sd, sensor_ev[value + 4].regs, sensor_ev[value + 4].size)) info->exp_bias = value; return 0; } static int sensor_g_wb(struct v4l2_subdev *sd, int *value) { struct sensor_info *info = to_state(sd); enum v4l2_auto_n_preset_white_balance *wb_type = (enum v4l2_auto_n_preset_white_balance *)value; *wb_type = info->wb; return 0; } static int sensor_s_wb(struct v4l2_subdev *sd, enum v4l2_auto_n_preset_white_balance value) { struct sensor_info *info = to_state(sd); if (info->capture_mode == V4L2_MODE_IMAGE) return 0; if (info->wb == value) return 0; LOG_ERR_RET(sensor_write_array (sd, sensor_wb[value].regs, sensor_wb[value].size)) if (value == V4L2_WHITE_BALANCE_AUTO) info->autowb = 1; else info->autowb = 0; info->wb = value; return 0; } static int sensor_g_colorfx(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); enum v4l2_colorfx *clrfx_type = (enum v4l2_colorfx *)value; *clrfx_type = info->clrfx; return 0; } static int sensor_s_colorfx(struct v4l2_subdev *sd, enum v4l2_colorfx value) { struct sensor_info *info = to_state(sd); if (info->clrfx == value) return 0; LOG_ERR_RET(sensor_write_array (sd, sensor_colorfx[value].regs, sensor_colorfx[value].size)) info->clrfx = value; return 0; } static int sensor_g_flash_mode(struct v4l2_subdev *sd, __s32 *value) { struct sensor_info *info = to_state(sd); enum v4l2_flash_led_mode *flash_mode = (enum v4l2_flash_led_mode *)value; *flash_mode = info->flash_mode; return 0; } static int sensor_s_flash_mode(struct v4l2_subdev *sd, enum v4l2_flash_led_mode value) { struct sensor_info *info = to_state(sd); sensor_dbg("sensor_s_flash_mode[0x%d]!\n", value); info->flash_mode = value; return 0; } /* * Stuff that knows about the sensor. */ static int sensor_power(struct v4l2_subdev *sd, int on) { int ret = 0; switch (on) { case CSI_SUBDEV_STBY_ON: sensor_dbg("CSI_SUBDEV_STBY_ON!\n"); #ifdef _FLASH_FUNC_ io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF); #endif sensor_s_release_af(sd); ret = sensor_write_array(sd, sensor_sw_stby_on_regs, ARRAY_SIZE(sensor_sw_stby_on_regs)); if (ret < 0) sensor_err("soft stby falied!\n"); usleep_range(10000, 12000); sensor_print("disalbe oe!\n"); ret = sensor_write_array(sd, sensor_oe_disable_regs, ARRAY_SIZE(sensor_oe_disable_regs)); if (ret < 0) sensor_err("disalbe oe falied!\n"); cci_lock(sd); vfe_gpio_write(sd, PWDN, CSI_GPIO_HIGH); cci_unlock(sd); vfe_set_mclk(sd, OFF); break; case CSI_SUBDEV_STBY_OFF: sensor_dbg("STBY_OFF!\n"); cci_lock(sd); vfe_set_mclk_freq(sd, MCLK/MCLK_DIV); vfe_set_mclk(sd, ON); usleep_range(10000, 12000); vfe_gpio_write(sd, PWDN, CSI_GPIO_LOW); usleep_range(10000, 12000); cci_unlock(sd); sensor_print("enable oe!\n"); ret = sensor_write_array(sd, sensor_oe_enable_regs, ARRAY_SIZE(sensor_oe_enable_regs)); if (ret < 0) sensor_err("enable oe falied!\n"); ret = sensor_write_array(sd, sensor_sw_stby_off_regs, ARRAY_SIZE(sensor_sw_stby_off_regs)); if (ret < 0) sensor_err("soft stby off falied!\n"); usleep_range(10000, 12000); break; case CSI_SUBDEV_PWR_ON: sensor_print("PWR_ON!\n"); cci_lock(sd); vfe_gpio_set_status(sd, PWDN, 1); vfe_gpio_set_status(sd, RESET, 1); vfe_gpio_write(sd, PWDN, CSI_GPIO_HIGH); vfe_gpio_write(sd, RESET, CSI_GPIO_LOW); usleep_range(1000, 1200); vfe_set_mclk_freq(sd, MCLK/MCLK_DIV); vfe_set_mclk(sd, ON); usleep_range(10000, 12000); vfe_gpio_write(sd, POWER_EN, CSI_GPIO_HIGH); vfe_set_pmu_channel(sd, IOVDD, ON); vfe_set_pmu_channel(sd, AVDD, ON); vfe_set_pmu_channel(sd, DVDD, ON); vfe_set_pmu_channel(sd, AFVDD, ON); vfe_gpio_write(sd, PWDN, CSI_GPIO_LOW); usleep_range(10000, 12000); vfe_gpio_write(sd, RESET, CSI_GPIO_HIGH); usleep_range(30000, 31000); cci_unlock(sd); break; case CSI_SUBDEV_PWR_OFF: sensor_print("PWR_OFF!\n"); cci_lock(sd); vfe_set_mclk(sd, OFF); vfe_gpio_write(sd, POWER_EN, CSI_GPIO_LOW); vfe_set_pmu_channel(sd, AFVDD, OFF); vfe_set_pmu_channel(sd, DVDD, OFF); vfe_set_pmu_channel(sd, AVDD, OFF); vfe_set_pmu_channel(sd, IOVDD, OFF); usleep_range(10000, 12000); vfe_gpio_write(sd, PWDN, CSI_GPIO_HIGH); vfe_gpio_write(sd, RESET, CSI_GPIO_LOW); vfe_gpio_set_status(sd, RESET, 0); vfe_gpio_set_status(sd, PWDN, 0); cci_unlock(sd); break; default: return -EINVAL; } return 0; } static int sensor_reset(struct v4l2_subdev *sd, u32 val) { switch (val) { case 0: vfe_gpio_write(sd, RESET, CSI_GPIO_HIGH); usleep_range(10000, 12000); break; case 1: vfe_gpio_write(sd, RESET, CSI_GPIO_LOW); usleep_range(10000, 12000); break; default: return -EINVAL; } return 0; } static int sensor_detect(struct v4l2_subdev *sd) { data_type rdval; LOG_ERR_RET(sensor_read(sd, 0x300a, &rdval)) if (rdval != 0x56) return -ENODEV; LOG_ERR_RET(sensor_read(sd, 0x300b, &rdval)) if (rdval != 0x40) return -ENODEV; return 0; } static int sensor_init(struct v4l2_subdev *sd, u32 val) { int ret; struct sensor_info *info = to_state(sd); #ifdef _FLASH_FUNC_ struct vfe_dev *dev = (struct vfe_dev *)dev_get_drvdata(sd->v4l2_dev->dev); #endif sensor_dbg("sensor_init 0x%x\n", val); /*Make sure it is a target sensor*/ ret = sensor_detect(sd); if (ret) { sensor_err("chip found is not an target chip.\n"); return ret; } vfe_get_standby_mode(sd, &info->stby_mode); if ((info->stby_mode == HW_STBY || info->stby_mode == SW_STBY) \ && info->init_first_flag == 0) { sensor_print("stby_mode and init_first_flag = 0\n"); return 0; } ogain = 0x28; oexposurelow = 0x00; oexposuremid = 0x3d; oexposurehigh = 0x00; info->focus_status = 0; info->low_speed = 0; info->width = 0; info->height = 0; info->brightness = 0; info->contrast = 0; info->saturation = 0; info->hue = 0; info->hflip = 0; info->vflip = 0; info->gain = 0; info->autogain = 1; info->exp_bias = 0; info->autoexp = 1; info->autowb = 1; info->wb = V4L2_WHITE_BALANCE_AUTO; info->clrfx = V4L2_COLORFX_NONE; info->band_filter = V4L2_CID_POWER_LINE_FREQUENCY_50HZ; info->tpf.numerator = 1; info->tpf.denominator = 30; /* 30fps */ ret = sensor_write_array(sd, sensor_default_regs, ARRAY_SIZE(sensor_default_regs)); if (ret < 0) { sensor_err("write sensor_default_regs error\n"); return ret; } sensor_s_band_filter(sd, V4L2_CID_POWER_LINE_FREQUENCY_50HZ); if (info->stby_mode == 0) info->init_first_flag = 0; info->preview_first_flag = 1; night_mode = 0; Nfrms = MAX_FRM_CAP; if (1 == AE_CW) sensor_write_array(sd, ae_centerweight_tbl, ARRAY_SIZE(ae_centerweight_tbl)); else sensor_write_array(sd, ae_average_tbl, ARRAY_SIZE(ae_average_tbl)); #ifdef _FLASH_FUNC_ if (dev->flash_used == 1) sunxi_flash_info_init(dev->flash_sd); #endif return 0; } static int sensor_g_exif(struct v4l2_subdev *sd, struct sensor_exif_attribute *exif) { int ret = 0; exif->fnumber = 220; exif->focal_length = 180; exif->brightness = 125; exif->flash_fire = 0; exif->iso_speed = 200; exif->exposure_time_num = 1; exif->exposure_time_den = 15; return ret; } static void sensor_s_af_win(struct v4l2_subdev *sd, struct v4l2_win_setting *af_win) { /*sensor_s_af_zone(sd, &af_win->coor);*/ } static void sensor_s_ae_win(struct v4l2_subdev *sd, struct v4l2_win_setting *ae_win) { } static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { int ret = 0; switch (cmd) { case GET_SENSOR_EXIF: sensor_g_exif(sd, (struct sensor_exif_attribute *)arg); break; case SET_AUTO_FOCUS_WIN: sensor_s_af_win(sd, (struct v4l2_win_setting *)arg); break; case SET_AUTO_EXPOSURE_WIN: sensor_s_ae_win(sd, (struct v4l2_win_setting *)arg); break; default: return -EINVAL; } return ret; } /* * Store information about the video data format. */ static struct sensor_format_struct { __u8 *desc; enum v4l2_mbus_pixelcode mbus_code; struct regval_list *regs; int regs_size; int bpp; /* Bytes per pixel */ } sensor_formats[] = { { .desc = "YUYV 4:2:2", .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, .regs = sensor_fmt_yuv422_yuyv, .regs_size = ARRAY_SIZE(sensor_fmt_yuv422_yuyv), .bpp = 2, }, { .desc = "YVYU 4:2:2", .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, .regs = sensor_fmt_yuv422_yvyu, .regs_size = ARRAY_SIZE(sensor_fmt_yuv422_yvyu), .bpp = 2, }, { .desc = "UYVY 4:2:2", .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, .regs = sensor_fmt_yuv422_uyvy, .regs_size = ARRAY_SIZE(sensor_fmt_yuv422_uyvy), .bpp = 2, }, { .desc = "VYUY 4:2:2", .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, .regs = sensor_fmt_yuv422_vyuy, .regs_size = ARRAY_SIZE(sensor_fmt_yuv422_vyuy), .bpp = 2, }, }; #define N_FMTS ARRAY_SIZE(sensor_formats) /* * Then there is the issue of window sizes. Try to capture the info here. */ static struct sensor_win_size sensor_win_sizes[] = { /* qsxga: 2592*1936 */ { .width = QSXGA_WIDTH, .height = QSXGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_qsxga_regs, .regs_size = ARRAY_SIZE(sensor_qsxga_regs), .set_size = NULL, }, /* qxga: 2048*1536 */ { .width = QXGA_WIDTH, .height = QXGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_qxga_regs, .regs_size = ARRAY_SIZE(sensor_qxga_regs), .set_size = NULL, }, /* 1080P */ { .width = HD1080_WIDTH, .height = HD1080_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_1080p_regs, .regs_size = ARRAY_SIZE(sensor_1080p_regs), .set_size = NULL, }, /* UXGA */ { .width = UXGA_WIDTH, .height = UXGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_uxga_regs, .regs_size = ARRAY_SIZE(sensor_uxga_regs), .set_size = NULL, }, /* SXGA */ { .width = SXGA_WIDTH, .height = SXGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_sxga_regs, .regs_size = ARRAY_SIZE(sensor_sxga_regs), .set_size = NULL, }, /* 720p */ { .width = HD720_WIDTH, .height = HD720_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_720p_regs, .regs_size = ARRAY_SIZE(sensor_720p_regs), .set_size = NULL, }, /* XGA */ { .width = XGA_WIDTH, .height = XGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_xga_regs, .regs_size = ARRAY_SIZE(sensor_xga_regs), .set_size = NULL, }, /* SVGA */ { .width = SVGA_WIDTH, .height = SVGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_svga_regs, .regs_size = ARRAY_SIZE(sensor_svga_regs), .set_size = NULL, }, /* VGA */ { .width = VGA_WIDTH, .height = VGA_HEIGHT, .hoffset = 0, .voffset = 0, .regs = sensor_vga_regs, .regs_size = ARRAY_SIZE(sensor_vga_regs), .set_size = NULL, }, }; #define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes)) static int sensor_enum_fmt(struct v4l2_subdev *sd, unsigned index, enum v4l2_mbus_pixelcode *code) { if (index >= N_FMTS) return -EINVAL; *code = sensor_formats[index].mbus_code; return 0; } static int sensor_enum_size(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize) { if (fsize->index > (N_WIN_SIZES-1)) return -EINVAL; fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; fsize->discrete.width = sensor_win_sizes[fsize->index].width; fsize->discrete.height = sensor_win_sizes[fsize->index].height; return 0; } static int sensor_try_fmt_internal(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt, struct sensor_format_struct **ret_fmt, struct sensor_win_size **ret_wsize) { int index; struct sensor_win_size *wsize; for (index = 0; index < N_FMTS; index++) if (sensor_formats[index].mbus_code == fmt->code) break; if (index >= N_FMTS) return -EINVAL; if (ret_fmt != NULL) *ret_fmt = sensor_formats + index; /* * Fields: the sensor devices claim to be progressive. */ fmt->field = V4L2_FIELD_NONE; /* * Round requested image size down to the nearest * we support, but not below the smallest. */ for (wsize = sensor_win_sizes; wsize < sensor_win_sizes + N_WIN_SIZES; wsize++) if (fmt->width >= wsize->width && fmt->height >= wsize->height) break; if (wsize >= sensor_win_sizes + N_WIN_SIZES) wsize--; /* Take the smallest one */ if (ret_wsize != NULL) *ret_wsize = wsize; /* * Note the size we'll actually handle. */ fmt->width = wsize->width; fmt->height = wsize->height; return 0; } static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { return sensor_try_fmt_internal(sd, fmt, NULL, NULL); } static int sensor_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { cfg->type = V4L2_MBUS_PARALLEL; cfg->flags = V4L2_MBUS_MASTER | VREF_POL | HREF_POL | CLK_POL ; return 0; } /* * Set a format. */ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { int ret; struct sensor_format_struct *sensor_fmt; struct sensor_win_size *wsize; struct sensor_info *info = to_state(sd); sensor_dbg("sensor_s_fmt\n"); sensor_write_array(sd, sensor_oe_disable_regs, ARRAY_SIZE(sensor_oe_disable_regs)); ret = sensor_try_fmt_internal(sd, fmt, &sensor_fmt, &wsize); if (ret) return ret; if (info->capture_mode == V4L2_MODE_VIDEO) { #ifdef _FLASH_FUNC_ if (info->flash_mode != V4L2_FLASH_LED_MODE_NONE) io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF); #endif } else if (info->capture_mode == V4L2_MODE_IMAGE) { ret = sensor_s_autoexp(sd, V4L2_EXPOSURE_MANUAL); if (ret < 0) sensor_err("sensor_s_autoexp off err when capturing image!\n"); ret = sensor_s_autogain(sd, 0); if (ret < 0) sensor_err("sensor_s_autogain off err when capturing image!\n"); if (wsize->width > SVGA_WIDTH) { #ifdef _FLASH_FUNC_ check_to_flash(sd); #endif sensor_get_lum(sd); sensor_get_preview_exposure(sd); sensor_get_fps(sd); } #ifdef _FLASH_FUNC_ if (info->flash_mode != V4L2_FLASH_LED_MODE_NONE) { if (to_flash == 1) { vfe_dev_cap_dbg("open flash when capture\n"); io_set_flash_ctrl(sd, SW_CTRL_FLASH_ON); sensor_get_lum(sd); sensor_get_preview_exposure(sd); sensor_get_fps(sd); msleep(50); } } #endif ret = sensor_s_autowb(sd, 0); if (ret < 0) sensor_err("sensor_s_autowb off err when capturing image!\n"); } else { sensor_err("sensor_s_autowb image!\n"); sensor_err("step1\n"); } sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size); if (wsize->regs) LOG_ERR_RET(sensor_write_array(sd, wsize->regs, wsize->regs_size)) if (wsize->set_size) LOG_ERR_RET(wsize->set_size(sd)) sensor_s_hflip(sd, info->hflip); sensor_s_vflip(sd, info->vflip); if (info->capture_mode == V4L2_MODE_VIDEO || info->capture_mode == V4L2_MODE_PREVIEW) { #ifdef AUTO_FPS if (info->capture_mode == V4L2_MODE_PREVIEW) sensor_write_array(sd, sensor_auto_fps_mode, ARRAY_SIZE(sensor_auto_fps_mode)); else sensor_write_array(sd, sensor_fix_fps_mode, ARRAY_SIZE(sensor_fix_fps_mode)); #endif ret = sensor_set_preview_exposure(sd); if (ret < 0) sensor_err("sensor_set_preview_exposure err !\n"); ret = sensor_s_autoexp(sd, V4L2_EXPOSURE_AUTO); if (ret < 0) sensor_err("sensor_s_autoexp on err when capturing video!\n"); ret = sensor_s_autogain(sd, 1); if (ret < 0) sensor_err("sensor_s_autogain on err when capturing video!\n"); if (info->wb == V4L2_WHITE_BALANCE_AUTO) { ret = sensor_s_autowb(sd, 1); if (ret < 0) sensor_err("sensor_s_autowb on err when capturing image!\n"); } if (info->capture_mode == V4L2_MODE_VIDEO) { if (wsize->width == 640) { sensor_s_sharpness_value(sd, 0x20); sensor_s_denoise_value(sd, 0x04); } else if (wsize->height == 960) { sensor_s_sharpness_value(sd, 0x08); sensor_s_denoise_value(sd, 0x08); } else if (wsize->height == 720) { sensor_s_sharpness_value(sd, 0x08); sensor_s_denoise_value(sd, 0x04); } else if (wsize->width == 1920) { sensor_s_sharpness_value(sd, 0x08); sensor_s_denoise_value(sd, 0x14); } else { sensor_s_sharpness_auto(sd); sensor_s_denoise_auto(sd); } } else if (info->capture_mode == V4L2_MODE_PREVIEW) { sensor_s_sharpness_value(sd, 0x20); sensor_s_denoise_value(sd, 0x10); } else sensor_err("capture_mode err when capturing image!\n"); if (info->low_speed == 1) { if (info->preview_first_flag == 1) { info->preview_first_flag = 0; msleep(600); } else msleep(200); } if ((info->width != QSXGA_WIDTH) && (info->preview_first_flag != 1)) { ret = sensor_s_relaunch_af_zone(sd); if (ret < 0) sensor_err("sensor_s_relaunch_af_zone err !\n"); ret = sensor_write(sd, 0x3022, 0x03); if (ret < 0) sensor_err("sensor_s_single_af err !\n"); if (info->auto_focus == 1) sensor_s_continueous_af(sd, 1); msleep(100); } else msleep(150); } else { if (wsize->width > SVGA_WIDTH) { ret = sensor_set_capture_exposure(sd); if (ret < 0) sensor_err("sensor_set_capture_exposure err !\n"); } sensor_s_sharpness_value(sd, SHARPNESS); if (info->low_speed == 1) { data_type rdval; sensor_read(sd, 0x3035, &rdval); sensor_write(sd, 0x3035, (rdval&0x0f)|((rdval&0xf0)*2)); } msleep(150); } info->fmt = sensor_fmt; info->width = wsize->width; info->height = wsize->height; sensor_print("s_fmt set width = %d, height = %d\n", wsize->width, wsize->height); sensor_write_array(sd, sensor_oe_enable_regs, ARRAY_SIZE(sensor_oe_enable_regs)); return 0; } /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. */ static int sensor_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; struct sensor_info *info = to_state(sd); if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; memset(cp, 0, sizeof(struct v4l2_captureparm)); cp->capability = V4L2_CAP_TIMEPERFRAME; cp->capturemode = info->capture_mode; cp->timeperframe.numerator = info->tpf.numerator; cp->timeperframe.denominator = info->tpf.denominator; return 0; } static int sensor_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sensor_info *info = to_state(sd); data_type div; sensor_dbg("sensor_s_parm\n"); if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { sensor_dbg("parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); return -EINVAL; } if (info->tpf.numerator == 0) { sensor_dbg("info->tpf.numerator == 0\n"); return -EINVAL; } info->capture_mode = cp->capturemode; if (info->capture_mode == V4L2_MODE_IMAGE) { sensor_dbg("capture mode can not set frame rate!\n"); return 0; } if (tpf->numerator == 0 || tpf->denominator == 0) { tpf->numerator = 1; tpf->denominator = SENSOR_FRAME_RATE; /* Reset to full rate */ sensor_err("sensor frame rate reset to full rate!\n"); } div = SENSOR_FRAME_RATE / (tpf->denominator / tpf->numerator); if (div > 15 || div == 0) { sensor_print("SENSOR_FRAME_RATE=%d\n", SENSOR_FRAME_RATE); sensor_print("tpf->denominator=%d\n", tpf->denominator); sensor_print("tpf->numerator=%d\n", tpf->numerator); return -EINVAL; } sensor_dbg("set frame rate %d\n", tpf->denominator / tpf->numerator); info->tpf.denominator = SENSOR_FRAME_RATE; info->tpf.numerator = div; if (info->tpf.denominator / info->tpf.numerator < 30) info->low_speed = 1; return 0; } /* * Code for dealing with controls. * fill with different sensor module * different sensor module has different settings here * if not support the follow function ,retrun -EINVAL */ /* *****************************begin of ******************************* */ static int sensor_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { /* Fill in min, max, step and default value for these controls. */ /* see include/linux/videodev2.h for details */ /* see sensor_s_parm and sensor_g_parm for the meaning of value */ switch (qc->id) { case V4L2_CID_VFLIP: case V4L2_CID_HFLIP: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_EXPOSURE: case V4L2_CID_AUTO_EXPOSURE_BIAS: return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0); case V4L2_CID_EXPOSURE_AUTO: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return v4l2_ctrl_query_fill(qc, 0, 9, 1, 1); case V4L2_CID_AUTO_WHITE_BALANCE: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); case V4L2_CID_COLORFX: return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0); case V4L2_CID_FLASH_LED_MODE: return v4l2_ctrl_query_fill(qc, 0, 4, 1, 0); case V4L2_CID_3A_LOCK: return v4l2_ctrl_query_fill(qc, 0, V4L2_LOCK_FOCUS, 1, 0); case V4L2_CID_AUTO_FOCUS_INIT: case V4L2_CID_AUTO_FOCUS_RELEASE: case V4L2_CID_AUTO_FOCUS_START: case V4L2_CID_AUTO_FOCUS_STOP: case V4L2_CID_AUTO_FOCUS_STATUS: return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); case V4L2_CID_FOCUS_AUTO: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); } return -EINVAL; } static int sensor_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: return sensor_g_brightness(sd, &ctrl->value); case V4L2_CID_CONTRAST: return sensor_g_contrast(sd, &ctrl->value); case V4L2_CID_SATURATION: return sensor_g_saturation(sd, &ctrl->value); case V4L2_CID_HUE: return sensor_g_hue(sd, &ctrl->value); case V4L2_CID_VFLIP: return sensor_g_vflip(sd, &ctrl->value); case V4L2_CID_HFLIP: return sensor_g_hflip(sd, &ctrl->value); case V4L2_CID_GAIN: return sensor_g_gain(sd, &ctrl->value); case V4L2_CID_AUTOGAIN: return sensor_g_autogain(sd, &ctrl->value); case V4L2_CID_EXPOSURE: case V4L2_CID_AUTO_EXPOSURE_BIAS: return sensor_g_exp_bias(sd, &ctrl->value); case V4L2_CID_EXPOSURE_AUTO: return sensor_g_autoexp(sd, &ctrl->value); case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return sensor_g_wb(sd, &ctrl->value); case V4L2_CID_AUTO_WHITE_BALANCE: return sensor_g_autowb(sd, &ctrl->value); case V4L2_CID_COLORFX: return sensor_g_colorfx(sd, &ctrl->value); case V4L2_CID_FLASH_LED_MODE: return sensor_g_flash_mode(sd, &ctrl->value); case V4L2_CID_POWER_LINE_FREQUENCY: return sensor_g_band_filter(sd, &ctrl->value); case V4L2_CID_3A_LOCK: return sensor_g_3a_lock(sd); case V4L2_CID_AUTO_FOCUS_STATUS: return sensor_g_af_status(sd); } return -EINVAL; } static int sensor_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: return sensor_s_brightness(sd, ctrl->value); case V4L2_CID_CONTRAST: return sensor_s_contrast(sd, ctrl->value); case V4L2_CID_SATURATION: return sensor_s_saturation(sd, ctrl->value); case V4L2_CID_HUE: return sensor_s_hue(sd, ctrl->value); case V4L2_CID_VFLIP: return sensor_s_vflip(sd, ctrl->value); case V4L2_CID_HFLIP: return sensor_s_hflip(sd, ctrl->value); case V4L2_CID_GAIN: return sensor_s_gain(sd, ctrl->value); case V4L2_CID_AUTOGAIN: return sensor_s_autogain(sd, ctrl->value); case V4L2_CID_EXPOSURE: case V4L2_CID_AUTO_EXPOSURE_BIAS: return sensor_s_exp_bias(sd, ctrl->value); case V4L2_CID_EXPOSURE_AUTO: return sensor_s_autoexp(sd, (enum v4l2_exposure_auto_type)ctrl->value); case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return sensor_s_wb(sd, (enum v4l2_auto_n_preset_white_balance)ctrl->value); case V4L2_CID_AUTO_WHITE_BALANCE: return sensor_s_autowb(sd, ctrl->value); case V4L2_CID_COLORFX: return sensor_s_colorfx(sd, (enum v4l2_colorfx)ctrl->value); case V4L2_CID_FLASH_LED_MODE: return sensor_s_flash_mode(sd, (enum v4l2_flash_led_mode)ctrl->value); case V4L2_CID_POWER_LINE_FREQUENCY: return sensor_s_band_filter(sd, (enum v4l2_power_line_frequency)ctrl->value); case V4L2_CID_3A_LOCK: return sensor_s_3a_lock(sd, ctrl->value); case V4L2_CID_AUTO_FOCUS_INIT: return sensor_s_init_af(sd); case V4L2_CID_AUTO_FOCUS_RELEASE: return sensor_s_release_af(sd); case V4L2_CID_AUTO_FOCUS_START: return sensor_s_single_af(sd); case V4L2_CID_AUTO_FOCUS_STOP: return sensor_s_pause_af(sd); case V4L2_CID_FOCUS_AUTO: return sensor_s_continueous_af(sd, ctrl->value); default: return -EINVAL; } return -EINVAL; } static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SENSOR, 0); } static const struct v4l2_subdev_core_ops sensor_core_ops = { .g_chip_ident = sensor_g_chip_ident, .g_ctrl = sensor_g_ctrl, .s_ctrl = sensor_s_ctrl, .queryctrl = sensor_queryctrl, .reset = sensor_reset, .init = sensor_init, .s_power = sensor_power, .ioctl = sensor_ioctl, }; static const struct v4l2_subdev_video_ops sensor_video_ops = { .enum_mbus_fmt = sensor_enum_fmt, .enum_framesizes = sensor_enum_size, .try_mbus_fmt = sensor_try_fmt, .s_mbus_fmt = sensor_s_fmt, .s_parm = sensor_s_parm, .g_parm = sensor_g_parm, .g_mbus_config = sensor_g_mbus_config, }; static const struct v4l2_subdev_ops sensor_ops = { .core = &sensor_core_ops, .video = &sensor_video_ops, }; static struct cci_driver cci_drv = { .name = SENSOR_NAME, .addr_width = CCI_BITS_16, .data_width = CCI_BITS_8, }; static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct v4l2_subdev *sd; struct sensor_info *info; info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL); if (info == NULL) return -ENOMEM; sd = &info->sd; glb_sd = sd; cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv); info->fmt = &sensor_formats[0]; info->af_first_flag = 1; info->init_first_flag = 1; info->auto_focus = 0; return 0; } static int sensor_remove(struct i2c_client *client) { struct v4l2_subdev *sd; sd = cci_dev_remove_helper(client, &cci_drv); pr_debug("sensor_remove ov5640 sd = %p!\n", sd); kfree(to_state(sd)); return 0; } static const struct i2c_device_id sensor_id[] = { {SENSOR_NAME, 0}, {} }; MODULE_DEVICE_TABLE(i2c, sensor_id); static struct i2c_driver sensor_driver = { .driver = { .owner = THIS_MODULE, .name = SENSOR_NAME, }, .probe = sensor_probe, .remove = sensor_remove, .id_table = sensor_id, }; static __init int init_sensor(void) { #ifdef CONFIG_ARCH_SUN9IW1P1 A80_VERSION = sunxi_get_soc_ver(); if (A80_VERSION >= SUN9IW1P1_REV_B) MCLK_DIV = 1; else MCLK_DIV = 2; pr_debug("A80_VERSION = %d , SUN9IW1P1_REV_B = %d, MCLK_DIV = %d\n", A80_VERSION, SUN9IW1P1_REV_B, MCLK_DIV); #else MCLK_DIV = 1; #endif return cci_dev_init_helper(&sensor_driver); } static __exit void exit_sensor(void) { cci_dev_exit_helper(&sensor_driver); } module_init(init_sensor); module_exit(exit_sensor);