From 848b0c53fade7f9bf9c43f39e74e821deaf40eb1 Mon Sep 17 00:00:00 2001 From: Jake Day Date: Wed, 16 Aug 2017 11:24:50 -0400 Subject: [PATCH] adding drivers for rear surface camera --- drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ad5823.c | 226 ++ drivers/media/i2c/ad5823.h | 92 + drivers/media/i2c/ov8865.c | 2176 +++++++++++++++++++ drivers/media/i2c/ov8865.h | 2723 ++++++++++++++++++++++++ drivers/media/i2c/ov8865_bld_otp.c | 588 +++++ drivers/media/i2c/ov8865_bld_otp.h | 170 ++ include/linux/atomisp.h | 1330 ++++++++++++ include/linux/atomisp_css15.h | 1097 ++++++++++ include/linux/atomisp_platform.h | 224 ++ include/linux/atomisp_platform_css15.h | 151 ++ include/media/v4l2-chip-ident.h | 352 +++ 13 files changed, 9141 insertions(+) create mode 100644 drivers/media/i2c/ad5823.c create mode 100644 drivers/media/i2c/ad5823.h create mode 100644 drivers/media/i2c/ov8865.c create mode 100644 drivers/media/i2c/ov8865.h create mode 100644 drivers/media/i2c/ov8865_bld_otp.c create mode 100644 drivers/media/i2c/ov8865_bld_otp.h create mode 100644 include/linux/atomisp.h create mode 100644 include/linux/atomisp_css15.h create mode 100644 include/linux/atomisp_platform.h create mode 100644 include/linux/atomisp_platform_css15.h create mode 100644 include/media/v4l2-chip-ident.h diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index aaa9471c7..a112557e4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -585,6 +585,17 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV8865 + tristate "OVT OV8865 sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This is a Video4Linux2 sensor-level driver for the OVT + OV8865 raw camera. + + OVT is a 8MP raw sensor. + + It currently only works with the atomisp driver. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 62323ec66..6e2e5e451 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_VIDEO_OV5645) += ov5645.o obj-$(CONFIG_VIDEO_OV5647) += ov5647.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV8865) += ov8865.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o diff --git a/drivers/media/i2c/ad5823.c b/drivers/media/i2c/ad5823.c new file mode 100644 index 000000000..db315782f --- /dev/null +++ b/drivers/media/i2c/ad5823.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad5823.h" + +static struct ad5823_device ad5823_dev; +static int ad5823_i2c_write(struct i2c_client *client, u8 reg, u8 val) +{ + struct i2c_msg msg; + u8 buf[2]; + buf[0] = reg; + buf[1] = val; + msg.addr = AD5823_VCM_ADDR; + msg.flags = 0; + msg.len = AD5823_REG_LENGTH + AD5823_8BIT; + msg.buf = &buf[0]; + + if (i2c_transfer(client->adapter, &msg, 1) != 1) + return -EIO; + return 0; +} + +static int ad5823_i2c_read(struct i2c_client *client, u8 reg, u8 *val) +{ + struct i2c_msg msg[2]; + u8 buf[2]; + buf[0] = reg; + buf[1] = 0; + + msg[0].addr = AD5823_VCM_ADDR; + msg[0].flags = 0; + msg[0].len = AD5823_REG_LENGTH; + msg[0].buf = &buf[0]; + + msg[1].addr = AD5823_VCM_ADDR; + msg[1].flags = I2C_M_RD; + msg[1].len = AD5823_8BIT; + msg[1].buf = &buf[1]; + *val = 0; + if (i2c_transfer(client->adapter, msg, 2) != 2) + return -EIO; + *val = buf[1]; + return 0; +} + +int ad5823_vcm_power_up(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = -EINVAL; + u8 vcm_mode_reg_val[4] = { + AD5823_ARC_RES0, + AD5823_ARC_RES1, + AD5823_ARC_RES2, + AD5823_ESRC + }; + + /* Enable power */ + if (ad5823_dev.platform_data) { + ret = ad5823_dev.platform_data->power_ctrl(sd, 1); + if (ret) + return ret; + } + /* + * waiting time requested by AD5823(vcm) + */ + usleep_range(1000, 2000); + + /* + * Set vcm ringing control mode. + */ + if (ad5823_dev.vcm_mode != AD5823_DIRECT) { + ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, + AD5823_RING_CTRL_ENABLE); + if (ret) + return ret; + + ret = ad5823_i2c_write(client, AD5823_REG_MODE, + vcm_mode_reg_val[ad5823_dev.vcm_mode]); + if (ret) + return ret; + } else { + ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, + AD5823_RING_CTRL_DISABLE); + if (ret) + return ret; + } + + return ret; +} + +int ad5823_vcm_power_down(struct v4l2_subdev *sd) +{ + int ret = -ENODEV; + + if (ad5823_dev.platform_data) + ret = ad5823_dev.platform_data->power_ctrl(sd, 0); + + return ret; +} + + +int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = -EINVAL; + u8 vcm_code; + + ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code); + if (ret) + return ret; + + /* set reg VCM_CODE_MSB Bit[1:0] */ + vcm_code = (vcm_code & VCM_CODE_MSB_MASK) | ((val >> 8) & ~VCM_CODE_MSB_MASK); + ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code); + if (ret) + return ret; + + /* set reg VCM_CODE_LSB Bit[7:0] */ + ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, (val & 0xff)); + if (ret) + return ret; + + /* set required vcm move time */ + vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF + - AD5823_HIGH_FREQ_RANGE; + ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code); + + return ret; +} + +int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value) +{ + int ret; + + value = min(value, AD5823_MAX_FOCUS_POS); + ret = ad5823_t_focus_vcm(sd, value); + if (ret == 0) { + ad5823_dev.number_of_steps = value - ad5823_dev.focus; + ad5823_dev.focus = value; + ktime_get_ts(&ad5823_dev.timestamp_t_focus_abs); + } + + return ret; +} + +int ad5823_t_focus_rel(struct v4l2_subdev *sd, s32 value) +{ + return ad5823_t_focus_abs(sd, ad5823_dev.focus + value); +} + +int ad5823_q_focus_status(struct v4l2_subdev *sd, s32 *value) +{ + u32 status = 0; + struct timespec temptime; + const struct timespec timedelay = { + 0, + min_t(u32, abs(ad5823_dev.number_of_steps)*DELAY_PER_STEP_NS, + DELAY_MAX_PER_STEP_NS), + }; + + ktime_get_ts(&temptime); + + temptime = timespec_sub(temptime, (ad5823_dev.timestamp_t_focus_abs)); + + if (timespec_compare(&temptime, &timedelay) <= 0) + status = ATOMISP_FOCUS_STATUS_MOVING + | ATOMISP_FOCUS_HP_IN_PROGRESS; + else + status = ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE + | ATOMISP_FOCUS_HP_COMPLETE; + + *value = status; + + return 0; +} + +int ad5823_q_focus_abs(struct v4l2_subdev *sd, s32 *value) +{ + s32 val; + + ad5823_q_focus_status(sd, &val); + + if (val & ATOMISP_FOCUS_STATUS_MOVING) + *value = ad5823_dev.focus - ad5823_dev.number_of_steps; + else + *value = ad5823_dev.focus ; + + return 0; +} + +int ad5823_t_vcm_slew(struct v4l2_subdev *sd, s32 value) +{ + return 0; +} + +int ad5823_t_vcm_timing(struct v4l2_subdev *sd, s32 value) +{ + return 0; +} + +int ad5823_vcm_init(struct v4l2_subdev *sd) +{ + /* set vcm mode to DIRECT */ + ad5823_dev.vcm_mode = AD5823_DIRECT; + ad5823_dev.platform_data = camera_get_af_platform_data(); + return ad5823_dev.platform_data ? 0 : -ENODEV; +} + diff --git a/drivers/media/i2c/ad5823.h b/drivers/media/i2c/ad5823.h new file mode 100644 index 000000000..794f91fda --- /dev/null +++ b/drivers/media/i2c/ad5823.h @@ -0,0 +1,92 @@ +/* + * Support for AD5823 VCM. + * + * Copyright (c) 2013 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef __AD5823_H__ +#define __AD5823_H__ + +#include +#include + + +#define AD5823_VCM_ADDR 0x0c + +#define AD5823_REG_RESET 0x01 +#define AD5823_REG_MODE 0x02 +#define AD5823_REG_VCM_MOVE_TIME 0x03 +#define AD5823_REG_VCM_CODE_MSB 0x04 +#define AD5823_REG_VCM_CODE_LSB 0x05 +#define AD5823_REG_VCM_THRESHOLD_MSB 0x06 +#define AD5823_REG_VCM_THRESHOLD_LSB 0x07 + +#define AD5823_REG_LENGTH 0x1 + +#define AD5823_RING_CTRL_ENABLE 0x04 +#define AD5823_RING_CTRL_DISABLE 0x00 + +#define AD5823_RESONANCE_PERIOD 100000 +#define AD5823_RESONANCE_COEF 512 +#define AD5823_HIGH_FREQ_RANGE 0x80 + +#define VCM_CODE_MSB_MASK 0xfc + +enum ad5823_tok_type { + AD5823_8BIT = 0x1, + AD5823_16BIT = 0x2, +}; + +enum ad5823_vcm_mode { + AD5823_ARC_RES0 = 0x0, /* Actuator response control RES1 */ + AD5823_ARC_RES1 = 0x1, /* Actuator response control RES0.5 */ + AD5823_ARC_RES2 = 0x2, /* Actuator response control RES2 */ + AD5823_ESRC = 0x3, /* Enhanced slew rate control */ + AD5823_DIRECT = 0x4, /* Direct control */ +}; + +/* ad5823 device structure */ +struct ad5823_device { + struct timespec timestamp_t_focus_abs; + enum ad5823_vcm_mode vcm_mode; + s16 number_of_steps; + bool initialized; /* true if ad5823 is detected */ + s32 focus; /* Current focus value */ + struct timespec focus_time; /* Time when focus was last time set */ + __u8 buffer[4]; /* Used for i2c transactions */ + const struct camera_af_platform_data *platform_data; +}; + +#define AD5823_INVALID_CONFIG 0xffffffff +#define AD5823_MAX_FOCUS_POS 1023 + + +#define DELAY_PER_STEP_NS 1000000 +#define DELAY_MAX_PER_STEP_NS (1000000 * 1023) + +int ad5823_vcm_power_up(struct v4l2_subdev *sd); +int ad5823_vcm_power_down(struct v4l2_subdev *sd); +int ad5823_vcm_init(struct v4l2_subdev *sd); + +int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val); +int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value); +int ad5823_t_focus_rel(struct v4l2_subdev *sd, s32 value); +int ad5823_q_focus_status(struct v4l2_subdev *sd, s32 *value); +int ad5823_q_focus_abs(struct v4l2_subdev *sd, s32 *value); + +#endif diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c new file mode 100644 index 000000000..c39cb014a --- /dev/null +++ b/drivers/media/i2c/ov8865.c @@ -0,0 +1,2176 @@ +/* + * Support for OmniVision ov8865 8MP camera sensor. + * + * Copyright (c) 2011 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ov8865.h" + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include "ov8865_bld_otp.c" +#define OV8865_BIN_FACTOR_MAX 2 +#define OV8865_OTP_INPUT_NAME "ov8865_otp.bin" + +#define to_ov8865_sensor(sd) container_of(sd, struct ov8865_device, sd) + +#define DEBUG_VERBOSE (1<<0) +#define DEBUG_GAIN_EXP (1<<1) +#define DEBUG_INTG_FACT (1<<2) +#define DEBUG_OTP (1<<4) +static unsigned int debug = 0x00; +module_param(debug, int, 0644); + +struct ov8865_device * global_dev; +static unsigned int ctrl_value; +static int bu64243_vcm_ctrl(const char *val, struct kernel_param *kp); +static int bu64243_t_focus_abs(struct v4l2_subdev *sd, s32 value); + +module_param_call(vcm_ctrl, bu64243_vcm_ctrl, param_get_uint, + &ctrl_value, S_IRUGO | S_IWUSR); + +static int ov8865_raw_size; +static int ov8865_otp_size; +static unsigned char ov8865_raw[DATA_BUF_SIZE]; +static unsigned char ov8865_otp_data[DATA_BUF_SIZE]; +static u16 exposure_time; +static int op_dump_otp; +static int ov8865_dump_otp(const char *val, struct kernel_param *kp); +module_param_call(dump_otp, ov8865_dump_otp, param_get_uint, + &op_dump_otp, S_IRUGO | S_IWUSR); + +#define OV8865_DEFAULT_LOG_LEVEL 1 + +static unsigned int log_level = OV8865_DEFAULT_LOG_LEVEL; +module_param(log_level, int, 0644); + +#define OV8865_LOG(level, a, ...) \ + do { \ + if (level < log_level) \ + printk(a,## __VA_ARGS__); \ + } while (0) + +static int ov8865_dump_otp(const char *val, struct kernel_param *kp) +{ + int ret; + ret = ov8865_otp_save(ov8865_raw, ov8865_raw_size, OV8865_SAVE_RAW_DATA); + if(ret != 0) + OV8865_LOG(2, "Fail to save ov8865 RAW data\n"); + + ret = ov8865_otp_save(ov8865_otp_data, ov8865_otp_size, OV8865_SAVE_OTP_DATA); + if(ret != 0) + OV8865_LOG(2, "Fail to save ov8865 OTP data\n"); + + return 0; +} + +static int +ov8865_read_reg(struct i2c_client *client, u16 len, u16 reg, u16 *val) +{ + struct i2c_msg msg[2]; + u16 data[OV8865_SHORT_MAX]; + int err, i; + + if (!client->adapter) { + v4l2_err(client, "%s error, no client->adapter\n", __func__); + return -ENODEV; + } + + /* @len should be even when > 1 */ + if (len > OV8865_BYTE_MAX) { + v4l2_err(client, "%s error, invalid data length\n", __func__); + return -EINVAL; + } + + memset(msg, 0, sizeof(msg)); + memset(data, 0, sizeof(data)); + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = I2C_MSG_LENGTH; + msg[0].buf = (u8 *)data; + /* high byte goes first */ + data[0] = cpu_to_be16(reg); + + msg[1].addr = client->addr; + msg[1].len = len; + msg[1].flags = I2C_M_RD; + msg[1].buf = (u8 *)data; + + err = i2c_transfer(client->adapter, msg, 2); + if (err < 0) + goto error; + + /* high byte comes first */ + if (len == OV8865_8BIT) { + *val = (u8)data[0]; + } else { + /* 16-bit access is default when len > 1 */ + for (i = 0; i < (len >> 1); i++) + val[i] = be16_to_cpu(data[i]); + } + + return 0; + +error: + dev_err(&client->dev, "read from offset 0x%x error %d", reg, err); + return err; +} + +static int ov8865_i2c_write(struct i2c_client *client, u16 len, u8 *data) +{ + struct i2c_msg msg; + const int num_msg = 1; + int ret; + int retry = 0; + +again: + msg.addr = client->addr; + msg.flags = 0; + msg.len = len; + msg.buf = data; + + ret = i2c_transfer(client->adapter, &msg, 1); + + /* + * It is said that Rev 2 sensor needs some delay here otherwise + * registers do not seem to load correctly. But tests show that + * removing the delay would not cause any in-stablility issue and the + * delay will cause serious performance down, so, removed previous + * mdelay(1) here. + */ + + if (ret == num_msg) { + return 0; + } + + if (retry <= I2C_RETRY_COUNT) { + dev_err(&client->dev, "retrying i2c write transfer... %d", + retry); + retry++; + msleep(20); + goto again; + } + + return ret; +} + +static int +ov8865_write_reg(struct i2c_client *client, u16 data_length, u16 reg, u16 val) +{ + int ret; + unsigned char data[4] = {0}; + u16 *wreg; + const u16 len = data_length + sizeof(u16); /* 16-bit address + data */ + + if (!client->adapter) { + v4l2_err(client, "%s error, no client->adapter\n", __func__); + return -ENODEV; + } + + if (data_length != OV8865_8BIT && data_length != OV8865_16BIT) { + v4l2_err(client, "%s error, invalid data_length\n", __func__); + return -EINVAL; + } + + /* high byte goes out first */ + wreg = (u16 *)data; + *wreg = cpu_to_be16(reg); + + if (data_length == OV8865_8BIT) { + data[2] = (u8)(val); + } else { + /* OV8865_16BIT */ + u16 *wdata = (u16 *)&data[2]; + *wdata = be16_to_cpu(val); + } + //printk("ov8865, ov8865_write_reg ,before ov8865_i2c_write\n"); + ret = ov8865_i2c_write(client, len, data); + if (ret) { + // printk("ov8865_i2c_write error\n"); + dev_err(&client->dev, + "write error: wrote 0x%x to offset 0x%x error %d", + val, reg, ret); + } + return ret; +} + + +/* + * ov8865_write_reg_array - Initializes a list of MT9M114 registers + * @client: i2c driver client structure + * @reglist: list of registers to be written + * + * This function initializes a list of registers. When consecutive addresses + * are found in a row on the list, this function creates a buffer and sends + * consecutive data in a single i2c_transfer(). + * + * __ov8865_flush_reg_array, __ov8865_buf_reg_array() and + * __ov8865_write_reg_is_consecutive() are internal functions to + * ov8865_write_reg_array_fast() and should be not used anywhere else. + * + */ + +static int __ov8865_flush_reg_array(struct i2c_client *client, + struct ov8865_write_ctrl *ctrl) +{ + u16 size; + + if (ctrl->index == 0) + return 0; + + size = sizeof(u16) + ctrl->index; /* 16-bit address + data */ + ctrl->buffer.addr = cpu_to_be16(ctrl->buffer.addr); + ctrl->index = 0; + //printk("ov8865, __ov8865_flush_reg_array, before ov8865_i2c_write\n"); + return ov8865_i2c_write(client, size, (u8 *)&ctrl->buffer); +} + +static int __ov8865_buf_reg_array(struct i2c_client *client, + struct ov8865_write_ctrl *ctrl, + const struct ov8865_reg *next) +{ + int size; + u16 *data16; + + switch (next->type) { + case OV8865_8BIT: + size = 1; + ctrl->buffer.data[ctrl->index] = (u8)next->val; + break; + case OV8865_16BIT: + size = 2; + data16 = (u16 *)&ctrl->buffer.data[ctrl->index]; + *data16 = cpu_to_be16((u16)next->val); + break; + default: + return -EINVAL; + } + + /* When first item is added, we need to store its starting address */ + if (ctrl->index == 0) + ctrl->buffer.addr = next->reg.sreg; + + ctrl->index += size; + + /* + * Buffer cannot guarantee free space for u32? Better flush it to avoid + * possible lack of memory for next item. + */ + if (ctrl->index + sizeof(u16) >= OV8865_MAX_WRITE_BUF_SIZE) + __ov8865_flush_reg_array(client, ctrl); + + return 0; +} + +static int +__ov8865_write_reg_is_consecutive(struct i2c_client *client, + struct ov8865_write_ctrl *ctrl, + const struct ov8865_reg *next) +{ + if (ctrl->index == 0) + return 1; + + return ctrl->buffer.addr + ctrl->index == next->reg.sreg; +} + +static int ov8865_write_reg_array(struct i2c_client *client, + const struct ov8865_reg *reglist) +{ + const struct ov8865_reg *next = reglist; + struct ov8865_write_ctrl ctrl; + int err; + + ctrl.index = 0; + for (; next->type != OV8865_TOK_TERM; next++) { + switch (next->type & OV8865_TOK_MASK) { + case OV8865_TOK_DELAY: + err = __ov8865_flush_reg_array(client, &ctrl); + if (err) + return err; + msleep(next->val); + break; + + default: + /* + * If next address is not consecutive, data needs to be + * flushed before proceed. + */ + if (!__ov8865_write_reg_is_consecutive(client, &ctrl, + next)) { + err = __ov8865_flush_reg_array(client, &ctrl); + if (err) + return err; + } + err = __ov8865_buf_reg_array(client, &ctrl, next); + if (err) { + v4l2_err(client, "%s: write error, aborted\n", + __func__); + //printk("ov8865, ov8865_write_reg_array ,error"); + return err; + } + break; + } + } + + return __ov8865_flush_reg_array(client, &ctrl); +} + +static int bu64243_write8(struct v4l2_subdev *sd, int reg, int val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct bu64243_device *dev = to_bu64243_device(sd); + struct i2c_msg msg; + + memset(&msg, 0 , sizeof(msg)); + msg.addr = BU64243_I2C_ADDR; + msg.len = 2; + msg.buf = dev->buffer; + msg.buf[0] = reg; + msg.buf[1] = val; + + OV8865_LOG(1, "%s %d reg:0x%x val:0x%x\n", __func__, __LINE__, reg, val); + return i2c_transfer(client->adapter, &msg, 1); +} + +static int bu64243_read8(struct v4l2_subdev *sd, int reg, u8 * data) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct bu64243_device *dev = to_bu64243_device(sd); + struct i2c_msg msg[2]; + int r; + + OV8865_LOG(1, "%s %d reg:0x%x\n", __func__, __LINE__, reg); + memset(msg, 0 , sizeof(msg)); + msg[0].addr = BU64243_I2C_ADDR; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = dev->buffer; + msg[0].buf[0] = reg; + + msg[1].addr = BU64243_I2C_ADDR; + msg[1].flags = I2C_M_RD; + msg[1].len = 2; + msg[1].buf = data; + + r = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (r != ARRAY_SIZE(msg)) + return -EIO; + + return 0; +} +static int bu64243_cmd(struct v4l2_subdev *sd, s32 reg, s32 val) +{ + int cmd = 0; + struct bu64243_device *dev = to_bu64243_device(sd); + + OV8865_LOG(1, "BU64243 reg:%d\n", reg); + OV8865_LOG(1, "BU64243_PS(dev->power_state):%x-->%x\n", dev->power_state, BU64243_PS(dev->power_state)); + OV8865_LOG(1, "BU64243_EN(dev->output_status):%x-->%x\n", dev->output_status, BU64243_EN(dev->output_status)); + OV8865_LOG(1, "BU64243_PS(dev->W0_W2):%x-->%x\n", reg, BU64243_W0_W2(reg)); + OV8865_LOG(1, "BU64243_PS(dev->isrc):%x-->%x\n", dev->isrc_mode, BU64243_M(dev->isrc_mode)); + OV8865_LOG(1, "BU64243_PS(dev->D9D8):%x-->%x\n", val, BU64243_D_HI(val)); + + cmd = BU64243_PS(dev->power_state) | BU64243_EN(dev->output_status) | + BU64243_W0_W2(reg) | BU64243_M(dev->isrc_mode) | + BU64243_D_HI(val); + + return cmd; +} + + +static int bu64243_init(struct v4l2_subdev *sd) +{ + /* shunyong for power on */ + OV8865_LOG(1, "Bu64243 needs no platform data, nothing need to do\n"); + return 0; +} + +static int bu64243_power_up(struct v4l2_subdev *sd) +{ + struct bu64243_device *dev = to_bu64243_device(sd); + struct ov8865_device *ov8865_dev = to_ov8865_sensor(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int r, value; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + dev->power_state = 1; + dev->output_status = BU64243_DEFAULT_OUTPUT_STATUS; /* */ + dev->point_a = BU64243_DEFAULT_POINT_A; /* 0 um */ + dev->point_b = BU64243_DEFAULT_POINT_B; /* lens float */ + dev->focus = BU64243_DEFAULT_POINT_C; /* focus point*/ + dev->res_freq = BU64243_DEFAULT_VCM_FREQ; /* resonant frequency*/ + dev->slew_rate = BU64243_DEFAULT_SLEW_RATE; /* slew rate*/ + dev->step_res = BU64243_DEFAULT_RES_SETTING; /* step resolution */ + dev->step_time = BU64243_DEFAULT_STEP_TIME_SETTING; /* step time */ + dev->isrc_mode = BU64243_DEFAULT_ISRC_MODE; + /* jiggle SCL pin to wake up device */ + if (ov8865_dev->otp_data != NULL) { + /*reprogram VCM point A, B*/ + unsigned int focus_far = ov8865_dev->otp_data[8] | ov8865_dev->otp_data[7]; + if (focus_far < (VCM_ORIENTATION_OFFSET + INTEL_FOCUS_OFFSET +1 + POINT_AB_OFFSET)) + focus_far = VCM_ORIENTATION_OFFSET + INTEL_FOCUS_OFFSET +1 + POINT_AB_OFFSET; + dev->point_b = focus_far - VCM_ORIENTATION_OFFSET - INTEL_FOCUS_OFFSET -1; /* lens loat */ + dev->point_a = dev->point_b - POINT_AB_OFFSET; /* 0 um */ + OV8865_LOG(1, "%s focus far in OTP:%d point a:%d b:%d \n", __func__, focus_far, dev->point_a, dev->point_b); + } + + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_VCM_CURRENT, dev->focus), BU64243_D_LO(dev->focus)); + if (r < 0) + return r; + + value = (BU64243_RFEQ(dev->res_freq)) | BU64243_SRATE((dev->slew_rate)); + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_PARAM_1, value), BU64243_D_LO(value)); + if (r < 0) + return r; + + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_PARAM_2, dev->point_a), BU64243_D_LO(dev->point_a)); + if (r < 0) + return r; + + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_PARAM_3, dev->point_b), BU64243_D_LO(dev->point_b)); + if (r < 0) + return r; + + value = (BU64243_STIME(dev->step_time)) | (BU64243_SRES(dev->step_res)); + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_PARAM_4, value), BU64243_D_LO(value)); + if (r < 0) + return r; + + dev->initialized = true; + v4l2_info(client, "detected bu64243\n"); + + return 0; + + /* shunyong for power on */ + OV8865_LOG(1, "power is controlled via sensor control\n"); + //printk("power is controlled via sensor control\n"); + return r; +} + +static int bu64243_power_down(struct v4l2_subdev *sd) +{ + struct bu64243_device *dev = to_bu64243_device(sd); + unsigned int focus_far =0; + u8 data[10]; + struct ov8865_device *ov8865_dev = to_ov8865_sensor(sd); + int r,i; + s32 current_value,average,focus_value; + if (ov8865_dev->otp_data != NULL) { + /*reprogram VCM point A, B*/ + OV8865_LOG(1,"otp data valid !!!enter bu64243_power_down \n "); + focus_far = ov8865_dev->otp_data[8] | ov8865_dev->otp_data[7]; + if (focus_far < (VCM_ORIENTATION_OFFSET + INTEL_FOCUS_OFFSET +1 + POINT_AB_OFFSET)) + focus_far = VCM_ORIENTATION_OFFSET + INTEL_FOCUS_OFFSET +1 + POINT_AB_OFFSET; + OV8865_LOG(1, "%s focus far in OTP:%d point a:%d b:%d \n", __func__, focus_far, dev->point_a, dev->point_b); + } + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_VCM_CURRENT, focus_far), BU64243_D_LO(focus_far)); + if (r < 0) + return r; + bu64243_read8(sd, bu64243_cmd(sd, BU64243_VCM_CURRENT, 0), data); + current_value = ((data[0] &0x03)<<8) +data[1]; + average = current_value/10; + OV8865_LOG(1, "current_value = %d , average = %d\n",current_value,average); + for (i= 1; i < 11; i ++){ + focus_value =current_value -average*i; + OV8865_LOG(1,"focus_value = %d\n",focus_value); + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_VCM_CURRENT, focus_value), BU64243_D_LO(focus_value)); + if (r < 0) + return r; + mdelay(5); + } + /* shunyong for power on */ + OV8865_LOG(1, "power is controlled via sensor control\n"); + return 0; +} + +static void bu64243_dump_regs(struct v4l2_subdev *sd) +{ + int i; + u8 data[10]; + + OV8865_LOG(2, "%s %d\n", __func__, __LINE__); + + for (i = 0; i < 5; i ++) { + bu64243_read8(sd, bu64243_cmd(sd, i, 0), data); + OV8865_LOG(2, "%s %d reg:%d data[0]:0x%x data[1]:0x%x\n", __func__, __LINE__, i, data[0], data[1]); + } +} + +static int bu64243_t_focus_abs(struct v4l2_subdev *sd, s32 value) +{ + struct bu64243_device *dev = to_bu64243_device(sd); + int r; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + if (!dev->initialized) + return -ENODEV; + + value = clamp(value, 0, BU64243_MAX_FOCUS_POS); + OV8865_LOG(1, "%s %d value:%x cmd:%x low:%x\n", __func__, __LINE__, value, bu64243_cmd(sd, BU64243_VCM_CURRENT, value), BU64243_D_LO(value)); + r = bu64243_write8(sd, bu64243_cmd(sd, BU64243_VCM_CURRENT, value), BU64243_D_LO(value)); + if (r < 0) + return r; + + getnstimeofday(&dev->focus_time); + dev->focus = value; + return 0; +} + + + +static int bu64243_vcm_ctrl(const char *val, struct kernel_param *kp) +{ + int ret; + int rv = param_set_int(val, kp); + + OV8865_LOG(2, "%s %d\n", __func__, __LINE__); + + if (rv) + return rv; + /* Enable power */ + OV8865_LOG(2, "%s %d enable power\n", __func__, __LINE__); + ret = global_dev->platform_data->power_ctrl(&(global_dev->sd), 1); + mdelay(200); + bu64243_power_up(&(global_dev->sd)); + mdelay(10); + + bu64243_t_focus_abs(&(global_dev->sd), ctrl_value); + OV8865_LOG(2, "%s %d ctrl value:0x%x\n", __func__, __LINE__, ctrl_value); + + bu64243_dump_regs(&(global_dev->sd)); + return 0; +} + +/* Start group hold for the following register writes */ +static int ov8865_grouphold_start(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + const int group = 0; + + return ov8865_write_reg(client, OV8865_8BIT, + OV8865_GROUP_ACCESS, + group | OV8865_GROUP_ACCESS_HOLD_START); +} + +/* End group hold and delay launch it */ +static int ov8865_grouphold_launch(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + const int group = 0; + int ret; + + /* End group */ + ret = ov8865_write_reg(client, OV8865_8BIT, + OV8865_GROUP_ACCESS, + group | OV8865_GROUP_ACCESS_HOLD_END); + if (ret) + return ret; + + /* Delay launch group (during next vertical blanking) */ + return ov8865_write_reg(client, OV8865_8BIT, + OV8865_GROUP_ACCESS, + group | OV8865_GROUP_ACCESS_DELAY_LAUNCH); +} + + +static int ov8865_g_priv_int_data(struct v4l2_subdev *sd, + struct v4l2_private_int_data *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov8865_device *dev = to_ov8865_sensor(sd); + u8 __user *to = priv->data; + u32 read_size = priv->size; + int ret; + int i; + u8 * pdata; + + /* No need to copy data if size is 0 */ + if (!read_size) + goto out; + + if (dev->otp_data == NULL) { + dev_err(&client->dev, "OTP data not available"); + return -1; + } + /* Correct read_size value only if bigger than maximum */ + if (read_size > DATA_BUF_SIZE) + read_size = DATA_BUF_SIZE; + + pdata = (u8 *) dev->otp_data; + + for (i = 0;i < 10; i ++) OV8865_LOG(2, "%d %x\n", i, pdata[i]); + + OV8865_LOG(2, "yangsy %s %d read:%d\n", __func__, __LINE__, read_size); + ret = copy_to_user(to, dev->otp_data, read_size); + if (ret) { + dev_err(&client->dev, "%s: failed to copy OTP data to user\n", + __func__); + return -EFAULT; + } +out: + + /* Return correct size */ + priv->size = DATA_BUF_SIZE; + OV8865_LOG(2, "%s %d qurry size:%d\n", __func__, __LINE__, priv->size); + + return 0; +} + +static int __ov8865_get_max_fps_index( + const struct ov8865_fps_setting *fps_settings) +{ + int i; + + for (i = 0; i < MAX_FPS_OPTIONS_SUPPORTED; i++) { + if (fps_settings[i].fps == 0) + break; + } + + return i - 1; +} + +static int __ov8865_update_frame_timing(struct v4l2_subdev *sd, int exposure, + u16 *hts, u16 *vts) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + /* Increase the VTS to match exposure + 14 */ + if (exposure > *vts - OV8865_INTEGRATION_TIME_MARGIN) + *vts = (u16) exposure + OV8865_INTEGRATION_TIME_MARGIN; + + ret = ov8865_write_reg(client, OV8865_16BIT, OV8865_TIMING_HTS, *hts); + if (ret) + return ret; + + return ov8865_write_reg(client, OV8865_16BIT, OV8865_TIMING_VTS, *vts); +} + +static int __ov8865_set_exposure(struct v4l2_subdev *sd, int exposure, int gain, + int dig_gain, u16 *hts, u16 *vts) +{ + /* shunyong: disabled exposure setting */ + + struct i2c_client *client = v4l2_get_subdevdata(sd); + int exp_val, ret; + + /* Update frame timings. Expsure must be minimum < vts-14 */ + ret = __ov8865_update_frame_timing(sd, exposure, hts, vts); + if (ret) + return ret; + + /* For OV8835, the low 4 bits are fraction bits and must be kept 0 */ + exp_val = exposure << 4; + exposure_time = exposure; + ret = ov8865_write_reg(client, OV8865_8BIT, + OV8865_LONG_EXPO+2, exp_val & 0xFF); + if (ret) + return ret; + + ret = ov8865_write_reg(client, OV8865_8BIT, + OV8865_LONG_EXPO+1, (exp_val >> 8) & 0xFF); + if (ret) + return ret; + + ret = ov8865_write_reg(client, OV8865_8BIT, + OV8865_LONG_EXPO, (exp_val >> 16) & 0x0F); + if (ret) + return ret; + + /* Digital gain : to all MWB channel gains */ + if (dig_gain) { + ret = ov8865_write_reg(client, OV8865_8BIT, + OV8865_DIGI_GAIN, ((dig_gain >> 6) & 0xFF)); + if (ret) + return ret; + ret = ov8865_write_reg(client, OV8865_8BIT, + (OV8865_DIGI_GAIN + 1), dig_gain & 0x3F); + if (ret) + return ret; + + } + + return ov8865_write_reg(client, OV8865_16BIT, OV8865_AGC_ADJ, gain & 0x1FFF); +} + +static int ov8865_set_exposure(struct v4l2_subdev *sd, int exposure, int gain, + int dig_gain) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + const struct ov8865_resolution *res; + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 hts, vts; + int ret; + + mutex_lock(&dev->input_lock); + + /* Validate exposure: cannot exceed 16bit value */ + exposure = clamp_t(int, exposure, 0, OV8865_MAX_EXPOSURE_VALUE); + + /* Validate gain: must not exceed maximum 8bit value */ + gain = clamp_t(int, gain, 0, OV8865_MAX_GAIN_VALUE); + + /* Validate digital gain: must not exceed 12 bit value*/ + dig_gain = clamp_t(int, dig_gain, 0, OV8865_MWB_GAIN_MAX); + + /* Group hold is valid only if sensor is streaming. */ + if (dev->streaming) { + ret = ov8865_grouphold_start(sd); + if (ret) + goto out; + } + + res = &dev->curr_res_table[dev->fmt_idx]; + hts = res->fps_options[dev->fps_index].pixels_per_line; + vts = res->fps_options[dev->fps_index].lines_per_frame; + + ret = __ov8865_set_exposure(sd, exposure, gain, dig_gain, &hts, &vts); + if (ret) + goto out; + + /* Updated the device variable. These are the current values. */ + dev->gain = gain; + dev->exposure = exposure; + dev->digital_gain = dig_gain; + +out: + /* Group hold launch - delayed launch */ + if (dev->streaming) + ret = ov8865_grouphold_launch(sd); + + mutex_unlock(&dev->input_lock); + + if (debug & DEBUG_GAIN_EXP) { + u16 val3500, val3501, val3502; + u16 val3503, val3508, val3509, val350a, val350b, val501e; + int val_exp, val_again; + + OV8865_LOG(2, "%s %d exposure:%d(0x%x) gain:%d(8x%x)\n", __func__, + __LINE__, exposure, exposure, gain, gain); + ov8865_read_reg(client, OV8865_8BIT, 0x3500, &val3500); + ov8865_read_reg(client, OV8865_8BIT, 0x3501, &val3501); + ov8865_read_reg(client, OV8865_8BIT, 0x3502, &val3502); + val_exp = (val3502 + (val3501 << 8) + (val3500 << 16)) >> 4; + OV8865_LOG(2, "%s %d 0x3500:%x 0x3501:%x 0x3502:%x exposure(dec):%d\n", __func__, + __LINE__, val3500, val3501, val3502, val_exp); + + ov8865_read_reg(client, OV8865_8BIT, 0x3503, &val3503); + ov8865_read_reg(client, OV8865_8BIT, 0x3508, &val3508); + ov8865_read_reg(client, OV8865_8BIT, 0x3509, &val3509); + ov8865_read_reg(client, OV8865_8BIT, 0x350a, &val350a); + ov8865_read_reg(client, OV8865_8BIT, 0x350b, &val350b); + ov8865_read_reg(client, OV8865_8BIT, 0x501e, &val501e); + + val_again = ((val3508 << 8) + val3509) >> 7; + OV8865_LOG(2, "%s %d 0x3503:%x 0x3508:%x 0x3509:%x val_again:(dec):%d\n", __func__, + __LINE__, val3503, val3508, val3509, val_again); + + OV8865_LOG(2, "%s %d 0x501e:%x 0x350a:%x 0x350b:%x\n", __func__, __LINE__, + val501e, val350a, val350b); + } + + return ret; +} + +static int ov8865_s_exposure(struct v4l2_subdev *sd, + struct atomisp_exposure *exposure) +{ + return ov8865_set_exposure(sd, exposure->integration_time[0], + exposure->gain[0], exposure->gain[1]); +} + +static long ov8865_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + switch (cmd) { + case ATOMISP_IOC_S_EXPOSURE: + return ov8865_s_exposure(sd, (struct atomisp_exposure *)arg); + case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: + return ov8865_g_priv_int_data(sd, arg); + default: + return -EINVAL; + } + return 0; +} + +static int ov8865_init_registers(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov8865_device *dev = to_ov8865_sensor(sd); + //printk("ov8865, ov8865_init_registers\n"); + + dev->basic_settings_list = ov8865_BasicSettings; + + return ov8865_write_reg_array(client, dev->basic_settings_list); +} + +static int ov8865_init(struct v4l2_subdev *sd, u32 val) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + int ret; + + mutex_lock(&dev->input_lock); + ret = ov8865_init_registers(sd); + mutex_unlock(&dev->input_lock); + + return ret; +} + +static void ov8865_uninit(struct v4l2_subdev *sd) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + + dev->exposure = 0; + dev->gain = 0; + dev->digital_gain = 0; +} + +static int power_up(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov8865_device *dev = to_ov8865_sensor(sd); + int ret; + + /* Enable power */ + ret = dev->platform_data->power_ctrl(sd, 1); + if (ret) + goto fail_power; + + /* Release reset */ + ret = dev->platform_data->gpio_ctrl(sd, 1); + if (ret) + dev_err(&client->dev, "gpio failed 1\n"); + + /* Enable clock */ + ret = dev->platform_data->flisclk_ctrl(sd, 1); + if (ret) + goto fail_clk; + + /* Minumum delay is 8192 clock cycles before first i2c transaction, + * which is 1.37 ms at the lowest allowed clock rate 6 MHz */ + usleep_range(2000, 2100); + return 0; + +fail_clk: + dev->platform_data->flisclk_ctrl(sd, 0); +fail_power: + dev->platform_data->power_ctrl(sd, 0); + dev_err(&client->dev, "sensor power-up failed\n"); + + return ret; +} + +static int power_down(struct v4l2_subdev *sd) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + ret = dev->platform_data->flisclk_ctrl(sd, 0); + if (ret) + dev_err(&client->dev, "flisclk failed\n"); + + /* gpio ctrl */ + ret = dev->platform_data->gpio_ctrl(sd, 0); + if (ret) + dev_err(&client->dev, "gpio failed 1\n"); + + /* power control */ + ret = dev->platform_data->power_ctrl(sd, 0); + if (ret) + dev_err(&client->dev, "vprog failed.\n"); + + return ret; +} + +static int __ov8865_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + int ret, r; + + if (on == 0) { + ov8865_uninit(sd); + /* shunyong: disable VCM for PO */ + r = bu64243_power_down(sd); + ret = power_down(sd); + + if (ret == 0) + ret = r; + dev->power = 0; + } else { + //printk("ov8865 start power-up"); + ret = power_up(sd); + if (ret) + return ret; + /* shunyong: disable VCM for PO */ + ret = bu64243_power_up(sd); + if (ret) { + power_down(sd); + return ret; + } + //printk("ov8865 before ov8865_init_registers\n"); + ret = ov8865_init_registers(sd); + // printk("ov8865 after ov8865_init_registers\n"); + if (ret) { + // printk("ov8865 bu64243_power_down power_down ret = %d\n",ret); + bu64243_power_down(sd); + power_down(sd); + } + dev->power = 1; + } + + return ret; +} + +static int ov8865_s_power(struct v4l2_subdev *sd, int on) +{ + int ret; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + mutex_lock(&dev->input_lock); + ret = __ov8865_s_power(sd, on); + mutex_unlock(&dev->input_lock); + + /* + * FIXME: Compatibility with old behaviour: return to preview + * when the device is power cycled. + */ + if (!ret && on) + v4l2_ctrl_s_ctrl(dev->run_mode, ATOMISP_RUN_MODE_PREVIEW); + + return ret; +} + +static int ov8865_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV8865, 0); + + return 0; +} + +/* Return value of the specified register, first try getting it from + * the register list and if not found, get from the sensor via i2c. + */ +static int ov8865_get_register(struct v4l2_subdev *sd, int reg, + const struct ov8865_reg *reglist) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + const struct ov8865_reg *next; + u16 val; + + /* Try if the values is in the register list */ + for (next = reglist; next->type != OV8865_TOK_TERM; next++) { + if (next->type != OV8865_8BIT) { + v4l2_err(sd, "only 8-bit registers supported\n"); + return -ENXIO; + } + if (next->reg.sreg == reg) + return next->val; + } + + /* If not, read from sensor */ + if (ov8865_read_reg(client, OV8865_8BIT, reg, &val)) { + v4l2_err(sd, "failed to read register 0x%04X\n", reg); + return -EIO; + } + + return val; +} + +static int ov8865_get_register_16bit(struct v4l2_subdev *sd, int reg, + const struct ov8865_reg *reglist, unsigned int *value) +{ + int high, low; + + high = ov8865_get_register(sd, reg, reglist); + if (high < 0) + return high; + + low = ov8865_get_register(sd, reg + 1, reglist); + if (low < 0) + return low; + + *value = ((u8) high << 8) | (u8) low; + return 0; +} + +static int ov8865_get_intg_factor(struct v4l2_subdev *sd, + struct camera_mipi_info *info, + const struct ov8865_reg *reglist) +{ + /*shunyong: disable get_intg for PO*/ + struct i2c_client *client = v4l2_get_subdevdata(sd); + const int ext_clk = 19200000; /* MHz */ + struct atomisp_sensor_mode_data *m = &info->data; + struct ov8865_device *dev = to_ov8865_sensor(sd); + const struct ov8865_resolution *res = + &dev->curr_res_table[dev->fmt_idx]; + int pll1_prediv0, pll1_prediv; + int pll1_multiplier; + int pll1_sys_pre_div; + int pll1_sys_divider; + int ret; + u16 val; + + memset(&info->data, 0, sizeof(info->data)); + + pll1_prediv0 = 1; /* 0x0312[4] = 0*/ + pll1_prediv = 4; /* 0x030b[2:0] = 5*/ + pll1_multiplier = 0x96; /* 0x030c[1:0]=0x0, 0x030d[7:0] = 0x96*/ + ov8865_read_reg(client, OV8865_8BIT, PLL1_SYS_PRE_DIV, &val); + pll1_sys_pre_div = 1 + ((int)val); + pll1_sys_divider = 1; /* 0x030e[2:0] = 0x00*/ + + m->vt_pix_clk_freq_mhz = (ext_clk / (pll1_prediv0 * pll1_prediv * pll1_sys_pre_div * pll1_sys_divider)) * pll1_multiplier;; + + /* HTS and VTS */ + m->line_length_pck = res->fps_options[dev->fps_index].pixels_per_line; + m->frame_length_lines = res->fps_options[dev->fps_index].lines_per_frame; + + m->coarse_integration_time_min = 0; + m->coarse_integration_time_max_margin = OV8865_INTEGRATION_TIME_MARGIN; + + /* OV Sensor do not use fine integration time. */ + m->fine_integration_time_min = 0; + m->fine_integration_time_max_margin = 0; + + /* + * read_mode indicate whether binning is used for calculating + * the correct exposure value from the user side. So adapt the + * read mode values accordingly. + */ + m->read_mode = res->bin_factor_x ? + OV8865_READ_MODE_BINNING_ON : OV8865_READ_MODE_BINNING_OFF; + + ret = ov8865_get_register(sd, OV8865_TIMING_X_INC, res->regs); + if (ret < 0) + return ret; + m->binning_factor_x = res->bin_factor_x ? 2 : 1; + + ret = ov8865_get_register(sd, OV8865_TIMING_Y_INC, res->regs); + if (ret < 0) + return ret; + m->binning_factor_y = res->bin_factor_y ? 2 : 1; + + /* Get the cropping and output resolution to ISP for this mode. */ + ret = ov8865_get_register_16bit(sd, OV8865_HORIZONTAL_START_H, + res->regs, &m->crop_horizontal_start); + if (ret) + return ret; + + ret = ov8865_get_register_16bit(sd, OV8865_VERTICAL_START_H, + res->regs, &m->crop_vertical_start); + if (ret) + return ret; + + ret = ov8865_get_register_16bit(sd, OV8865_HORIZONTAL_OUTPUT_SIZE_H, + res->regs, &m->output_width); + if (ret) + return ret; + m->output_width = m->output_width - ISP_PADDING_W; /*remove ISP padding, real output*/ + + ret = ov8865_get_register_16bit(sd, OV8865_VERTICAL_OUTPUT_SIZE_H, + res->regs, &m->output_height); + if (ret) + return ret; + m->output_height = m->output_height - ISP_PADDING_H; + + /* + * As ov8865 is central crop, we calculate for 3264x2448 to meet IQ/OTP + * requirement + */ + if (res->bin_factor_x) { + /*consider output padding*/ + m->crop_horizontal_start = (OV8865_ISP_MAX_WIDTH - ((m->output_width + ISP_PADDING_W) << res->bin_factor_x))/2; + } else { + m->crop_horizontal_start = (OV8865_ISP_MAX_WIDTH - m->output_width)/2; + } + m->crop_horizontal_end = OV8865_ISP_MAX_WIDTH - m->crop_horizontal_start - 1; + + if (res->bin_factor_y) { + /*consider output padding*/ + m->crop_vertical_start = (OV8865_ISP_MAX_HEIGHT - ((m->output_height + ISP_PADDING_H) << res->bin_factor_y))/2; + } else { + m->crop_vertical_start = (OV8865_ISP_MAX_HEIGHT - m->output_height )/2; + } + + m->crop_vertical_end = OV8865_ISP_MAX_HEIGHT - m->crop_vertical_start - 1; + + if(debug & DEBUG_INTG_FACT) { + OV8865_LOG(2, "%s %d vt_pix_clk_freq_mhz:%d line_length_pck:%d frame_length_lines:%d\n", __func__, __LINE__, + m->vt_pix_clk_freq_mhz, m->line_length_pck, m->frame_length_lines); + OV8865_LOG(2, "%s %d coarse_intg_min:%d coarse_intg_max_margin:%d fine_intg_min:%d fine_intg_max_margin:%d\n", + __func__, __LINE__, + m->coarse_integration_time_min, m->coarse_integration_time_max_margin, + m->fine_integration_time_min, m->fine_integration_time_max_margin); + OV8865_LOG(2, "%s %d crop_x_start:%d crop_y_start:%d crop_x_end:%d crop_y_end:%d \n", __func__, __LINE__, + m->crop_horizontal_start, m->crop_vertical_start, m->crop_horizontal_end, m->crop_vertical_end); + OV8865_LOG(2, "%s %d output_width:%d output_height:%d\n", __func__, __LINE__, m->output_width, m->output_height); + } + + return 0; +} + +#if 0 +static int __ov8865_s_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval) +{ + /* shunyong disabel s_frame_interval for PO */ +#if 0 + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct camera_mipi_info *info = v4l2_get_subdev_hostdata(sd); + const struct ov8865_resolution *res = + res = &dev->curr_res_table[dev->fmt_idx]; + int i; + int ret; + int fps; + u16 hts; + u16 vts; + + if (!interval->interval.numerator) + interval->interval.numerator = 1; + + fps = interval->interval.denominator / interval->interval.numerator; + + /* Ignore if we are already using the required FPS. */ + if (fps == res->fps_options[dev->fps_index].fps) + return 0; + + dev->fps_index = 0; + + /* Go through the supported FPS list */ + for (i = 0; i < MAX_FPS_OPTIONS_SUPPORTED; i++) { + if (!res->fps_options[i].fps) + break; + if (abs(res->fps_options[i].fps - fps) + < abs(res->fps_options[dev->fps_index].fps - fps)) + dev->fps_index = i; + } + + /* Get the new Frame timing values for new exposure */ + hts = res->fps_options[dev->fps_index].pixels_per_line; + vts = res->fps_options[dev->fps_index].lines_per_frame; + + /* update frametiming. Conside the curren exposure/gain as well */ + ret = __ov8865_set_exposure(sd, dev->exposure, dev->gain, + dev->digital_gain, &hts, &vts); + if (ret) + return ret; + + /* Update the new values so that user side knows the current settings */ + ret = ov8865_get_intg_factor(sd, info, dev->basic_settings_list); + if (ret) + return ret; + + interval->interval.denominator = res->fps_options[dev->fps_index].fps; + interval->interval.numerator = 1; +#endif + return 0; +} +#endif +/* + * distance - calculate the distance + * @res: resolution + * @w: width + * @h: height + * + * Get the gap between resolution and w/h. + * res->width/height smaller than w/h wouldn't be considered. + * Returns the value of gap or -1 if fail. + */ +/* tune this value so that the DVS resolutions get selected properly, + * but make sure 16:9 does not match 4:3. + */ +#define LARGEST_ALLOWED_RATIO_MISMATCH 500 +static int distance(struct ov8865_resolution const *res, const u32 w, + const u32 h) +{ + unsigned int w_ratio = ((res->width<<13)/w); + unsigned int h_ratio = ((res->height<<13)/h); + int match = abs(((w_ratio<<13)/h_ratio) - ((int)8192)); + + if ((w_ratio < (int)8192) || (h_ratio < (int)8192) + || (match > LARGEST_ALLOWED_RATIO_MISMATCH)) + return -1; + + return w_ratio + h_ratio; +} + +/* + * Returns the nearest higher resolution index. + * @w: width + * @h: height + * matching is done based on enveloping resolution and + * aspect ratio. If the aspect ratio cannot be matched + * to any index, -1 is returned. + */ +static int nearest_resolution_index(struct v4l2_subdev *sd, int w, int h) +{ + int i; + int idx = -1; + int dist; + int min_dist = INT_MAX; + const struct ov8865_resolution *tmp_res = NULL; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + printk("-%lx %lx w:%d h:%d\r\n", (unsigned long)dev->curr_res_table, (unsigned long )ov8865_res_preview, w, h); + if ((dev->curr_res_table == ov8865_res_preview)|| + (dev->curr_res_table == ov8865_res_still)) { + if ((((w == 1332) && (h == 1092))) || + (((w == 1320) && (h == 1080)))||(((w == 1280) &&(h == 720))) || + (((w == 1292) &&(h == 732))) || + (((w == 1024) &&(h == 576))) || (((w == 1036) &&(h == 588)))|| + (((w == 720) &&(h == 480))) || (((w == 732) &&(h == 492)))|| + (((w == 640) &&(h == 360))) || (((w == 652) &&(h == 372)))|| + (((w == 320) &&(h == 180))) || (((w == 332) &&(h == 192)))){ + w = 1632; + h = 1224; + } + if((((w == 1920) &&(h == 1080))) || (((w == 1932) &&(h == 1092)))){ + w = 1936; + h = 1096; + } + } + if ((dev->curr_res_table == ov8865_res_still)) { + if ((((w == 176) && (h == 144))) || + (((w == 188) && (h == 156)))){ + w = 1632; + h = 1224; + } + } +#if 0 + printk("%lx %lx w:%d h:%d\r\n", (unsigned long)dev->curr_res_table, (unsigned long )ov8865_res_preview, w, h); + if ((dev->curr_res_table == ov8865_res_preview)|| + (dev->curr_res_table == ov8865_res_still)) { + if ((((w == 1332) && (h == 1092))) || + (((w == 1320) && (h == 1080)))){ + w = 1632; + h = 1224; + } + } + if ((dev->curr_res_table == ov8865_res_still)) { + if ((((w == 176) && (h == 144))) || + (((w == 188) && (h == 156)))){ + w = 1632; + h = 1224; + } + } +#endif + for (i = 0; i < dev->entries_curr_table; i++) { + tmp_res = &dev->curr_res_table[i]; + dist = distance(tmp_res, w, h); + if (dist == -1) + continue; + if (dist < min_dist) { + min_dist = dist; + idx = i; + } + } + return idx; +} + +static int get_resolution_index(struct v4l2_subdev *sd, int w, int h) +{ + int i; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + for (i = 0; i < dev->entries_curr_table; i++) { + if (w != dev->curr_res_table[i].width) + continue; + if (h != dev->curr_res_table[i].height) + continue; + /* Found it */ + return i; + } + return -1; +} + +static int __ov8865_try_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + int idx; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + if (!fmt) + return -EINVAL; + + if ((fmt->width > OV8865_RES_WIDTH_MAX) || + (fmt->height > OV8865_RES_HEIGHT_MAX)) { + fmt->width = OV8865_RES_WIDTH_MAX; + fmt->height = OV8865_RES_HEIGHT_MAX; + } else { + idx = nearest_resolution_index(sd, fmt->width, fmt->height); + + /* + * nearest_resolution_index() doesn't return smaller resolutions. + * If it fails, it means the requested resolution is higher than we + * can support. Fallback to highest possible resolution in this case. + */ + if (idx == -1) + idx = dev->entries_curr_table - 1; + + fmt->width = dev->curr_res_table[idx].width; + fmt->height = dev->curr_res_table[idx].height; + } + + fmt->code = V4L2_MBUS_FMT_SBGGR10_1X10; + return 0; +} + +static int ov8865_try_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + int r; + + mutex_lock(&dev->input_lock); + r = __ov8865_try_mbus_fmt(sd, fmt); + mutex_unlock(&dev->input_lock); + + return r; +} + +static int ov8865_s_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct camera_mipi_info *ov8865_info = NULL; + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 hts, vts; + int ret; + const struct ov8865_resolution *res; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + ov8865_info = v4l2_get_subdev_hostdata(sd); + if (ov8865_info == NULL) + return -EINVAL; + + mutex_lock(&dev->input_lock); + + ret = __ov8865_try_mbus_fmt(sd, fmt); + if (ret) + goto out; + + dev->fmt_idx = get_resolution_index(sd, fmt->width, fmt->height); + /* Sanity check */ + if (unlikely(dev->fmt_idx == -1)) { + ret = -EINVAL; + goto out; + } + + /* Sets the default FPS */ + dev->fps_index = 0; + + /* Get the current resolution setting */ + res = &dev->curr_res_table[dev->fmt_idx]; + + /* Write the selected resolution table values to the registers */ + ret = ov8865_write_reg_array(client, res->regs); + if (ret) + goto out; + + OV8865_LOG(2, "%s %d name:%s width:%d height:%d\n", __func__, __LINE__, res->desc, res->width, res->height); + /* Frame timing registers are updates as part of exposure */ + hts = res->fps_options[dev->fps_index].pixels_per_line; + vts = res->fps_options[dev->fps_index].lines_per_frame; + + /* + * update hts, vts, exposure and gain as one block. Note that the vts + * will be changed according to the exposure used. But the maximum vts + * dev->curr_res_table[dev->fmt_idx] should not be changed at all. + */ + ret = __ov8865_set_exposure(sd, dev->exposure, dev->gain, + dev->digital_gain, &hts, &vts); + if (ret) + goto out; + + ret = ov8865_get_intg_factor(sd, ov8865_info, dev->basic_settings_list); + +out: + mutex_unlock(&dev->input_lock); + + return ret; +} + +static int ov8865_g_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + + if (!fmt) + return -EINVAL; + + mutex_lock(&dev->input_lock); + fmt->width = dev->curr_res_table[dev->fmt_idx].width; + fmt->height = dev->curr_res_table[dev->fmt_idx].height; + fmt->code = V4L2_MBUS_FMT_SBGGR10_1X10; + mutex_unlock(&dev->input_lock); + + return 0; +} + +static int ov8865_detect(struct i2c_client *client, u16 *id, u8 *revision) +{ + struct i2c_adapter *adapter = client->adapter; + int ret; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + /* i2c check */ + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return -ENODEV; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + + /* check sensor chip ID - are same for both 8865 and 8835 modules */ + ret = ov8865_read_reg(client, OV8865_16BIT, OV8865_CHIP_ID_HIGH, id); + dev_info(&client->dev, "chip_id = 0x%4.4x\n", *id); + + if (ret) + return ret; + + OV8865_LOG(1, "%s %d\n", __func__, __LINE__); + /* This always reads as 0x8865, even on 8835. */ + dev_info(&client->dev, "chip_id = 0x%4.4x\n", *id); + if (*id != OV8865_CHIP_ID) + return -ENODEV; + + return 0; +} + +/* + * ov8865 stream on/off + */ +static int ov8865_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + mutex_lock(&dev->input_lock); + //printk("ov8865, ov8865_s_stream, before ov8865_write_reg\n"); + ret = ov8865_write_reg(client, OV8865_8BIT, 0x0100, enable ? 1 : 0); + if (ret != 0) { + mutex_unlock(&dev->input_lock); + v4l2_err(client, "failed to set streaming\n"); + // printk("failed to set streaming\n"); + return ret; + } + + dev->streaming = enable; + + mutex_unlock(&dev->input_lock); + + return 0; +} + +/* + * ov8865 enum frame size, frame intervals + */ +static int ov8865_enum_framesizes(struct v4l2_subdev *sd, + struct v4l2_frmsizeenum *fsize) +{ + unsigned int index = fsize->index; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + mutex_lock(&dev->input_lock); + if (index >= dev->entries_curr_table) { + mutex_unlock(&dev->input_lock); + return -EINVAL; + } + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = dev->curr_res_table[index].width; + fsize->discrete.height = dev->curr_res_table[index].height; + fsize->reserved[0] = dev->curr_res_table[index].used; + mutex_unlock(&dev->input_lock); + + return 0; +} + +static int ov8865_enum_frameintervals(struct v4l2_subdev *sd, + struct v4l2_frmivalenum *fival) +{ + unsigned int index = fival->index; + int fmt_index; + struct ov8865_device *dev = to_ov8865_sensor(sd); + const struct ov8865_resolution *res; + + mutex_lock(&dev->input_lock); + + /* + * since the isp will donwscale the resolution to the right size, + * find the nearest one that will allow the isp to do so important to + * ensure that the resolution requested is padded correctly by the + * requester, which is the atomisp driver in this case. + */ + fmt_index = nearest_resolution_index(sd, fival->width, fival->height); + if (-1 == fmt_index) + fmt_index = dev->entries_curr_table - 1; + + res = &dev->curr_res_table[fmt_index]; + + /* Check if this index is supported */ + if (index > __ov8865_get_max_fps_index(res->fps_options)) { + mutex_unlock(&dev->input_lock); + return -EINVAL; + } + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = res->fps_options[index].fps; + + mutex_unlock(&dev->input_lock); + + return 0; +} + +static int ov8865_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + *code = V4L2_MBUS_FMT_SBGGR10_1X10; + return 0; +} + +static int ov8865_s_config(struct v4l2_subdev *sd, + int irq, void *pdata) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 sensor_revision = 0; + u16 sensor_id; + int ret; + +// OV8865_LOG(2, "%s %d pdata=%x\n", __func__, __LINE__, (unsigned int)pdata); + if (pdata == NULL) + return -ENODEV; + + dev->platform_data = pdata; + + mutex_lock(&dev->input_lock); + + if (dev->platform_data->platform_init) { + ret = dev->platform_data->platform_init(client); + if (ret) { + mutex_unlock(&dev->input_lock); + v4l2_err(client, "ov8865 platform init err\n"); + return ret; + } + } + + OV8865_LOG(1, "%s %d ov8865 platform_init done\n", __func__, __LINE__); + //printk(" ov8865 platform_init done\n"); + + ret = __ov8865_s_power(sd, 1); + if (ret) { + mutex_unlock(&dev->input_lock); + v4l2_err(client, "ov8865 power-up err.\n"); + return ret; + } + OV8865_LOG(1, "%s %d ov8865 s_power done\n", __func__, __LINE__); + dev->otp_data = NULL; + //ret = request_firmware(&fw, OV8865_OTP_INPUT_NAME, &client->dev); + //if (ret) { + OV8865_LOG(2,"ov8865 load from user-space failed, load from sensor\n"); + ov8865_write_reg(client, OV8865_8BIT, 0x5002, 0x00); + ov8865_write_reg(client, OV8865_8BIT, 0x0100, 0x01); + ret = ov8865_otp_read(client, ov8865_raw, &ov8865_raw_size); + ov8865_write_reg(client, OV8865_8BIT, 0x5002, 0x08); + ov8865_write_reg(client, OV8865_8BIT, 0x0100, 0x00); + if (!ret) { + //printk("ov8865 otp read done\n"); + ret = ov8865_otp_trans(ov8865_raw, ov8865_raw_size, ov8865_otp_data, &ov8865_otp_size); + if (!ret) { + // printk("ov8865 otp trans done\n"); + dev->otp_data = ov8865_otp_data; + } else + printk("ov8865 otp trans failed\n"); + } + //} else { + // OV8865_LOG(2, "ov8865 load from user-space success size:0x%x\n", fw->size); + // memcpy(ov8865_raw, fw->data, fw->size); + // ov8865_raw_size = fw->size; + // ret = ov8865_otp_trans(ov8865_raw, ov8865_raw_size, ov8865_otp_data, &ov8865_otp_size); + // if (!ret) { + // OV8865_LOG(2, "ov8865 otp trans done\n"); + // dev->otp_data = ov8865_otp_data; + // } else + // OV8865_LOG(2, "ov8865 otp trans failed\n"); + //} + + + ret = dev->platform_data->csi_cfg(sd, 1); + if (ret) + goto fail_csi_cfg; + + OV8865_LOG(1, "%s %d ov8865 csi_cfg done\n", __func__, __LINE__); + /* config & detect sensor */ + ret = ov8865_detect(client, &sensor_id, &sensor_revision); + if (ret) { + v4l2_err(client, "ov8865_detect err s_config.\n"); + goto fail_detect; + } + OV8865_LOG(1, "%s %d ov8865 detect done\n", __func__, __LINE__); + dev->sensor_id = sensor_id; + dev->sensor_revision = sensor_revision; + + /* power off sensor */ + ret = __ov8865_s_power(sd, 0); + mutex_unlock(&dev->input_lock); + if (ret) { + v4l2_err(client, "ov8865 power-down err.\n"); + return ret; + } + + OV8865_LOG(1, "%s %d ov8865 s_config successfully\n", __func__, __LINE__); + return 0; + +fail_detect: + dev->platform_data->csi_cfg(sd, 0); +fail_csi_cfg: + __ov8865_s_power(sd, 0); + mutex_unlock(&dev->input_lock); + dev_err(&client->dev, "sensor power-gating failed\n"); + return ret; +} + +static int +ov8865_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index) + return -EINVAL; + code->code = V4L2_MBUS_FMT_SBGGR10_1X10; + + return 0; +} + +static int +ov8865_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + int index = fse->index; + struct ov8865_device *dev = to_ov8865_sensor(sd); + + mutex_lock(&dev->input_lock); + if (index >= dev->entries_curr_table) { + mutex_unlock(&dev->input_lock); + return -EINVAL; + } + + fse->min_width = dev->curr_res_table[index].width; + fse->min_height = dev->curr_res_table[index].height; + fse->max_width = dev->curr_res_table[index].width; + fse->max_height = dev->curr_res_table[index].height; + mutex_unlock(&dev->input_lock); + + return 0; +} + +static struct v4l2_mbus_framefmt * +__ov8865_get_pad_format(struct ov8865_device *sensor, + struct v4l2_subdev_fh *fh, unsigned int pad, + enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(fh, pad); + + return &sensor->format; +} + +static int +ov8865_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + + fmt->format = *__ov8865_get_pad_format(dev, fh, fmt->pad, fmt->which); + + return 0; +} + +static int +ov8865_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + struct v4l2_mbus_framefmt *format = + __ov8865_get_pad_format(dev, fh, fmt->pad, fmt->which); + + *format = fmt->format; + + return 0; +} + +static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov8865_device *dev = container_of( + ctrl->handler, struct ov8865_device, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + + /* input_lock is taken by the control framework, so it + * doesn't need to be taken here. + */ + + /* We only handle V4L2_CID_RUN_MODE for now. */ + switch (ctrl->id) { + case V4L2_CID_RUN_MODE: + switch (ctrl->val) { + case ATOMISP_RUN_MODE_VIDEO: + dev->curr_res_table = ov8865_res_video; + dev->entries_curr_table = ARRAY_SIZE(ov8865_res_video); + break; + case ATOMISP_RUN_MODE_STILL_CAPTURE: + dev->curr_res_table = ov8865_res_still; + dev->entries_curr_table = ARRAY_SIZE(ov8865_res_still); + break; + default: + dev->curr_res_table = ov8865_res_preview; + dev->entries_curr_table = ARRAY_SIZE(ov8865_res_preview); + } + + dev->fmt_idx = 0; + dev->fps_index = 0; + return 0; + case V4L2_CID_TEST_PATTERN: + return ov8865_write_reg(client, OV8865_16BIT, 0x3070, + ctrl->val); + /* shunyong: disable focus when PO */ + case V4L2_CID_FOCUS_ABSOLUTE: + return bu64243_t_focus_abs(&dev->sd, ctrl->val); + } + return -EINVAL; /* Should not happen. */ +} + +static int ov8865_g_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov8865_device *dev = container_of( + ctrl->handler, struct ov8865_device, ctrl_handler); + + switch (ctrl->id) { + /* shunyong, disable Focus when PO */ + case V4L2_CID_FOCUS_STATUS: { + static const struct timespec move_time = { + /* The time required for focus motor to move the lens */ + .tv_sec = 0, + .tv_nsec = 60000000, + }; + struct bu64243_device *bu64243 = to_bu64243_device(&dev->sd); + struct timespec current_time, finish_time, delta_time; + + getnstimeofday(¤t_time); + finish_time = timespec_add(bu64243->focus_time, move_time); + delta_time = timespec_sub(current_time, finish_time); + if (delta_time.tv_sec >= 0 && delta_time.tv_nsec >= 0) { + /* VCM motor is not moving */ + ctrl->val = ATOMISP_FOCUS_HP_COMPLETE | + ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE; + } else { + /* VCM motor is still moving */ + ctrl->val = ATOMISP_FOCUS_STATUS_MOVING | + ATOMISP_FOCUS_HP_IN_PROGRESS; + } + return 0; + } + break; + case V4L2_CID_EXPOSURE_ABSOLUTE: + ctrl->val = exposure_time; + return 0; + case V4L2_CID_BIN_FACTOR_HORZ: + case V4L2_CID_BIN_FACTOR_VERT: { + ctrl->val = ctrl->id == V4L2_CID_BIN_FACTOR_HORZ ? + dev->curr_res_table[dev->fmt_idx].bin_factor_x: dev->curr_res_table[dev->fmt_idx].bin_factor_y; + + OV8865_LOG(1, "bin-factor for ISP:%d\n", ctrl->val); + return 0; + } + } + + return 0; +} + +static int +ov8865_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + const struct ov8865_resolution *res; + + mutex_lock(&dev->input_lock); + + /* Return the currently selected settings' maximum frame interval */ + res = &dev->curr_res_table[dev->fmt_idx]; + + interval->interval.numerator = 1; + interval->interval.denominator = res->fps_options[dev->fps_index].fps; + + mutex_unlock(&dev->input_lock); + + return 0; +} +#if 0 +static int ov8865_s_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + int ret; + + mutex_lock(&dev->input_lock); + ret = __ov8865_s_frame_interval(sd, interval); + mutex_unlock(&dev->input_lock); + + return ret; +} +#endif +static int ov8865_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) +{ + struct ov8865_device *dev = to_ov8865_sensor(sd); + + mutex_lock(&dev->input_lock); + *frames = dev->curr_res_table[dev->fmt_idx].skip_frames; + mutex_unlock(&dev->input_lock); + + return 0; +} + +static const struct v4l2_subdev_video_ops ov8865_video_ops = { + .s_stream = ov8865_s_stream, + .enum_framesizes = ov8865_enum_framesizes, + .enum_frameintervals = ov8865_enum_frameintervals, + .enum_mbus_fmt = ov8865_enum_mbus_fmt, + .try_mbus_fmt = ov8865_try_mbus_fmt, + .g_mbus_fmt = ov8865_g_mbus_fmt, + .s_mbus_fmt = ov8865_s_mbus_fmt, + .g_frame_interval = ov8865_g_frame_interval, + //.s_frame_interval = ov8865_s_frame_interval, +}; + +static const struct v4l2_subdev_sensor_ops ov8865_sensor_ops = { + .g_skip_frames = ov8865_g_skip_frames, +}; + +static const struct v4l2_subdev_core_ops ov8865_core_ops = { + .g_chip_ident = ov8865_g_chip_ident, + .queryctrl = v4l2_subdev_queryctrl, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .s_power = ov8865_s_power, + .ioctl = ov8865_ioctl, + .init = ov8865_init, +}; + +/* REVISIT: Do we need pad operations? */ +static const struct v4l2_subdev_pad_ops ov8865_pad_ops = { + .enum_mbus_code = ov8865_enum_mbus_code, + .enum_frame_size = ov8865_enum_frame_size, + .get_fmt = ov8865_get_pad_format, + .set_fmt = ov8865_set_pad_format, +}; + +static const struct v4l2_subdev_ops ov8865_ops = { + .core = &ov8865_core_ops, + .video = &ov8865_video_ops, + .pad = &ov8865_pad_ops, + .sensor = &ov8865_sensor_ops, +}; + +static int ov8865_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov8865_device *dev = to_ov8865_sensor(sd); + if (dev->platform_data->platform_deinit) + dev->platform_data->platform_deinit(); + + media_entity_cleanup(&dev->sd.entity); + v4l2_ctrl_handler_free(&dev->ctrl_handler); + dev->platform_data->csi_cfg(sd, 0); + v4l2_device_unregister_subdev(sd); + kfree(dev); + + return 0; +} + +static const struct v4l2_ctrl_ops ctrl_ops = { + .s_ctrl = ov8865_s_ctrl, + .g_volatile_ctrl = ov8865_g_ctrl, +}; + +static const char * const ctrl_run_mode_menu[] = { + NULL, + "Video", + "Still capture", + "Continuous capture", + "Preview", +}; + +static const struct v4l2_ctrl_config ctrl_run_mode = { + .ops = &ctrl_ops, + .id = V4L2_CID_RUN_MODE, + .name = "run mode", + .type = V4L2_CTRL_TYPE_MENU, + .min = 1, + .def = 4, + .max = 4, + .qmenu = ctrl_run_mode_menu, +}; + +static const struct v4l2_ctrl_config ctrls[] = { + { + .ops = &ctrl_ops, + .id = V4L2_CID_EXPOSURE_ABSOLUTE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .max = 0xffff, + .step = 0x01, + .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE, + + }, { + .ops = &ctrl_ops, + .id = V4L2_CID_TEST_PATTERN, + .name = "Test pattern", + .type = V4L2_CTRL_TYPE_INTEGER, + .step = 1, + .max = 0xffff, + }, { + .ops = &ctrl_ops, + .id = V4L2_CID_FOCUS_ABSOLUTE, + .name = "Focus absolute", + .type = V4L2_CTRL_TYPE_INTEGER, + .step = 1, + .max = BU64243_MAX_FOCUS_POS, + }, { + /* This one is junk: see the spec for proper use of this CID. */ + .ops = &ctrl_ops, + .id = V4L2_CID_FOCUS_STATUS, + .name = "Focus status", + .type = V4L2_CTRL_TYPE_INTEGER, + .step = 1, + .max = 100, + .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE, + }, { + /* This is crap. For compatibility use only. */ + .ops = &ctrl_ops, + .id = V4L2_CID_FOCAL_ABSOLUTE, + .name = "Focal lenght", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = (OV8865_FOCAL_LENGTH_NUM << 16) | OV8865_FOCAL_LENGTH_DEM, + .max = (OV8865_FOCAL_LENGTH_NUM << 16) | OV8865_FOCAL_LENGTH_DEM, + .step = 1, + .def = (OV8865_FOCAL_LENGTH_NUM << 16) | OV8865_FOCAL_LENGTH_DEM, + .flags = V4L2_CTRL_FLAG_READ_ONLY, + }, { + /* This one is crap, too. For compatibility use only. */ + .ops = &ctrl_ops, + .id = V4L2_CID_FNUMBER_ABSOLUTE, + .name = "F-number", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = (OV8865_F_NUMBER_DEFAULT_NUM << 16) | OV8865_F_NUMBER_DEM, + .max = (OV8865_F_NUMBER_DEFAULT_NUM << 16) | OV8865_F_NUMBER_DEM, + .step = 1, + .def = (OV8865_F_NUMBER_DEFAULT_NUM << 16) | OV8865_F_NUMBER_DEM, + .flags = V4L2_CTRL_FLAG_READ_ONLY, + }, { + /* + * The most utter crap. _Never_ use this, even for + * compatibility reasons! + */ + .ops = &ctrl_ops, + .id = V4L2_CID_FNUMBER_RANGE, + .name = "F-number range", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = (OV8865_F_NUMBER_DEFAULT_NUM << 24) | (OV8865_F_NUMBER_DEM << 16) | (OV8865_F_NUMBER_DEFAULT_NUM << 8) | OV8865_F_NUMBER_DEM, + .max = (OV8865_F_NUMBER_DEFAULT_NUM << 24) | (OV8865_F_NUMBER_DEM << 16) | (OV8865_F_NUMBER_DEFAULT_NUM << 8) | OV8865_F_NUMBER_DEM, + .step = 1, + .def = (OV8865_F_NUMBER_DEFAULT_NUM << 24) | (OV8865_F_NUMBER_DEM << 16) | (OV8865_F_NUMBER_DEFAULT_NUM << 8) | OV8865_F_NUMBER_DEM, + .flags = V4L2_CTRL_FLAG_READ_ONLY, + }, { + .ops = &ctrl_ops, + .id = V4L2_CID_BIN_FACTOR_HORZ, + .name = "Horizontal binning factor", + .type = V4L2_CTRL_TYPE_INTEGER, + .max = OV8865_BIN_FACTOR_MAX, + .step = 1, + .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE, + }, { + .ops = &ctrl_ops, + .id = V4L2_CID_BIN_FACTOR_VERT, + .name = "Vertical binning factor", + .type = V4L2_CTRL_TYPE_INTEGER, + .max = OV8865_BIN_FACTOR_MAX, + .step = 1, + .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE, + } +}; + +static int ov8865_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ov8865_device *dev; + unsigned int i; + int ret; + + OV8865_LOG(2, "%s %d start\n", __func__, __LINE__); + //printk("ov8865 start\n"); + /* allocate sensor device & init sub device */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + v4l2_err(client, "%s: out of memory\n", __func__); + //printk("ov8865 out of memory\n"); + return -ENOMEM; + } + + /* shunyong, disable focus when PO */ + + mutex_init(&dev->input_lock); + + dev->fmt_idx = 0; + v4l2_i2c_subdev_init(&(dev->sd), client, &ov8865_ops); + + ret = bu64243_init(&dev->sd); + if (ret < 0) + goto out_free; + + OV8865_LOG(1, "%s %d vcm done\n", __func__, __LINE__); + //printk("ov8865 vcm done\n"); + if (client->dev.platform_data) { + //printk("ov8865 dev.platform_data\n"); + ret = ov8865_s_config(&dev->sd, client->irq, + client->dev.platform_data); + //printk("ov8865 end ov8865_s_config\n"); + if (ret) { + //printk("ov8865 out_free\n"); + goto out_free; + } + } + + OV8865_LOG(1, "%s %d s_config done\n", __func__, __LINE__); + //printk("ov8865 s_config done\n"); + dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + dev->pad.flags = MEDIA_PAD_FL_SOURCE; + dev->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; + dev->format.code = V4L2_MBUS_FMT_SBGGR10_1X10; + + ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, ARRAY_SIZE(ctrls) + 1); + if (ret) { + ov8865_remove(client); + return ret; + } + + OV8865_LOG(1, "%s %d handle init done\n", __func__, __LINE__); + //printk("ov8865 handle init done\n"); + dev->run_mode = v4l2_ctrl_new_custom(&dev->ctrl_handler, + &ctrl_run_mode, NULL); + + for (i = 0; i < ARRAY_SIZE(ctrls); i++) + v4l2_ctrl_new_custom(&dev->ctrl_handler, &ctrls[i], NULL); + + if (dev->ctrl_handler.error) { + ov8865_remove(client); + return dev->ctrl_handler.error; + } + + /* Use same lock for controls as for everything else. */ + dev->ctrl_handler.lock = &dev->input_lock; + dev->sd.ctrl_handler = &dev->ctrl_handler; + v4l2_ctrl_handler_setup(&dev->ctrl_handler); + + OV8865_LOG(1, "%s %d ctrl added\n", __func__, __LINE__); + //printk("ov8865 ctrl added\n"); + ret = media_entity_init(&dev->sd.entity, 1, &dev->pad, 0); + if (ret) { + ov8865_remove(client); + return ret; + } + + global_dev = dev; + OV8865_LOG(2, "%s %d done\n", __func__, __LINE__); + //printk("ov8865 done\n"); + return 0; + +out_free: + + OV8865_LOG(1, "%s %d fail, free\n", __func__, __LINE__); + //printk("ov8865 fail, free\n"); + v4l2_device_unregister_subdev(&dev->sd); + kfree(dev); + return ret; +} + +static const struct i2c_device_id ov8865_id[] = { + {OV8865_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ov8865_id); + +static struct i2c_driver ov8865_driver = { + .driver = { + .owner = THIS_MODULE, + .name = OV8865_NAME, + }, + .probe = ov8865_probe, + .remove = ov8865_remove, + .id_table = ov8865_id, +}; + +static __init int ov8865_init_mod(void) +{ + OV8865_LOG(2, "%s %d\n", __func__, __LINE__); + return i2c_add_driver(&ov8865_driver); +} + +static __exit void ov8865_exit_mod(void) +{ + OV8865_LOG(2, "%s %d\n", __func__, __LINE__); + i2c_del_driver(&ov8865_driver); +} + +module_init(ov8865_init_mod); +module_exit(ov8865_exit_mod); + +MODULE_DESCRIPTION("A low-level driver for Omnivision OV8865 sensors"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov8865.h b/drivers/media/i2c/ov8865.h new file mode 100644 index 000000000..fb26318f7 --- /dev/null +++ b/drivers/media/i2c/ov8865.h @@ -0,0 +1,2723 @@ +/* + * Support for Omnivision OV8865 camera sensor. + * Based on Aptina mt9e013 driver. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef __OV8865_H__ +#define __OV8865_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define to_bu64243_device(_sd) (&(container_of(_sd, struct ov8865_device, sd) \ + ->bu64243)) + +#define BU64243_W0_W2(a) ((a & 0x07) << 3) +#define BU64243_PS(a) (a << 7) +#define BU64243_EN(a) (a << 6) +#define BU64243_M(a) (a << 2) +#define BU64243_D_HI(a) ((a >> 8) & 0x03) +#define BU64243_D_LO(a) (a & 0xff) +#define BU64243_RFEQ(a) ((a & 0x1f) << 3) +#define BU64243_SRATE(a) (a & 0x03) +#define BU64243_STIME(a) (a & 0x1f) +#define BU64243_SRES(a) ((a & 0x07) << 5) +#define BU64243_I2C_ADDR 0x0C +#define BU64243_VCM_CURRENT 0 /* point C */ +#define BU64243_PARAM_1 1 /* freq and slew rate */ +#define BU64243_PARAM_2 2 /* point A */ +#define BU64243_PARAM_3 3 /* point B */ +#define BU64243_PARAM_4 4 /*step res and step time*/ + + + +#define BU64243_DEFAULT_POINT_A 0x2a /* 42 */ +#define BU64243_DEFAULT_POINT_B 0x52 /* 82 */ +#define BU64243_DEFAULT_POINT_C 0xCB /* 203*/ +#define BU64243_DEFAULT_VCM_FREQ 0x08 /* 85HZ */ +#define BU64243_DEFAULT_SLEW_RATE 0x03 /* fastest */ +#define BU64243_DEFAULT_RES_SETTING 0x04 /* 4LSB */ +#define BU64243_DEFAULT_STEP_TIME_SETTING 0x04 /* 200us */ +#define BU64243_DEFAULT_OUTPUT_STATUS 0x01 /* 0 um */ +#define BU64243_DEFAULT_ISRC_MODE 0x01 /* 0 um */ + +#define INTEL_FOCUS_OFFSET 20 +#define VCM_ORIENTATION_OFFSET 100 +#define POINT_AB_OFFSET 40 + +#define BU64243_MAX_FOCUS_POS 1023 + +/* bu64243 device structure */ +struct bu64243_device { + bool initialized; /* true if bu64243 is detected */ + u16 focus; + u16 power_state; + u16 output_status; /* */ + u16 isrc_mode; /* ISRC enable */ + u16 point_a; /* 0 um */ + u16 point_b; /* lens float */ + u16 point_c; /* focus point*/ + u16 res_freq; /* resonant frequency*/ + u16 slew_rate; /* slew rate*/ + u16 step_res; /* step resolution */ + u16 step_time; /* step time */ + struct timespec focus_time; /* Time when focus was last time set */ + __u8 buffer[4]; /* Used for i2c transactions */ + const struct camera_af_platform_data *platform_data; +}; + +#define OV8865_NAME "ov8865" +#define OV8865_ADDR 0x10 + + +#define OV8865_CHIP_ID 0x8865 + + +#define LAST_REG_SETING {0xffff, 0xff} +#define is_last_reg_setting(item) ((item).reg == 0xffff) +#define I2C_MSG_LENGTH 0x2 + +#define OV8865_INVALID_CONFIG 0xffffffff + +#define OV8865_INTG_UNIT_US 100 +#define OV8865_MCLK 192 + +#define OV8865_REG_BITS 16 +#define OV8865_REG_MASK 0xFFFF + +/* This should be added into include/linux/videodev2.h */ +#ifndef V4L2_IDENT_OV8865 +#define V4L2_IDENT_OV8865 8245 +#endif + +/* + * ov8865 System control registers + */ +#define OV8865_PLL_PLL10 0x3090 +#define OV8865_PLL_PLL11 0x3091 +#define OV8865_PLL_PLL12 0x3092 +#define OV8865_PLL_PLL13 0x3093 +#define OV8865_TIMING_VTS 0x380e +#define OV8865_TIMING_HTS 0x380C + +#define PLL1_SYS_PRE_DIV 0x030F + +#define OV8865_HORIZONTAL_START_H 0x3800 +#define OV8865_HORIZONTAL_START_L 0x3801 +#define OV8865_VERTICAL_START_H 0x3802 +#define OV8865_VERTICAL_START_L 0x3803 +#define OV8865_HORIZONTAL_END_H 0x3804 +#define OV8865_HORIZONTAL_END_L 0x3805 +#define OV8865_VERTICAL_END_H 0x3806 +#define OV8865_VERTICAL_END_L 0x3807 +#define OV8865_HORIZONTAL_OUTPUT_SIZE_H 0x3808 +#define OV8865_HORIZONTAL_OUTPUT_SIZE_L 0x3809 +#define OV8865_VERTICAL_OUTPUT_SIZE_H 0x380a +#define OV8865_VERTICAL_OUTPUT_SIZE_L 0x380b + +#define OV8865_GROUP_ACCESS 0x3208 +#define OV8865_GROUP_ACCESS_HOLD_START 0x00 +#define OV8865_GROUP_ACCESS_HOLD_END 0x10 +#define OV8865_GROUP_ACCESS_DELAY_LAUNCH 0xA0 +#define OV8865_GROUP_ACCESS_QUICK_LAUNCH 0xE0 + +#define OV8865_LONG_EXPO 0x3500 +#define OV8865_AGC_ADJ 0x3508 +#define OV8865_TEST_PATTERN_MODE 0x3070 + +/* ov8865 SCCB */ +#define OV8865_SCCB_CTRL 0x3100 +#define OV8865_AEC_PK_EXPO_H 0x3500 +#define OV8865_AEC_PK_EXPO_M 0x3501 +#define OV8865_AEC_PK_EXPO_L 0x3502 +#define OV8865_AEC_MANUAL_CTRL 0x3503 +#define OV8865_AGC_ADJ_H 0x3508 +#define OV8865_AGC_ADJ_L 0x3509 + +#define OV8865_MWB_RED_GAIN_H 0x3400 +#define OV8865_MWB_GREEN_GAIN_H 0x3402 +#define OV8865_MWB_BLUE_GAIN_H 0x3404 +#define OV8865_DIGI_GAIN 0x350A +#define OV8865_MWB_GAIN_MAX 0x3fff + +#define OV8865_OTP_BANK0_PID 0x3d00 +#define OV8865_CHIP_ID_HIGH 0x300B +#define OV8865_CHIP_ID_LOW 0x300C +#define OV8865_STREAM_MODE 0x0100 + +#define OV8865_FOCAL_LENGTH_NUM 439 /*4.39mm*/ +#define OV8865_FOCAL_LENGTH_DEM 100 +#define OV8865_F_NUMBER_DEFAULT_NUM 22 +#define OV8865_F_NUMBER_DEM 10 + +#define OV8865_TIMING_X_INC 0x3814 +#define OV8865_TIMING_Y_INC 0x382A + +#define OV8865_ISP_CTRL 0x501E + +/* sensor_mode_data read_mode adaptation */ +#define OV8865_READ_MODE_BINNING_ON 0x0400 +#define OV8865_READ_MODE_BINNING_OFF 0x00 +#define OV8865_INTEGRATION_TIME_MARGIN 4 + +#define OV8865_MAX_VTS_VALUE 0x7FFF +#define OV8865_MAX_EXPOSURE_VALUE \ + (OV8865_MAX_VTS_VALUE - OV8865_INTEGRATION_TIME_MARGIN) +#define OV8865_MAX_GAIN_VALUE 0xfff /*x32 gain*/ + +/* + * focal length bits definition: + * bits 31-16: numerator, bits 15-0: denominator + */ +#define OV8865_FOCAL_LENGTH_DEFAULT ((385<<16)|100) //3.85 + +/* + * current f-number bits definition: + * bits 31-16: numerator, bits 15-0: denominator + */ +#define OV8865_F_NUMBER_DEFAULT ((220<<16)|100) //2.2 + +/* + * f-number range bits definition: + * bits 31-24: max f-number numerator + * bits 23-16: max f-number denominator + * bits 15-8: min f-number numerator + * bits 7-0: min f-number denominator + */ +#define OV8865_F_NUMBER_RANGE 0x180a180a +#define OTPM_ADD_START_1 0x1000 +#define OTPM_DATA_LENGTH_1 0x0100 +#define OTPM_COUNT 0x200 + +/* Defines for register writes and register array processing */ +#define OV8865_BYTE_MAX 32 +#define OV8865_SHORT_MAX 16 +#define I2C_RETRY_COUNT 5 +#define OV8865_TOK_MASK 0xfff0 + +#define OV8865_STATUS_POWER_DOWN 0x0 +#define OV8865_STATUS_STANDBY 0x2 +#define OV8865_STATUS_ACTIVE 0x3 +#define OV8865_STATUS_VIEWFINDER 0x4 + +#define MAX_FPS_OPTIONS_SUPPORTED 3 + +#define v4l2_format_capture_type_entry(_width, _height, \ + _pixelformat, _bytesperline, _colorspace) \ + {\ + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,\ + .fmt.pix.width = (_width),\ + .fmt.pix.height = (_height),\ + .fmt.pix.pixelformat = (_pixelformat),\ + .fmt.pix.bytesperline = (_bytesperline),\ + .fmt.pix.colorspace = (_colorspace),\ + .fmt.pix.sizeimage = (_height)*(_bytesperline),\ + } + +#define s_output_format_entry(_width, _height, _pixelformat, \ + _bytesperline, _colorspace, _fps) \ + {\ + .v4l2_fmt = v4l2_format_capture_type_entry(_width, \ + _height, _pixelformat, _bytesperline, \ + _colorspace),\ + .fps = (_fps),\ + } + +#define s_output_format_reg_entry(_width, _height, _pixelformat, \ + _bytesperline, _colorspace, _fps, _reg_setting) \ + {\ + .s_fmt = s_output_format_entry(_width, _height,\ + _pixelformat, _bytesperline, \ + _colorspace, _fps),\ + .reg_setting = (_reg_setting),\ + } + +struct s_ctrl_id { + struct v4l2_queryctrl qc; + int (*s_ctrl)(struct v4l2_subdev *sd, u32 val); + int (*g_ctrl)(struct v4l2_subdev *sd, u32 *val); +}; + +#define v4l2_queryctrl_entry_integer(_id, _name,\ + _minimum, _maximum, _step, \ + _default_value, _flags) \ + {\ + .id = (_id), \ + .type = V4L2_CTRL_TYPE_INTEGER, \ + .name = _name, \ + .minimum = (_minimum), \ + .maximum = (_maximum), \ + .step = (_step), \ + .default_value = (_default_value),\ + .flags = (_flags),\ + } +#define v4l2_queryctrl_entry_boolean(_id, _name,\ + _default_value, _flags) \ + {\ + .id = (_id), \ + .type = V4L2_CTRL_TYPE_BOOLEAN, \ + .name = _name, \ + .minimum = 0, \ + .maximum = 1, \ + .step = 1, \ + .default_value = (_default_value),\ + .flags = (_flags),\ + } + +#define s_ctrl_id_entry_integer(_id, _name, \ + _minimum, _maximum, _step, \ + _default_value, _flags, \ + _s_ctrl, _g_ctrl) \ + {\ + .qc = v4l2_queryctrl_entry_integer(_id, _name,\ + _minimum, _maximum, _step,\ + _default_value, _flags), \ + .s_ctrl = _s_ctrl, \ + .g_ctrl = _g_ctrl, \ + } + +#define s_ctrl_id_entry_boolean(_id, _name, \ + _default_value, _flags, \ + _s_ctrl, _g_ctrl) \ + {\ + .qc = v4l2_queryctrl_entry_boolean(_id, _name,\ + _default_value, _flags), \ + .s_ctrl = _s_ctrl, \ + .g_ctrl = _g_ctrl, \ + } + + +#define macro_string_entry(VAL) \ + { \ + .val = VAL, \ + .string = #VAL, \ + } + +enum ov8865_tok_type { + OV8865_8BIT = 0x0001, + OV8865_16BIT = 0x0002, + OV8865_TOK_TERM = 0xf000, /* terminating token for reg list */ + OV8865_TOK_DELAY = 0xfe00 /* delay token for reg list */ +}; + +/* + * If register address or register width is not 32 bit width, + * user needs to convert it manually + */ + +struct s_register_setting { + u32 reg; + u32 val; +}; + +struct s_output_format { + struct v4l2_format v4l2_fmt; + int fps; +}; + +/** + * struct ov8865_fwreg - Firmware burst command + * @type: FW burst or 8/16 bit register + * @addr: 16-bit offset to register or other values depending on type + * @val: data value for burst (or other commands) + * + * Define a structure for sensor register initialization values + */ +struct ov8865_fwreg { + enum ov8865_tok_type type; /* value, register or FW burst string */ + u16 addr; /* target address */ + u32 val[8]; +}; + +/** + * struct ov8865_reg - MI sensor register format + * @type: type of the register + * @reg: 16-bit offset to register + * @val: 8/16/32-bit register value + * + * Define a structure for sensor register initialization values + */ +struct ov8865_reg { + enum ov8865_tok_type type; + union { + u16 sreg; + struct ov8865_fwreg *fwreg; + } reg; + u32 val; /* @set value for read/mod/write, @mask */ + u32 val2; /* optional: for rmw, OR mask */ +}; + +struct ov8865_fps_setting { + int fps; + unsigned short pixels_per_line; + unsigned short lines_per_frame; +}; + +/* Store macro values' debug names */ +struct macro_string { + u8 val; + char *string; +}; + +static inline const char * +macro_to_string(const struct macro_string *array, int size, u8 val) +{ + int i; + for (i = 0; i < size; i++) { + if (array[i].val == val) + return array[i].string; + } + return "Unknown VAL"; +} + +struct ov8865_control { + struct v4l2_queryctrl qc; + int (*query)(struct v4l2_subdev *sd, s32 *value); + int (*tweak)(struct v4l2_subdev *sd, s32 value); +}; + +struct ov8865_resolution { + u8 *desc; + int res; + int width; + int height; + bool used; + const struct ov8865_reg *regs; + u8 bin_factor_x; + u8 bin_factor_y; + unsigned short skip_frames; + const struct ov8865_fps_setting fps_options[MAX_FPS_OPTIONS_SUPPORTED]; +}; + +struct ov8865_format { + u8 *desc; + u32 pixelformat; + struct s_register_setting *regs; +}; + +/* ov8865 device structure */ +struct ov8865_device { + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_mbus_framefmt format; + + u8 *otp_data; + struct camera_sensor_platform_data *platform_data; + int fmt_idx; + int streaming; + int power; + u16 sensor_id; + u8 sensor_revision; + int exposure; + int gain; + u16 digital_gain; + struct bu64243_device bu64243; + struct mutex input_lock; /* serialize sensor's ioctl */ + + const struct ov8865_reg *basic_settings_list; + const struct ov8865_resolution *curr_res_table; + int entries_curr_table; + int fps_index; + + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *run_mode; +}; + +/* + * The i2c adapter on Intel Medfield can transfer 32 bytes maximum + * at a time. In burst mode we require that the buffer is transferred + * in one shot, so limit the buffer size to 32 bytes minus a safety. + */ +#define OV8865_MAX_WRITE_BUF_SIZE 30 +struct ov8865_write_buffer { + u16 addr; + u8 data[OV8865_MAX_WRITE_BUF_SIZE]; +}; + +struct ov8865_write_ctrl { + int index; + struct ov8865_write_buffer buffer; +}; + +#define OV8865_RES_WIDTH_MAX 3280 +#define OV8865_RES_HEIGHT_MAX 2464 + +/* please refer to 0x3800 0x3801 setting*/ +#define OV8865_CROP_X_START_FOR_MAX_SIZE 0x0C +/* please refer to 0x3802 0x3803 setting*/ +#define OV8865_CROP_Y_START_FOR_MAX_SIZE 0x0C + +#define ISP_PADDING_W 16 +#define ISP_PADDING_H 16 +#define OV8865_ISP_MAX_WIDTH (OV8865_RES_WIDTH_MAX - ISP_PADDING_W) +#define OV8865_ISP_MAX_HEIGHT (OV8865_RES_HEIGHT_MAX - ISP_PADDING_H) + +static const struct ov8865_reg ov8865_BasicSettings[] = { + {OV8865_8BIT, {0x0103}, 0x01}, + /* delay 10ms*/ + {OV8865_TOK_DELAY, {0}, 0x0A}, + + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x3638}, 0xff}, + {OV8865_8BIT, {0x0300}, 0x05}, + {OV8865_8BIT, {0x0302}, 0x96}, + {OV8865_8BIT, {0x0303}, 0x00}, + {OV8865_8BIT, {0x0304}, 0x03}, + {OV8865_8BIT, {0x030b}, 0x05}, + {OV8865_8BIT, {0x030e}, 0x00}, + {OV8865_8BIT, {0x030d}, 0x96}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x0312}, 0x01}, + {OV8865_8BIT, {0x031e}, 0x0c}, + {OV8865_8BIT, {0x3015}, 0x01}, + {OV8865_8BIT, {0x3018}, 0x72}, + {OV8865_8BIT, {0x3020}, 0x93}, + {OV8865_8BIT, {0x3022}, 0x01}, + {OV8865_8BIT, {0x3031}, 0x0a}, + {OV8865_8BIT, {0x3106}, 0x01}, + {OV8865_8BIT, {0x3305}, 0xf1}, + {OV8865_8BIT, {0x3308}, 0x00}, + {OV8865_8BIT, {0x3309}, 0x28}, + {OV8865_8BIT, {0x330a}, 0x00}, + {OV8865_8BIT, {0x330b}, 0x20}, + {OV8865_8BIT, {0x330c}, 0x00}, + {OV8865_8BIT, {0x330d}, 0x00}, + {OV8865_8BIT, {0x330e}, 0x00}, + {OV8865_8BIT, {0x330f}, 0x40}, + {OV8865_8BIT, {0x3307}, 0x04}, + {OV8865_8BIT, {0x3604}, 0x04}, + {OV8865_8BIT, {0x3602}, 0x30}, + {OV8865_8BIT, {0x3605}, 0x00}, + {OV8865_8BIT, {0x3607}, 0x20}, + {OV8865_8BIT, {0x3608}, 0x11}, + {OV8865_8BIT, {0x3609}, 0x68}, + {OV8865_8BIT, {0x360a}, 0x40}, + {OV8865_8BIT, {0x360c}, 0xdd}, + {OV8865_8BIT, {0x360e}, 0x0c}, + {OV8865_8BIT, {0x3610}, 0x07}, + {OV8865_8BIT, {0x3612}, 0x86}, + {OV8865_8BIT, {0x3613}, 0x58}, + {OV8865_8BIT, {0x3614}, 0x28}, + {OV8865_8BIT, {0x3617}, 0x40}, + {OV8865_8BIT, {0x3618}, 0x5a}, + {OV8865_8BIT, {0x3619}, 0x9b}, + {OV8865_8BIT, {0x361c}, 0x00}, + {OV8865_8BIT, {0x361d}, 0x60}, + {OV8865_8BIT, {0x3631}, 0x60}, + {OV8865_8BIT, {0x3633}, 0x10}, + {OV8865_8BIT, {0x3634}, 0x10}, + {OV8865_8BIT, {0x3635}, 0x10}, + {OV8865_8BIT, {0x3636}, 0x10}, + {OV8865_8BIT, {0x3641}, 0x55}, + {OV8865_8BIT, {0x3646}, 0x86}, + {OV8865_8BIT, {0x3647}, 0x27}, + {OV8865_8BIT, {0x364a}, 0x1b}, + {OV8865_8BIT, {0x3500}, 0x00}, + {OV8865_8BIT, {0x3503}, 0x00}, + {OV8865_8BIT, {0x3509}, 0x00}, + {OV8865_8BIT, {0x3705}, 0x00}, + {OV8865_8BIT, {0x3719}, 0x31}, + {OV8865_8BIT, {0x3714}, 0x12}, + {OV8865_8BIT, {0x3733}, 0x10}, + {OV8865_8BIT, {0x3734}, 0x40}, + {OV8865_8BIT, {0x3755}, 0x40}, + {OV8865_8BIT, {0x3758}, 0x00}, + {OV8865_8BIT, {0x3759}, 0x4c}, + {OV8865_8BIT, {0x375c}, 0x40}, + {OV8865_8BIT, {0x375e}, 0x00}, + {OV8865_8BIT, {0x3768}, 0x04}, + {OV8865_8BIT, {0x3769}, 0x20}, + {OV8865_8BIT, {0x376c}, 0xc0}, + {OV8865_8BIT, {0x376d}, 0xc0}, + {OV8865_8BIT, {0x376a}, 0x08}, + {OV8865_8BIT, {0x3761}, 0x00}, + {OV8865_8BIT, {0x3762}, 0x00}, + {OV8865_8BIT, {0x3763}, 0x00}, + {OV8865_8BIT, {0x3766}, 0xff}, + {OV8865_8BIT, {0x376b}, 0x42}, + {OV8865_8BIT, {0x37a4}, 0x00}, + {OV8865_8BIT, {0x37a6}, 0x00}, + {OV8865_8BIT, {0x3760}, 0x00}, + {OV8865_8BIT, {0x376f}, 0x01}, + {OV8865_8BIT, {0x37b0}, 0x00}, + {OV8865_8BIT, {0x37b1}, 0x00}, + {OV8865_8BIT, {0x37b2}, 0x00}, + {OV8865_8BIT, {0x37b6}, 0x00}, + {OV8865_8BIT, {0x37b7}, 0x00}, + {OV8865_8BIT, {0x37b8}, 0x00}, + {OV8865_8BIT, {0x37b9}, 0xff}, + {OV8865_8BIT, {0x3800}, 0x00}, /*please change OV8865_CROP_X_START_FOR_MAX_SIZE accordingly*/ + {OV8865_8BIT, {0x3801}, 0x0c}, + {OV8865_8BIT, {0x3802}, 0x00}, /*please change OV8865_CROP_Y_START_FOR_MAX_SIZE accordingly*/ + {OV8865_8BIT, {0x3803}, 0x0c}, + {OV8865_8BIT, {0x3804}, 0x0c}, + {OV8865_8BIT, {0x3805}, 0xd3}, + {OV8865_8BIT, {0x3806}, 0x09}, + {OV8865_8BIT, {0x3807}, 0xa3}, + {OV8865_8BIT, {0x3810}, 0x00}, + {OV8865_8BIT, {0x3811}, 0x04}, + {OV8865_8BIT, {0x3815}, 0x01}, + {OV8865_8BIT, {0x3820}, 0x06}, + {OV8865_8BIT, {0x382b}, 0x01}, + {OV8865_8BIT, {0x3837}, 0x18}, + {OV8865_8BIT, {0x3841}, 0xff}, + {OV8865_8BIT, {0x3d85}, 0x06}, + {OV8865_8BIT, {0x3d8c}, 0x75}, + {OV8865_8BIT, {0x3d8d}, 0xef}, + {OV8865_8BIT, {0x4000}, 0xf1}, + {OV8865_8BIT, {0x4005}, 0x10}, + {OV8865_8BIT, {0x400b}, 0x0c}, + {OV8865_8BIT, {0x400d}, 0x10}, + {OV8865_8BIT, {0x401b}, 0x00}, + {OV8865_8BIT, {0x401d}, 0x00}, + {OV8865_8BIT, {0x4028}, 0x00}, + {OV8865_8BIT, {0x4029}, 0x02}, + {OV8865_8BIT, {0x402a}, 0x04}, + {OV8865_8BIT, {0x402b}, 0x04}, + {OV8865_8BIT, {0x402c}, 0x02}, + {OV8865_8BIT, {0x402d}, 0x02}, + {OV8865_8BIT, {0x402e}, 0x08}, + {OV8865_8BIT, {0x402f}, 0x02}, + {OV8865_8BIT, {0x401f}, 0x00}, + {OV8865_8BIT, {0x4034}, 0x3f}, + {OV8865_8BIT, {0x4300}, 0xff}, + {OV8865_8BIT, {0x4301}, 0x00}, + {OV8865_8BIT, {0x4302}, 0x0f}, + {OV8865_8BIT, {0x4503}, 0x10}, + {OV8865_8BIT, {0x481f}, 0x32}, + {OV8865_8BIT, {0x4837}, 0x16}, + {OV8865_8BIT, {0x4850}, 0x10}, + {OV8865_8BIT, {0x4851}, 0x32}, + {OV8865_8BIT, {0x4b00}, 0x2a}, + {OV8865_8BIT, {0x4b0d}, 0x00}, + {OV8865_8BIT, {0x4d00}, 0x04}, + {OV8865_8BIT, {0x4d01}, 0x18}, + {OV8865_8BIT, {0x4d02}, 0xc3}, + {OV8865_8BIT, {0x4d03}, 0xff}, + {OV8865_8BIT, {0x4d04}, 0xff}, + {OV8865_8BIT, {0x4d05}, 0xff}, + {OV8865_8BIT, {0x5000}, 0x96}, + {OV8865_8BIT, {0x5001}, 0x01}, + {OV8865_8BIT, {0x5002}, 0x08}, + {OV8865_8BIT, {0x5901}, 0x00}, + {OV8865_8BIT, {0x5e00}, 0x00}, + {OV8865_8BIT, {0x5e01}, 0x41}, + {OV8865_8BIT, {0x5b00}, 0x02}, + {OV8865_8BIT, {0x5b01}, 0xd0}, + {OV8865_8BIT, {0x5b02}, 0x03}, + {OV8865_8BIT, {0x5b03}, 0xff}, + {OV8865_8BIT, {0x5b05}, 0x6c}, + {OV8865_8BIT, {0x5780}, 0xfc}, + {OV8865_8BIT, {0x5781}, 0xdf}, + {OV8865_8BIT, {0x5782}, 0x3f}, + {OV8865_8BIT, {0x5783}, 0x08}, + {OV8865_8BIT, {0x5784}, 0x0c}, + {OV8865_8BIT, {0x5786}, 0x20}, + {OV8865_8BIT, {0x5787}, 0x40}, + {OV8865_8BIT, {0x5788}, 0x08}, + {OV8865_8BIT, {0x5789}, 0x08}, + {OV8865_8BIT, {0x578a}, 0x02}, + {OV8865_8BIT, {0x578b}, 0x01}, + {OV8865_8BIT, {0x578c}, 0x01}, + {OV8865_8BIT, {0x578d}, 0x0c}, + {OV8865_8BIT, {0x578e}, 0x02}, + {OV8865_8BIT, {0x578f}, 0x01}, + {OV8865_8BIT, {0x5790}, 0x01}, + {OV8865_8BIT, {0x5800}, 0x1d}, + {OV8865_8BIT, {0x5801}, 0x0e}, + {OV8865_8BIT, {0x5802}, 0x0c}, + {OV8865_8BIT, {0x5803}, 0x0c}, + {OV8865_8BIT, {0x5804}, 0x0f}, + {OV8865_8BIT, {0x5805}, 0x22}, + {OV8865_8BIT, {0x5806}, 0x0a}, + {OV8865_8BIT, {0x5807}, 0x06}, + {OV8865_8BIT, {0x5808}, 0x05}, + {OV8865_8BIT, {0x5809}, 0x05}, + {OV8865_8BIT, {0x580a}, 0x07}, + {OV8865_8BIT, {0x580b}, 0x0a}, + {OV8865_8BIT, {0x580c}, 0x06}, + {OV8865_8BIT, {0x580d}, 0x02}, + {OV8865_8BIT, {0x580e}, 0x00}, + {OV8865_8BIT, {0x580f}, 0x00}, + {OV8865_8BIT, {0x5810}, 0x03}, + {OV8865_8BIT, {0x5811}, 0x07}, + {OV8865_8BIT, {0x5812}, 0x06}, + {OV8865_8BIT, {0x5813}, 0x02}, + {OV8865_8BIT, {0x5814}, 0x00}, + {OV8865_8BIT, {0x5815}, 0x00}, + {OV8865_8BIT, {0x5816}, 0x03}, + {OV8865_8BIT, {0x5817}, 0x07}, + {OV8865_8BIT, {0x5818}, 0x09}, + {OV8865_8BIT, {0x5819}, 0x06}, + {OV8865_8BIT, {0x581a}, 0x04}, + {OV8865_8BIT, {0x581b}, 0x04}, + {OV8865_8BIT, {0x581c}, 0x06}, + {OV8865_8BIT, {0x581d}, 0x0a}, + {OV8865_8BIT, {0x581e}, 0x19}, + {OV8865_8BIT, {0x581f}, 0x0d}, + {OV8865_8BIT, {0x5820}, 0x0b}, + {OV8865_8BIT, {0x5821}, 0x0b}, + {OV8865_8BIT, {0x5822}, 0x0e}, + {OV8865_8BIT, {0x5823}, 0x22}, + {OV8865_8BIT, {0x5824}, 0x23}, + {OV8865_8BIT, {0x5825}, 0x28}, + {OV8865_8BIT, {0x5826}, 0x29}, + {OV8865_8BIT, {0x5827}, 0x27}, + {OV8865_8BIT, {0x5828}, 0x13}, + {OV8865_8BIT, {0x5829}, 0x26}, + {OV8865_8BIT, {0x582a}, 0x33}, + {OV8865_8BIT, {0x582b}, 0x32}, + {OV8865_8BIT, {0x582c}, 0x33}, + {OV8865_8BIT, {0x582d}, 0x16}, + {OV8865_8BIT, {0x582e}, 0x14}, + {OV8865_8BIT, {0x582f}, 0x30}, + {OV8865_8BIT, {0x5830}, 0x31}, + {OV8865_8BIT, {0x5831}, 0x30}, + {OV8865_8BIT, {0x5832}, 0x15}, + {OV8865_8BIT, {0x5833}, 0x26}, + {OV8865_8BIT, {0x5834}, 0x23}, + {OV8865_8BIT, {0x5835}, 0x21}, + {OV8865_8BIT, {0x5836}, 0x23}, + {OV8865_8BIT, {0x5837}, 0x05}, + {OV8865_8BIT, {0x5838}, 0x36}, + {OV8865_8BIT, {0x5839}, 0x27}, + {OV8865_8BIT, {0x583a}, 0x28}, + {OV8865_8BIT, {0x583b}, 0x26}, + {OV8865_8BIT, {0x583c}, 0x24}, + {OV8865_8BIT, {0x583d}, 0xdf}, + + /* otp key setting */ + {OV8865_8BIT, {0x3820}, 0x06}, /* Mirror off, flip on */ + {OV8865_8BIT, {0x3821}, 0x40}, /* Align with Intel/Lenovo requirement */ + {OV8865_8BIT, {0x5000}, 0x16}, + {OV8865_8BIT, {0x5018}, 0x10}, + {OV8865_8BIT, {0x5019}, 0x00}, + {OV8865_8BIT, {0x501a}, 0x10}, + {OV8865_8BIT, {0x501b}, 0x00}, + {OV8865_8BIT, {0x501c}, 0x10}, + {OV8865_8BIT, {0x501d}, 0x00}, + {OV8865_8BIT, {0x501e}, 0x00}, + + {OV8865_8BIT, {0x4000}, 0xf3}, + {OV8865_8BIT, {0x3503}, 0x00}, + {OV8865_8BIT, {0x3501}, 0x07}, + {OV8865_8BIT, {0x3502}, 0xff}, + + {OV8865_8BIT, {0x3508}, 0x00}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +/*****************************STILL********************************/ + +static const struct ov8865_reg ov8865_896x736_30fps[] = { +/* 896x736_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x09}, + {OV8865_8BIT, {0x3501}, 0x31}, + {OV8865_8BIT, {0x3502}, 0x00}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x24}, + {OV8865_8BIT, {0x3701}, 0x0c}, + {OV8865_8BIT, {0x3702}, 0x28}, + {OV8865_8BIT, {0x3703}, 0x19}, + {OV8865_8BIT, {0x3704}, 0x14}, + {OV8865_8BIT, {0x3706}, 0x38}, + {OV8865_8BIT, {0x3707}, 0x04}, + {OV8865_8BIT, {0x3708}, 0x24}, + {OV8865_8BIT, {0x3709}, 0x40}, + {OV8865_8BIT, {0x370a}, 0x00}, + {OV8865_8BIT, {0x370b}, 0xb8}, + {OV8865_8BIT, {0x370c}, 0x04}, + {OV8865_8BIT, {0x3718}, 0x12}, + {OV8865_8BIT, {0x3712}, 0x42}, + {OV8865_8BIT, {0x371e}, 0x19}, + {OV8865_8BIT, {0x371f}, 0x40}, + {OV8865_8BIT, {0x3720}, 0x05}, + {OV8865_8BIT, {0x3721}, 0x05}, + {OV8865_8BIT, {0x3724}, 0x02}, + {OV8865_8BIT, {0x3725}, 0x02}, + {OV8865_8BIT, {0x3726}, 0x06}, + {OV8865_8BIT, {0x3728}, 0x05}, + {OV8865_8BIT, {0x3729}, 0x02}, + {OV8865_8BIT, {0x372a}, 0x03}, + {OV8865_8BIT, {0x372b}, 0x53}, + {OV8865_8BIT, {0x372c}, 0xa3}, + {OV8865_8BIT, {0x372d}, 0x53}, + {OV8865_8BIT, {0x372e}, 0x06}, + {OV8865_8BIT, {0x372f}, 0x10}, + {OV8865_8BIT, {0x3730}, 0x01}, + {OV8865_8BIT, {0x3731}, 0x06}, + {OV8865_8BIT, {0x3732}, 0x14}, + {OV8865_8BIT, {0x3736}, 0x20}, + {OV8865_8BIT, {0x373a}, 0x02}, + {OV8865_8BIT, {0x373b}, 0x0c}, + {OV8865_8BIT, {0x373c}, 0x0a}, + {OV8865_8BIT, {0x373e}, 0x03}, + {OV8865_8BIT, {0x375a}, 0x06}, + {OV8865_8BIT, {0x375b}, 0x13}, + {OV8865_8BIT, {0x375d}, 0x02}, + {OV8865_8BIT, {0x375f}, 0x14}, + {OV8865_8BIT, {0x3767}, 0x1c}, + {OV8865_8BIT, {0x3772}, 0x23}, + {OV8865_8BIT, {0x3773}, 0x02}, + {OV8865_8BIT, {0x3774}, 0x16}, + {OV8865_8BIT, {0x3775}, 0x12}, + {OV8865_8BIT, {0x3776}, 0x08}, + {OV8865_8BIT, {0x37a0}, 0x44}, + {OV8865_8BIT, {0x37a1}, 0x3d}, + {OV8865_8BIT, {0x37a2}, 0x3d}, + {OV8865_8BIT, {0x37a3}, 0x01}, + {OV8865_8BIT, {0x37a5}, 0x08}, + {OV8865_8BIT, {0x37a7}, 0x44}, + {OV8865_8BIT, {0x37a8}, 0x58}, + {OV8865_8BIT, {0x37a9}, 0x58}, + {OV8865_8BIT, {0x37aa}, 0x44}, + {OV8865_8BIT, {0x37ab}, 0x2e}, + {OV8865_8BIT, {0x37ac}, 0x2e}, + {OV8865_8BIT, {0x37ad}, 0x33}, + {OV8865_8BIT, {0x37ae}, 0x0d}, + {OV8865_8BIT, {0x37af}, 0x0d}, + {OV8865_8BIT, {0x37b3}, 0x42}, + {OV8865_8BIT, {0x37b4}, 0x42}, + {OV8865_8BIT, {0x37b5}, 0x33}, + {OV8865_8BIT, {0x3808}, 0x03}, + {OV8865_8BIT, {0x3809}, 0x80}, + {OV8865_8BIT, {0x380a}, 0x02}, + {OV8865_8BIT, {0x380b}, 0xe0}, + {OV8865_8BIT, {0x380c}, 0x06}, + {OV8865_8BIT, {0x380d}, 0xe6}, + {OV8865_8BIT, {0x380e}, 0x05}, + {OV8865_8BIT, {0x380f}, 0x50}, + {OV8865_8BIT, {0x3813}, 0x04}, + {OV8865_8BIT, {0x3814}, 0x03}, + {OV8865_8BIT, {0x3821}, 0x61}, + {OV8865_8BIT, {0x382a}, 0x03}, + {OV8865_8BIT, {0x3830}, 0x08}, + {OV8865_8BIT, {0x3836}, 0x02}, + {OV8865_8BIT, {0x3846}, 0x88}, + {OV8865_8BIT, {0x3f08}, 0x0b}, + {OV8865_8BIT, {0x4001}, 0x14}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x01}, + {OV8865_8BIT, {0x4023}, 0x56}, + {OV8865_8BIT, {0x4024}, 0x03}, + {OV8865_8BIT, {0x4025}, 0x54}, + {OV8865_8BIT, {0x4026}, 0x03}, + {OV8865_8BIT, {0x4027}, 0x84}, + {OV8865_8BIT, {0x4500}, 0x40}, + {OV8865_8BIT, {0x4601}, 0x38}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_1216x736_30fps[] = { + /* 1216x736_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x09}, + {OV8865_8BIT, {0x3501}, 0x31}, + {OV8865_8BIT, {0x3502}, 0x00}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x24}, + {OV8865_8BIT, {0x3701}, 0x0c}, + {OV8865_8BIT, {0x3702}, 0x28}, + {OV8865_8BIT, {0x3703}, 0x19}, + {OV8865_8BIT, {0x3704}, 0x14}, + {OV8865_8BIT, {0x3706}, 0x38}, + {OV8865_8BIT, {0x3707}, 0x04}, + {OV8865_8BIT, {0x3708}, 0x24}, + {OV8865_8BIT, {0x3709}, 0x40}, + {OV8865_8BIT, {0x370a}, 0x00}, + {OV8865_8BIT, {0x370b}, 0xb8}, + {OV8865_8BIT, {0x370c}, 0x04}, + {OV8865_8BIT, {0x3718}, 0x12}, + {OV8865_8BIT, {0x3712}, 0x42}, + {OV8865_8BIT, {0x371e}, 0x19}, + {OV8865_8BIT, {0x371f}, 0x40}, + {OV8865_8BIT, {0x3720}, 0x05}, + {OV8865_8BIT, {0x3721}, 0x05}, + {OV8865_8BIT, {0x3724}, 0x02}, + {OV8865_8BIT, {0x3725}, 0x02}, + {OV8865_8BIT, {0x3726}, 0x06}, + {OV8865_8BIT, {0x3728}, 0x05}, + {OV8865_8BIT, {0x3729}, 0x02}, + {OV8865_8BIT, {0x372a}, 0x03}, + {OV8865_8BIT, {0x372b}, 0x53}, + {OV8865_8BIT, {0x372c}, 0xa3}, + {OV8865_8BIT, {0x372d}, 0x53}, + {OV8865_8BIT, {0x372e}, 0x06}, + {OV8865_8BIT, {0x372f}, 0x10}, + {OV8865_8BIT, {0x3730}, 0x01}, + {OV8865_8BIT, {0x3731}, 0x06}, + {OV8865_8BIT, {0x3732}, 0x14}, + {OV8865_8BIT, {0x3736}, 0x20}, + {OV8865_8BIT, {0x373a}, 0x02}, + {OV8865_8BIT, {0x373b}, 0x0c}, + {OV8865_8BIT, {0x373c}, 0x0a}, + {OV8865_8BIT, {0x373e}, 0x03}, + {OV8865_8BIT, {0x375a}, 0x06}, + {OV8865_8BIT, {0x375b}, 0x13}, + {OV8865_8BIT, {0x375d}, 0x02}, + {OV8865_8BIT, {0x375f}, 0x14}, + {OV8865_8BIT, {0x3767}, 0x1c}, + {OV8865_8BIT, {0x3772}, 0x23}, + {OV8865_8BIT, {0x3773}, 0x02}, + {OV8865_8BIT, {0x3774}, 0x16}, + {OV8865_8BIT, {0x3775}, 0x12}, + {OV8865_8BIT, {0x3776}, 0x08}, + {OV8865_8BIT, {0x37a0}, 0x44}, + {OV8865_8BIT, {0x37a1}, 0x3d}, + {OV8865_8BIT, {0x37a2}, 0x3d}, + {OV8865_8BIT, {0x37a3}, 0x01}, + {OV8865_8BIT, {0x37a5}, 0x08}, + {OV8865_8BIT, {0x37a7}, 0x44}, + {OV8865_8BIT, {0x37a8}, 0x58}, + {OV8865_8BIT, {0x37a9}, 0x58}, + {OV8865_8BIT, {0x37aa}, 0x44}, + {OV8865_8BIT, {0x37ab}, 0x2e}, + {OV8865_8BIT, {0x37ac}, 0x2e}, + {OV8865_8BIT, {0x37ad}, 0x33}, + {OV8865_8BIT, {0x37ae}, 0x0d}, + {OV8865_8BIT, {0x37af}, 0x0d}, + {OV8865_8BIT, {0x37b3}, 0x42}, + {OV8865_8BIT, {0x37b4}, 0x42}, + {OV8865_8BIT, {0x37b5}, 0x33}, + {OV8865_8BIT, {0x3808}, 0x04}, + {OV8865_8BIT, {0x3809}, 0xc0}, + {OV8865_8BIT, {0x380a}, 0x02}, + {OV8865_8BIT, {0x380b}, 0xe0}, + {OV8865_8BIT, {0x380c}, 0x07}, + {OV8865_8BIT, {0x380d}, 0x1a}, + {OV8865_8BIT, {0x380e}, 0x05}, + {OV8865_8BIT, {0x380f}, 0x28}, + {OV8865_8BIT, {0x3813}, 0x04}, + {OV8865_8BIT, {0x3814}, 0x03}, + {OV8865_8BIT, {0x3821}, 0x61}, + {OV8865_8BIT, {0x382a}, 0x03}, + {OV8865_8BIT, {0x3830}, 0x08}, + {OV8865_8BIT, {0x3836}, 0x02}, + {OV8865_8BIT, {0x3846}, 0x88}, + {OV8865_8BIT, {0x3f08}, 0x0b}, + {OV8865_8BIT, {0x4001}, 0x14}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x02}, + {OV8865_8BIT, {0x4023}, 0x96}, + {OV8865_8BIT, {0x4024}, 0x04}, + {OV8865_8BIT, {0x4025}, 0x94}, + {OV8865_8BIT, {0x4026}, 0x04}, + {OV8865_8BIT, {0x4027}, 0xc4}, + {OV8865_8BIT, {0x4500}, 0x40}, + {OV8865_8BIT, {0x4601}, 0x74}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_1632x1224_30fps[] = { + /* 1632x1224_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x09}, + {OV8865_8BIT, {0x3501}, 0x5c}, + {OV8865_8BIT, {0x3502}, 0x00}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x24}, + {OV8865_8BIT, {0x3701}, 0x0c}, + {OV8865_8BIT, {0x3702}, 0x28}, + {OV8865_8BIT, {0x3703}, 0x19}, + {OV8865_8BIT, {0x3704}, 0x14}, + {OV8865_8BIT, {0x3706}, 0x38}, + {OV8865_8BIT, {0x3707}, 0x04}, + {OV8865_8BIT, {0x3708}, 0x24}, + {OV8865_8BIT, {0x3709}, 0x40}, + {OV8865_8BIT, {0x370a}, 0x00}, + {OV8865_8BIT, {0x370b}, 0xb8}, + {OV8865_8BIT, {0x370c}, 0x04}, + {OV8865_8BIT, {0x3718}, 0x12}, + {OV8865_8BIT, {0x3712}, 0x42}, + {OV8865_8BIT, {0x371e}, 0x19}, + {OV8865_8BIT, {0x371f}, 0x40}, + {OV8865_8BIT, {0x3720}, 0x05}, + {OV8865_8BIT, {0x3721}, 0x05}, + {OV8865_8BIT, {0x3724}, 0x02}, + {OV8865_8BIT, {0x3725}, 0x02}, + {OV8865_8BIT, {0x3726}, 0x06}, + {OV8865_8BIT, {0x3728}, 0x05}, + {OV8865_8BIT, {0x3729}, 0x02}, + {OV8865_8BIT, {0x372a}, 0x03}, + {OV8865_8BIT, {0x372b}, 0x53}, + {OV8865_8BIT, {0x372c}, 0xa3}, + {OV8865_8BIT, {0x372d}, 0x53}, + {OV8865_8BIT, {0x372e}, 0x06}, + {OV8865_8BIT, {0x372f}, 0x10}, + {OV8865_8BIT, {0x3730}, 0x01}, + {OV8865_8BIT, {0x3731}, 0x06}, + {OV8865_8BIT, {0x3732}, 0x14}, + {OV8865_8BIT, {0x3736}, 0x20}, + {OV8865_8BIT, {0x373a}, 0x02}, + {OV8865_8BIT, {0x373b}, 0x0c}, + {OV8865_8BIT, {0x373c}, 0x0a}, + {OV8865_8BIT, {0x373e}, 0x03}, + {OV8865_8BIT, {0x375a}, 0x06}, + {OV8865_8BIT, {0x375b}, 0x13}, + {OV8865_8BIT, {0x375d}, 0x02}, + {OV8865_8BIT, {0x375f}, 0x14}, + {OV8865_8BIT, {0x3767}, 0x1c}, + {OV8865_8BIT, {0x3772}, 0x23}, + {OV8865_8BIT, {0x3773}, 0x02}, + {OV8865_8BIT, {0x3774}, 0x16}, + {OV8865_8BIT, {0x3775}, 0x12}, + {OV8865_8BIT, {0x3776}, 0x08}, + {OV8865_8BIT, {0x37a0}, 0x44}, + {OV8865_8BIT, {0x37a1}, 0x3d}, + {OV8865_8BIT, {0x37a2}, 0x3d}, + {OV8865_8BIT, {0x37a3}, 0x01}, + {OV8865_8BIT, {0x37a5}, 0x08}, + {OV8865_8BIT, {0x37a7}, 0x44}, + {OV8865_8BIT, {0x37a8}, 0x58}, + {OV8865_8BIT, {0x37a9}, 0x58}, + {OV8865_8BIT, {0x37aa}, 0x44}, + {OV8865_8BIT, {0x37ab}, 0x2e}, + {OV8865_8BIT, {0x37ac}, 0x2e}, + {OV8865_8BIT, {0x37ad}, 0x33}, + {OV8865_8BIT, {0x37ae}, 0x0d}, + {OV8865_8BIT, {0x37af}, 0x0d}, + {OV8865_8BIT, {0x37b3}, 0x42}, + {OV8865_8BIT, {0x37b4}, 0x42}, + {OV8865_8BIT, {0x37b5}, 0x33}, + {OV8865_8BIT, {0x3808}, 0x06}, + {OV8865_8BIT, {0x3809}, 0x60}, + {OV8865_8BIT, {0x380a}, 0x04}, + {OV8865_8BIT, {0x380b}, 0xc8}, + {OV8865_8BIT, {0x380c}, 0x06}, + {OV8865_8BIT, {0x380d}, 0x42}, + {OV8865_8BIT, {0x380e}, 0x05}, + {OV8865_8BIT, {0x380f}, 0xda}, + {OV8865_8BIT, {0x3813}, 0x04}, + {OV8865_8BIT, {0x3814}, 0x03}, + {OV8865_8BIT, {0x3821}, 0x61}, + {OV8865_8BIT, {0x382a}, 0x03}, + {OV8865_8BIT, {0x3830}, 0x08}, + {OV8865_8BIT, {0x3836}, 0x02}, + {OV8865_8BIT, {0x3846}, 0x88}, + {OV8865_8BIT, {0x3f08}, 0x0b}, + {OV8865_8BIT, {0x4001}, 0x14}, + {OV8865_8BIT, {0x4020}, 0x01}, + {OV8865_8BIT, {0x4021}, 0x20}, + {OV8865_8BIT, {0x4022}, 0x01}, + {OV8865_8BIT, {0x4023}, 0x9f}, + {OV8865_8BIT, {0x4024}, 0x03}, + {OV8865_8BIT, {0x4025}, 0xe0}, + {OV8865_8BIT, {0x4026}, 0x04}, + {OV8865_8BIT, {0x4027}, 0x5f}, + {OV8865_8BIT, {0x4500}, 0x40}, + {OV8865_8BIT, {0x4601}, 0x74}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_1936x1096_21fps[] = { + /* 1936x1096_21fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x44}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x07}, + {OV8865_8BIT, {0x3809}, 0x90}, + {OV8865_8BIT, {0x380a}, 0x04}, + {OV8865_8BIT, {0x380b}, 0x48}, + {OV8865_8BIT, {0x380c}, 0x0f}, + {OV8865_8BIT, {0x380d}, 0x98}, + {OV8865_8BIT, {0x380e}, 0x06}, //04 + {OV8865_8BIT, {0x380f}, 0xb5}, //b2 + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x05}, + {OV8865_8BIT, {0x4023}, 0x65}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0x63}, + {OV8865_8BIT, {0x4026}, 0x07}, + {OV8865_8BIT, {0x4027}, 0x93}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_1936x1096_30fps[] = { + /* 1936x1096_30fps */ + + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x44}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x07}, + {OV8865_8BIT, {0x3809}, 0x90}, + {OV8865_8BIT, {0x380a}, 0x04}, + {OV8865_8BIT, {0x380b}, 0x48}, + {OV8865_8BIT, {0x380c}, 0x0f}, + {OV8865_8BIT, {0x380d}, 0x98}, + {OV8865_8BIT, {0x380e}, 0x04}, + {OV8865_8BIT, {0x380f}, 0xb2}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x05}, + {OV8865_8BIT, {0x4023}, 0x65}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0x63}, + {OV8865_8BIT, {0x4026}, 0x07}, + {OV8865_8BIT, {0x4027}, 0x93}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_2064x1552_21fps[] = { + /* 2064x1552_21fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x08}, + {OV8865_8BIT, {0x3809}, 0x10}, + {OV8865_8BIT, {0x380a}, 0x06}, + {OV8865_8BIT, {0x380b}, 0x10}, + {OV8865_8BIT, {0x380c}, 0x0b}, + {OV8865_8BIT, {0x380d}, 0xf0}, + {OV8865_8BIT, {0x380e}, 0x08}, //;06 + {OV8865_8BIT, {0x380f}, 0xc2}, //;22 + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x05}, + {OV8865_8BIT, {0x4023}, 0xe6}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xe4}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0x14}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + + +static const struct ov8865_reg ov8865_2064x1552_30fps[] = { + /* 2064x1552_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x08}, + {OV8865_8BIT, {0x3809}, 0x10}, + {OV8865_8BIT, {0x380a}, 0x06}, + {OV8865_8BIT, {0x380b}, 0x10}, + {OV8865_8BIT, {0x380c}, 0x0b}, + {OV8865_8BIT, {0x380d}, 0xf0}, + {OV8865_8BIT, {0x380e}, 0x06}, + {OV8865_8BIT, {0x380f}, 0x22}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x05}, + {OV8865_8BIT, {0x4023}, 0xe6}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xe4}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0x14}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_2576x1936_10fps[] = { + /* 2576x1936_10fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x01}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0a}, + {OV8865_8BIT, {0x3809}, 0x10}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x90}, + {OV8865_8BIT, {0x380c}, 0x10}, + {OV8865_8BIT, {0x380d}, 0x3a}, + {OV8865_8BIT, {0x380e}, 0x0d}, + {OV8865_8BIT, {0x380f}, 0x88}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x07}, + {OV8865_8BIT, {0x4023}, 0xe6}, + {OV8865_8BIT, {0x4024}, 0x09}, + {OV8865_8BIT, {0x4025}, 0xe4}, + {OV8865_8BIT, {0x4026}, 0x0a}, + {OV8865_8BIT, {0x4027}, 0x14}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_2576x1936_21fps[] = { + /* 2576x1936_21fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0a}, + {OV8865_8BIT, {0x3809}, 0x10}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x90}, + {OV8865_8BIT, {0x380c}, 0x08}, + {OV8865_8BIT, {0x380d}, 0xa2}, + {OV8865_8BIT, {0x380e}, 0x0c}, //;08 + {OV8865_8BIT, {0x380f}, 0x1e}, //;7c + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x07}, + {OV8865_8BIT, {0x4023}, 0xe6}, + {OV8865_8BIT, {0x4024}, 0x09}, + {OV8865_8BIT, {0x4025}, 0xe4}, + {OV8865_8BIT, {0x4026}, 0x0a}, + {OV8865_8BIT, {0x4027}, 0x14}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; +/*****************************OV8865 PREVIEW********************************/ + +static struct ov8865_reg const ov8865_2576x1936_30fps[] = { + /* 2576x1936_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0a}, + {OV8865_8BIT, {0x3809}, 0x10}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x90}, + {OV8865_8BIT, {0x380c}, 0x08}, + {OV8865_8BIT, {0x380d}, 0xa2}, + {OV8865_8BIT, {0x380e}, 0x08}, + {OV8865_8BIT, {0x380f}, 0x7c}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x00}, + {OV8865_8BIT, {0x4021}, 0x00}, + {OV8865_8BIT, {0x4022}, 0x07}, + {OV8865_8BIT, {0x4023}, 0xe6}, + {OV8865_8BIT, {0x4024}, 0x09}, + {OV8865_8BIT, {0x4025}, 0xe4}, + {OV8865_8BIT, {0x4026}, 0x0a}, + {OV8865_8BIT, {0x4027}, 0x14}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static struct ov8865_reg const ov8865_3280x1852_10fps[] = { + /* 3280x1852_10fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x72}, + {OV8865_8BIT, {0x3502}, 0x20}, + {OV8865_8BIT, {0x3508}, 0x01}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x3c}, + {OV8865_8BIT, {0x380c}, 0x12}, + {OV8865_8BIT, {0x380d}, 0x54}, + {OV8865_8BIT, {0x380e}, 0x0b}, + {OV8865_8BIT, {0x380f}, 0xfc}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static struct ov8865_reg const ov8865_3280x1852_21fps[] = { + /* 3280x1852_21fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x72}, + {OV8865_8BIT, {0x3502}, 0x20}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x3c}, + {OV8865_8BIT, {0x380c}, 0x0b},//;0a + {OV8865_8BIT, {0x380d}, 0x3e},//;00 + {OV8865_8BIT, {0x380e}, 0x09},//;07 + {OV8865_8BIT, {0x380f}, 0x4e},//;52 + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + + +static const struct ov8865_reg ov8865_3280x1852_30fps[] = { + /* 3280x1852_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x72}, + {OV8865_8BIT, {0x3502}, 0x20}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x07}, + {OV8865_8BIT, {0x380b}, 0x3c}, + {OV8865_8BIT, {0x380c}, 0x09}, + {OV8865_8BIT, {0x380d}, 0x20}, + {OV8865_8BIT, {0x380e}, 0x08}, + {OV8865_8BIT, {0x380f}, 0x00}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_3280x2464_21fps[] = { + /* 3280x2464_21fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x09}, + {OV8865_8BIT, {0x380b}, 0xa0}, + {OV8865_8BIT, {0x380c}, 0x08},//;07 + {OV8865_8BIT, {0x380d}, 0xd2},//;90 + {OV8865_8BIT, {0x380e}, 0x0b},//;09 + {OV8865_8BIT, {0x380f}, 0xda},//;b2 + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_3280x2464_10fps[] = { + /* 3280x2464_10fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x09}, + {OV8865_8BIT, {0x380b}, 0xa0}, + {OV8865_8BIT, {0x380c}, 0x12},//;07 + {OV8865_8BIT, {0x380d}, 0x54},//;90 + {OV8865_8BIT, {0x380e}, 0x0b},//;09 + {OV8865_8BIT, {0x380f}, 0xda},//;b2 + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static const struct ov8865_reg ov8865_3280x2464_30fps[] = { + /* 3280x2464_30fps */ + {OV8865_8BIT, {0x0100}, 0x00}, + {OV8865_8BIT, {0x030f}, 0x04}, + {OV8865_8BIT, {0x3501}, 0x98}, + {OV8865_8BIT, {0x3502}, 0x60}, + {OV8865_8BIT, {0x3508}, 0x02}, + {OV8865_8BIT, {0x3700}, 0x48}, + {OV8865_8BIT, {0x3701}, 0x18}, + {OV8865_8BIT, {0x3702}, 0x50}, + {OV8865_8BIT, {0x3703}, 0x32}, + {OV8865_8BIT, {0x3704}, 0x28}, + {OV8865_8BIT, {0x3706}, 0x70}, + {OV8865_8BIT, {0x3707}, 0x08}, + {OV8865_8BIT, {0x3708}, 0x48}, + {OV8865_8BIT, {0x3709}, 0x80}, + {OV8865_8BIT, {0x370a}, 0x01}, + {OV8865_8BIT, {0x370b}, 0x70}, + {OV8865_8BIT, {0x370c}, 0x07}, + {OV8865_8BIT, {0x3718}, 0x14}, + {OV8865_8BIT, {0x3712}, 0x44}, + {OV8865_8BIT, {0x371e}, 0x31}, + {OV8865_8BIT, {0x371f}, 0x7f}, + {OV8865_8BIT, {0x3720}, 0x0a}, + {OV8865_8BIT, {0x3721}, 0x0a}, + {OV8865_8BIT, {0x3724}, 0x04}, + {OV8865_8BIT, {0x3725}, 0x04}, + {OV8865_8BIT, {0x3726}, 0x0c}, + {OV8865_8BIT, {0x3728}, 0x0a}, + {OV8865_8BIT, {0x3729}, 0x03}, + {OV8865_8BIT, {0x372a}, 0x06}, + {OV8865_8BIT, {0x372b}, 0xa6}, + {OV8865_8BIT, {0x372c}, 0xa6}, + {OV8865_8BIT, {0x372d}, 0xa6}, + {OV8865_8BIT, {0x372e}, 0x0c}, + {OV8865_8BIT, {0x372f}, 0x20}, + {OV8865_8BIT, {0x3730}, 0x02}, + {OV8865_8BIT, {0x3731}, 0x0c}, + {OV8865_8BIT, {0x3732}, 0x28}, + {OV8865_8BIT, {0x3736}, 0x30}, + {OV8865_8BIT, {0x373a}, 0x04}, + {OV8865_8BIT, {0x373b}, 0x18}, + {OV8865_8BIT, {0x373c}, 0x14}, + {OV8865_8BIT, {0x373e}, 0x06}, + {OV8865_8BIT, {0x375a}, 0x0c}, + {OV8865_8BIT, {0x375b}, 0x26}, + {OV8865_8BIT, {0x375d}, 0x04}, + {OV8865_8BIT, {0x375f}, 0x28}, + {OV8865_8BIT, {0x3767}, 0x1e}, + {OV8865_8BIT, {0x3772}, 0x46}, + {OV8865_8BIT, {0x3773}, 0x04}, + {OV8865_8BIT, {0x3774}, 0x2c}, + {OV8865_8BIT, {0x3775}, 0x13}, + {OV8865_8BIT, {0x3776}, 0x10}, + {OV8865_8BIT, {0x37a0}, 0x88}, + {OV8865_8BIT, {0x37a1}, 0x7a}, + {OV8865_8BIT, {0x37a2}, 0x7a}, + {OV8865_8BIT, {0x37a3}, 0x02}, + {OV8865_8BIT, {0x37a5}, 0x09}, + {OV8865_8BIT, {0x37a7}, 0x88}, + {OV8865_8BIT, {0x37a8}, 0xb0}, + {OV8865_8BIT, {0x37a9}, 0xb0}, + {OV8865_8BIT, {0x37aa}, 0x88}, + {OV8865_8BIT, {0x37ab}, 0x5c}, + {OV8865_8BIT, {0x37ac}, 0x5c}, + {OV8865_8BIT, {0x37ad}, 0x55}, + {OV8865_8BIT, {0x37ae}, 0x19}, + {OV8865_8BIT, {0x37af}, 0x19}, + {OV8865_8BIT, {0x37b3}, 0x84}, + {OV8865_8BIT, {0x37b4}, 0x84}, + {OV8865_8BIT, {0x37b5}, 0x66}, + {OV8865_8BIT, {0x3808}, 0x0c}, + {OV8865_8BIT, {0x3809}, 0xd0}, + {OV8865_8BIT, {0x380a}, 0x09}, + {OV8865_8BIT, {0x380b}, 0xa0}, + {OV8865_8BIT, {0x380c}, 0x07}, + {OV8865_8BIT, {0x380d}, 0x90}, + {OV8865_8BIT, {0x380e}, 0x09}, + {OV8865_8BIT, {0x380f}, 0xb6}, + {OV8865_8BIT, {0x3813}, 0x02}, + {OV8865_8BIT, {0x3814}, 0x01}, + {OV8865_8BIT, {0x3821}, 0x40}, + {OV8865_8BIT, {0x382a}, 0x01}, + {OV8865_8BIT, {0x3830}, 0x04}, + {OV8865_8BIT, {0x3836}, 0x01}, + {OV8865_8BIT, {0x3846}, 0x48}, + {OV8865_8BIT, {0x3f08}, 0x16}, + {OV8865_8BIT, {0x4001}, 0x04}, + {OV8865_8BIT, {0x4020}, 0x02}, + {OV8865_8BIT, {0x4021}, 0x40}, + {OV8865_8BIT, {0x4022}, 0x03}, + {OV8865_8BIT, {0x4023}, 0x3f}, + {OV8865_8BIT, {0x4024}, 0x07}, + {OV8865_8BIT, {0x4025}, 0xc0}, + {OV8865_8BIT, {0x4026}, 0x08}, + {OV8865_8BIT, {0x4027}, 0xbf}, + {OV8865_8BIT, {0x4500}, 0x68}, + {OV8865_8BIT, {0x4601}, 0x10}, + + { OV8865_TOK_TERM, {0}, 0} +}; + +static struct ov8865_resolution ov8865_res_preview[] = { + { + .desc = "ov8865_896x736_30fps", + .width = 896, + .height = 736, + .used = 0, + .regs = ov8865_896x736_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x6e6, /* 1766 */ + .lines_per_frame = 0x550, /* 1360 */ + }, + { + } + }, + }, + { + .desc = "ov8865_1632x1224_30fps", + .width = 1632, + .height = 1224, + .used = 0, + .regs = ov8865_1632x1224_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0642, /* 1602 */ + .lines_per_frame = 0x05da, /* 1498 */ + }, + { + } + } + }, + { + .desc = "ov8865_1936x1096_30fps", + .width = 1936, + .height = 1096, + .regs = ov8865_1936x1096_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0f98, /* 3992 */ + .lines_per_frame = 0x04b2, /* 1202 */ + }, + { + } + }, + }, + { + .desc = "ov8865_3280x1852_30fps", + .width = 3280, + .height = 1852, + .used = 0, + .regs = ov8865_3280x1852_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0920, /* 2336*/ + .lines_per_frame = 0x0800, /* 2048 */ + }, + { + } + } + }, + { + .desc = "ov8865_3280x2464_30fps", + .width = 3280, + .height = 2464, + .used = 0, + .regs = ov8865_3280x2464_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0790, /* 1936*/ + .lines_per_frame = 0x09b6, /* 2486 */ + }, + { + } + }, + }, +}; + +static struct ov8865_resolution ov8865_res_still[] = { +#if 0 + { + .desc = "ov8865_2576x1936_10fps", + .width = 2576, + .height = 1936, + .used = 0, + .regs = ov8865_2576x1936_10fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 1, + .fps_options = { + { + .fps = 10, + .pixels_per_line = 0x103a, /* 4154 */ + .lines_per_frame = 0x0d88, /* 3464 */ + }, + { + } + }, + }, +#endif + + { + .desc = "ov8865_896x736_30fps", + .width = 896, + .height = 736, + .used = 0, + .regs = ov8865_896x736_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x6e6, /* 1766 */ + .lines_per_frame = 0x550, /* 1360 */ + }, + { + } + }, + }, + { + .desc = "ov8865_1632x1224_30fps", + .width = 1632, + .height = 1224, + .used = 0, + .regs = ov8865_1632x1224_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 1, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0642, /* 1602 */ + .lines_per_frame = 0x05da, /* 1498 */ + }, + { + } + } + }, + { + .desc = "ov8865_1936x1096_30fps", + .width = 1936, + .height = 1096, + .regs = ov8865_1936x1096_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0f98, /* 3992 */ + .lines_per_frame = 0x04b2, /* 1202 */ + }, + { + } + }, + }, + { + .desc = "ov8865_3280x1852_10fps", + .width = 3280, + .height = 1852, + .used = 0, + .regs = ov8865_3280x1852_10fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 1, + .fps_options = { + { + .fps = 10, + .pixels_per_line = 0x1254, /* 4692 */ + .lines_per_frame = 0x0bfc, /* 3068 */ + }, + { + } + }, + }, + { + .desc = "ov8865_3280x2464_10fps", + .width = 3280, + .height = 2464, + .used = 0, + .regs = ov8865_3280x2464_10fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 10, + .pixels_per_line = 0x1254/* 4692*/, /* 2258 */ + .lines_per_frame = 0x0bda, /* 3034 */ + }, + { + } + }, + }, +}; + +static struct ov8865_resolution ov8865_res_video[] = { + { + .desc = "ov8865_896x736_30fps", + .width = 896, + .height = 736, + .used = 0, + .regs = ov8865_896x736_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x6e6, /* 1766 */ + .lines_per_frame = 0x550, /* 1360 */ + }, + { + } + }, + }, +#if 0 + { + .desc = "ov8865_1216x736_30fps", + .width = 1216, + .height = 736, + .used = 0, + .regs = ov8865_1216x736_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x071a, /* 1818 */ + .lines_per_frame = 0x0528, /* 1320 */ + }, + { + } + }, + }, +#endif + { + .desc = "ov8865_1632x1224_30fps", + .width = 1632, + .height = 1224, + .used = 0, + .regs = ov8865_1632x1224_30fps, + .bin_factor_x = 1, + .bin_factor_y = 1, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0642, /* 1602 */ + .lines_per_frame = 0x05da, /* 1498 */ + }, + { + } + }, + }, + + { + .desc = "ov8865_1936x1096_30fps", + .width = 1936, + .height = 1096, + .regs = ov8865_1936x1096_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0f98, /* 3992 */ + .lines_per_frame = 0x04b2, /* 1202 */ + }, + { + } + }, + }, + + { + .desc = "ov8865_3280x1852_30fps", + .width = 3280, + .height = 1852, + .used = 0, + .regs = ov8865_3280x1852_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0920, /* 2336*/ + .lines_per_frame = 0x0800, /* 2048 */ + }, + { + } + } + }, + { + .desc = "ov8865_3280x2464_30fps", + .width = 3280, + .height = 2464, + .used = 0, + .regs = ov8865_3280x2464_30fps, + .bin_factor_x = 0, + .bin_factor_y = 0, + .skip_frames = 0, + .fps_options = { + { + .fps = 30, + .pixels_per_line = 0x0790, /* 1936*/ + .lines_per_frame = 0x09b6, /* 2486 */ + }, + { + } + }, + }, + +}; + +static int +ov8865_read_reg(struct i2c_client *client, u16 len, u16 reg, u16 *val); + +static int +ov8865_write_reg(struct i2c_client *client, u16 data_length, u16 reg, u16 val); + +#endif diff --git a/drivers/media/i2c/ov8865_bld_otp.c b/drivers/media/i2c/ov8865_bld_otp.c new file mode 100644 index 000000000..059849bcd --- /dev/null +++ b/drivers/media/i2c/ov8865_bld_otp.c @@ -0,0 +1,588 @@ +/* + * Support for OmniVision ov8865 8MP camera sensor. + * + * Copyright (c) 2014 Intel Corporation. All Rights Reserved. + * + * ov8865 Data format conversion + * + * include AWB&LSC of light source table and AF table + * + */ + +#include "ov8865_bld_otp.h" + +#ifdef __KERNEL__ +static u32 ov8865_otp_save(const u8 *databuf, u32 data_size, const u8 *filp_name) +{ + struct file *fp=NULL; + mm_segment_t fs; + loff_t pos; + + fp=filp_open(filp_name,O_CREAT|O_RDWR,0644); + if(IS_ERR(fp)) + return -1; + + fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_write(fp, databuf, data_size, &pos); + set_fs(fs); + + filp_close(fp,NULL); + + return 0; +} +static int +ov8865_read_otp(struct i2c_client *client, u16 len, u16 reg, u8 *val) +{ + struct i2c_msg msg[2]; + u16 data[OV8865_SHORT_MAX]; + int err; + + if (!client->adapter) { + v4l2_err(client, "%s error, no client->adapter\n", __func__); + return -ENODEV; + } + + memset(msg, 0, sizeof(msg)); + memset(data, 0, sizeof(data)); + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = I2C_MSG_LENGTH; + msg[0].buf = (u8 *)data; + /* high byte goes first */ + data[0] = cpu_to_be16(reg); + + msg[1].addr = client->addr; + msg[1].len = len; + msg[1].flags = I2C_M_RD; + msg[1].buf = (u8 *)val; + + err = i2c_transfer(client->adapter, msg, 2); + if (err < 0) + goto error; + + return 0; + +error: + dev_err(&client->dev, "read from offset 0x%x error %d", reg, err); + return err; +} + +static int ov8865_otp_read(struct i2c_client *client, u8 *ov8865_data_ptr, u32 *ov8865_size) +{ + int ret; + int address_start = SNR_OTP_START; + int address_end = SNR_OTP_END; + + printk("ov8865 OTP debug\n"); + + // read otp into buffer + ov8865_write_reg(client, OV8865_8BIT, 0x3d84, 0xc0); // program disable, manual mode + //partial mode OTP write start address + ov8865_write_reg(client, OV8865_8BIT, 0x3d88, (address_start>>8)); + ov8865_write_reg(client, OV8865_8BIT, 0x3d89, (address_start & 0xff)); + // partial mode OTP write end address + ov8865_write_reg(client, OV8865_8BIT, 0x3d8A, (address_end>>8)); + ov8865_write_reg(client, OV8865_8BIT, 0x3d8B, (address_end & 0xff)); + ov8865_write_reg(client, OV8865_8BIT, 0x3d81, 0x01); // read otp + usleep_range(10000, 10100); + + + ret = ov8865_read_otp(client, address_end - address_start + 1, address_start, ov8865_data_ptr); + if (ret) { + OTP_LOG("ov8865 read otp failed"); + return -1; + } + + ov8865_write_reg(client, OV8865_8BIT, 0x3d81, 0x00); //stop read otp + *ov8865_size = address_end - address_start + 1; + printk("ov8865 OTP read done\n"); + return 0; +} +#endif + +static void dump_ov8865_module_info(const u8 *ov8865_data_ptr) { + module_info_t *info; + + info = (module_info_t *) &ov8865_data_ptr[ov8865_data_group_pos.module_info]; + + OTP_LOG("module information:\n"); + OTP_LOG("mid:%d calibration vsersion:%d \n", info->mid, info->calibration_version); + OTP_LOG("year:%d month:%d day:%d\n", info->year, info->month, info->day); + OTP_LOG("IDs of sensor:%d lens:%d vcm:%d ic:%d IR/BG:%d\n", info->sensor_id, + info->lens_id, info->vcm_id, info->driver_ic_id, info->IR_BG_id); + OTP_LOG("color temp:%d AF/FF:%d light:%d\n", info->color_ctc, info->af_flag, info->light_type); +} + +static int check_ov8865_calibration_ver13(const u8 *ov8865_data_ptr) +{ + unsigned char major_version, minor_version; + + major_version = ov8865_data_ptr[ov8865_data_group_pos.awb_lsc_light_source_one]; + minor_version = ov8865_data_ptr[ov8865_data_group_pos.awb_lsc_light_source_one + 1]; + + OTP_LOG("calibration major:minor -- %d : %d\n", major_version, minor_version); + if ((major_version == 1) && (minor_version == 3)) { + OTP_LOG("This is ver1.3 calibration data\n"); + return 1; + } + + return 0; + +} + +static int ov8865_otp_trans(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size) +{ + int ret = 0; + + if(ov8865_data_ptr == NULL || ov8865_size == 0) + return ENULL_OV8865; + + if(otp_data_ptr == NULL || otp_size == 0) + return ENULL_OTP; + + /* initialize ov8865_data_group_pos */ + ov8865_data_group_pos.module_info = 0; + ov8865_data_group_pos.awb_lsc_light_source_one = 0; + ov8865_data_group_pos.awb_lsc_light_source_two = 0; + ov8865_data_group_pos.af = 0; + /* check the whole ov8865 data whether is correction */ + ret = ov8865_data_check(ov8865_data_ptr,ov8865_size); + if(ret) + return ret; + /* initialize otp_data_ptr to ready for copy */ + + memset(otp_data_ptr, 0, *otp_size); + ret = otp_data_copy(ov8865_data_ptr,ov8865_size, otp_data_ptr, otp_size); + if(ret) + return ret; + + return ret; +} +/* lsc address definition*/ +static ov8865_group_address_t lsc_awb_light_src_one_group_addr[2] = { + {0x20, 0x9F}, + {0xBF, 0x9F} +}; + +static ov8865_group_address_t lsc_awb_light_src_two_group_addr[2] = { + {0x15F, 0x9F}, + {0x1FE, 0x9F} +}; +/* +8865 CRC_16 Checksum ¼ÆËãÒÔÏÂÈý×éÊý¾Ý×ܺͣº +1. 5000É«ÎÂÏÂLSCºÍAWB ÓÐЧÊý¾ÝµÄÒ»×é: µÚÒ»×飺0x7030~0x70CB µÚ¶þ×飺0x70CF~0x716A +2. 3000É«ÎÂÏÂLSCºÍAWB ÓÐЧÊý¾ÝµÄÒ»×é: µÚÒ»×飺0x7172~0x7173 0x7176~0x720A µÚ¶þ×飺0x7211~0x7212 0x7215~0x72A9 +3. AFÓÐЧÊý¾ÝµÄÒ»×飺µÚÒ»×飺0x72AC~0x72B6 µÚ¶þ×飺0x72B8~0x72C2 + +*/ +static int check_all_calibration_data(const u8 *ov8865_data_ptr, u32 offset, u32 len) +{ + u32 i = 0; + u32 sum = 0, otp_sum; + u8 tmp[DATA_BUF_SIZE]; + u32 tmp_len=0; + + memset(tmp,0,DATA_BUF_SIZE); + /* LSC information of light source 1 */ + memcpy(tmp+tmp_len, ov8865_data_ptr+ov8865_data_group_pos.awb_lsc_light_source_one, + OV8865_AWB_LSC_LIGHT_SOURCE_GROUP_LEN-3); + tmp_len += OV8865_AWB_LSC_LIGHT_SOURCE_GROUP_LEN-3; + + /* LSC information of light source 2 */ + memcpy(tmp+tmp_len, ov8865_data_ptr+ov8865_data_group_pos.awb_lsc_light_source_two + 3, 2); + tmp_len += 2; + + /* LSC information of light source 2 */ + memcpy(tmp+tmp_len, ov8865_data_ptr+ov8865_data_group_pos.awb_lsc_light_source_two+ 7, OV8865_AWB_LSC_LIGHT_SOURCE_GROUP_LEN - 10); + tmp_len += OV8865_AWB_LSC_LIGHT_SOURCE_GROUP_LEN - 10; + + /* AWB information of light source 1 */ + memcpy(tmp+tmp_len, ov8865_data_ptr+ov8865_data_group_pos.af, OV8865_AF_GROUP_LEN - 1); + tmp_len += OV8865_AF_GROUP_LEN - 1; + + /* CRC_16 checksum */ + for(i=0,sum=0;i= 0; i--) { + if ((flag >> ((3 - i) << 1)) & 0x01) break; + } + + if (i < 0) { + OTP_LOG("no valid module info found\n"); + return -1; + } + OTP_LOG("Module info found:%d start:0x%x len:0x%x\n", i, + module_info_group_addr[i].start, + module_info_group_addr[i].len); + + ret = check_ov8865_Group(ov8865_data_ptr, module_info_group_addr[i].start, module_info_group_addr[i].len); + if (ret) { + OTP_LOG("module info sum check failed\n"); + return -1; + } + + return module_info_group_addr[i].start; +} + +static int check_ov8865_AWB_LSC_light_source(const unsigned char *ov8865_data_ptr, int offset) +{ + unsigned char flag = ov8865_data_ptr[offset]; + ov8865_group_address_t *group_addr; + int i; + int ret; + + OTP_LOG("%s %d offset:%x flag:%x\n", __func__, __LINE__, offset, flag); + + if (offset == OV8865_AWB_LSC_LIGHT_SOURCE_TWO_OFFSET) { + group_addr = lsc_awb_light_src_two_group_addr; + } else { + group_addr = lsc_awb_light_src_one_group_addr; + } + + for (i = 1; i >= 0; i--) { + if ((flag >> ((3 - i) << 1)) & 0x01) break; + } + + if (i < 0) { + OTP_LOG("no valid awb info found\n"); + return -1; + } + + OTP_LOG("awb found:%d start:0x%x len:0x%x\n", i, + group_addr[i].start, + group_addr[i].len); + ret = check_ov8865_Group(ov8865_data_ptr, group_addr[i].start, group_addr[i].len); + if (ret) { + OTP_LOG("awb sum check failed\n"); + return -1; + } + + return group_addr[i].start; +} + +static ov8865_group_address_t af_info_group_addr_v13[2] = { + {0x29C, 0x0C}, + {0x2A8, 0x0C}, +}; + +static ov8865_group_address_t af_info_group_addr_non_v13[2] = { + {0x29E, 0x0C}, + {0x2AA, 0x0C}, +}; + +static int check_ov8865_AF(const unsigned char *ov8865_data_ptr, int offset) +{ + unsigned char flag = ov8865_data_ptr[offset]; + int i; + int ret; + + ov8865_group_address_t * af_info_group_addr; + + if (check_ov8865_calibration_ver13(ov8865_data_ptr) == 1) { + af_info_group_addr = &af_info_group_addr_v13[0]; + OTP_LOG("This is ver1.3 calibration AF Group 0 start:%x\n", af_info_group_addr[0].start); + } else { + af_info_group_addr = &af_info_group_addr_non_v13[0]; + OTP_LOG("This is not ver1.3 calibration AF Group 0 start:%x\n", af_info_group_addr[0].start); + } + + OTP_LOG("%s %d group check offset:%x flag:%x\n", __func__, __LINE__, offset, flag); + for (i = 1; i >= 0; i--) { + if ((flag >> ((3 - i) << 1)) & 0x01) break; + } + + if (i < 0) { + OTP_LOG("no valid AF info found\n"); + return -1; + } + OTP_LOG("AF info found:%d start:0x%x len:0x%x\n", i, + af_info_group_addr[i].start, + af_info_group_addr[i].len); + + ret = check_ov8865_Group(ov8865_data_ptr, af_info_group_addr[i].start, af_info_group_addr[i].len); + if (ret) { + OTP_LOG("module info sum check failed\n"); + return -1; + } + + return af_info_group_addr[i].start; +} + +static int check_ov8865_Group(const unsigned char *ov8865_data_ptr, int offset, int len) +{ + int i = 0; + u32 sum = 0; + /* calculated(sum) from all bytes before checksum */ + for(i=0;i> 8) ^ crc16table[index]; + } + + return crc; +} + +static int otp_data_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size) +{ + int ret = 0; + + *otp_size = 0; + ret = otp_Module_Information_copy(ov8865_data_ptr,ov8865_size,otp_data_ptr,otp_size); + if(ret == -1) + return ret; + + ret = otp_AF_copy(ov8865_data_ptr,ov8865_size,otp_data_ptr,otp_size); + if(ret == -1) + return ret; + + ret = otp_AWB_LSC_light_copy(ov8865_data_ptr,ov8865_size,otp_data_ptr,otp_size); + if(ret == -1) + return ret; + + ret = otp_crc(otp_data_ptr,otp_size); + if(ret == -1) + return ret; + + return 0; +} + +static int otp_AWB_LSC_light_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size) +{ + int ret = 0; + /* AWB and LSC of light source 1 */ + + ret = otp_AWB_LSC_light_source_copy(ov8865_data_ptr, otp_data_ptr,otp_size); + if(ret) + return -1; + + return 0; +} + +static int otp_AWB_LSC_light_source_copy(const unsigned char *ov8865_data_ptr, unsigned char *otp_data_ptr, int *otp_size) +{ + u32 otp_offset = 0; + u32 ov8865_offset = 0; + + + /* otp_data[0]:major_version and; otp_data[1]:mino_version; otp_data[2]:n_lights */ + otp_offset = 0; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* focus copy */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.af; + memcpy(otp_data_ptr+otp_offset, ov8865_data_ptr+ov8865_offset, 11); + + /* otp_data[2]:n_lights */ + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one; + otp_offset += 11; + ov8865_offset += 2; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,1); + /* otp_data[3]:cie_x1 of light source 1; otp_data[4]:cie_x1 of light source 2*/ + /* for hack*/ + otp_offset += 1; + ov8865_offset += 1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,1); + + otp_offset += 1; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+3; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,1); + + /* otp_data[5]:cie_y1 of light source 1; otp_data[6]:cie_y1 of light source 2*/ + otp_offset += 1; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one+4; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,1); + + otp_offset += 1; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+4; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,1); + + /* otp_data[7]:LSC_width; otp_data[8]: LSC_height */ + /* LSC of light source 1:lsc_fraq_bits; LSCgrid */ + otp_offset += 1; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one + 5; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1); + + /* LSC of light source 2:lsc_fraq_bits; LSCgrid */ + otp_offset += OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two + 5 +2; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-3); + + /* AWB of light source 1&2 */ + /* AWB_ch1_source_1 */ + otp_offset += OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-3; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one+5 + OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch1_source_2 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+5 +OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch2_source_1 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one+7+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch2_source_2 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+7+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch3_source_1 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one+9+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch3_source_2 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+9+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch4_source_1 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_one+0x0B+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + /* AWB_ch4_source_2 */ + otp_offset += 2; + ov8865_offset = ov8865_data_group_pos.awb_lsc_light_source_two+0x0B+ OV8865_LSC_LIGHT_SOURCE_GROUP_LEN-1; + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,2); + + *otp_size = otp_offset + 2; + + return 0; +} + +static int otp_AF_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size) +{ + /* offset 2bytes in otp_data */ + int otp_offset = 2; + int ov8865_offset = ov8865_data_group_pos.af; + /* OV8865_AF_GROUP_LEN include ov8865_data checksum(1byte) */ + memcpy(otp_data_ptr+otp_offset,ov8865_data_ptr+ov8865_offset,OV8865_AF_GROUP_LEN-1); + /* length of otp_data */ + *otp_size += OV8865_AF_GROUP_LEN-1; + + return 0; +} + +static int otp_crc(unsigned char *otp_data_ptr, int *otp_size) +{ + uint16_t crc = get_nvm_checksum((uint8_t*)otp_data_ptr,*otp_size); + unsigned char crc_buf[2]; + + memset(crc_buf, 0, 2); + /* Little endian */ + crc_buf[0] = (unsigned char)crc; + crc_buf[1] = (unsigned char)(crc>>8); + memcpy(otp_data_ptr+(*otp_size),crc_buf,2); + *otp_size += 2; + + return 0; +} + +static int otp_Module_Information_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size) +{ + /* There's nothing to copy */ + return 0; +} + diff --git a/drivers/media/i2c/ov8865_bld_otp.h b/drivers/media/i2c/ov8865_bld_otp.h new file mode 100644 index 000000000..89dc5098b --- /dev/null +++ b/drivers/media/i2c/ov8865_bld_otp.h @@ -0,0 +1,170 @@ +/* + * Support for OmniVision ov8865 8MP camera sensor. + * + * Copyright (c) 2014 Intel Corporation. All Rights Reserved. + * + * ov8865 Data format conversion + * + * include AWB&LSC of light source table and AF table + * + */ +#ifndef __KERNEL__ +#include +#include +#include +#define OTP_LOG printf +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +#else +//#define OTP_LOG_ENABLE 1 + +#ifdef OTP_LOG_ENABLE + #define OTP_LOG printk +#else + static inline void OTP_LOG(const char *fmt, ...){} +#endif + +#endif + +#define DEBUG 0x1 +#define DATA_BUF_SIZE 1024 + +#define ENULL_OV8865 -200 +#define ENULL_OTP -201 + +#define SNR_OTP_START 0x7010 +#define SNR_OTP_END 0x72CF + +#define OV8865_MODULE_INFORMATION_GROUP_LEN 0xF +#define OV8865_AWB_LSC_LIGHT_SOURCE_GROUP_LEN 0x9F +#define OV8865_AF_GROUP_LEN 0xC + +#define OV8865_MODULE_INFORMATION_OFFSET 0 + +#define OV8865_AWB_LSC_LIGHT_SOURCE_ONE_OFFSET 0x1F +#define OV8865_AWB_LSC_LIGHT_SOURCE_TWO_OFFSET 0x15E + + +#define OV8865_AF_OFFSET_VER13 0x29B +#define OV8865_AF_OFFSET_NON_VER13 0x29D + +#define OV8865_AF_GROUP_ONE_OFFSET 0x29C +#define OV8865_AF_GROUP_TWO_OFFSET 0x2A8 + +#define OV8865_LSC_LIGHT_SOURCE_GROUP_LEN 0x90 +#define OV8865_SAVE_RAW_DATA "/data/ov8865.otp" +#define OV8865_SAVE_OTP_DATA "/data/ov8865_parsed.otp" +static int ov8865_otp_trans(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size); +#ifdef __KERNEL__ +static int ov8865_otp_read(struct i2c_client *client, u8 *ov8865_data_ptr, u32 *ov8865_size); +#endif +static int ov8865_data_check(const unsigned char *ov8865_data_ptr, int ov8865_size); +static int check_ov8865_Module_Information(const unsigned char *ov8865_data_ptr, int offset); +static int check_ov8865_AWB_LSC_light_source(const unsigned char *ov8865_data_ptr, int offset); +static int check_ov8865_AF(const unsigned char *ov8865_data_ptr, int offset); +static int check_ov8865_Group(const unsigned char *ov8865_data_ptr, int offset, int len); +static uint16_t get_nvm_checksum(const uint8_t *a_data_ptr, int32_t a_size); +static int otp_data_copy(const unsigned char *ov8865_data_ptr,const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size); +static int otp_Module_Information_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size); +static int otp_AWB_LSC_light_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size); +static int otp_AWB_LSC_light_source_copy(const unsigned char *ov8865_data_ptr, unsigned char *otp_data_ptr, int *otp_size); +static int otp_AF_copy(const unsigned char *ov8865_data_ptr, const int ov8865_size, unsigned char *otp_data_ptr, int *otp_size); +static int otp_crc(unsigned char *otp_data_ptr, int *otp_size); + +/* record the valid group position in ov8865_data */ +struct ov8865_data_group_pos_st{ + int module_info; + int awb_lsc_light_source_one; + int awb_lsc_light_source_two; + int af; +}ov8865_data_group_pos; + +typedef struct ov8865_group_address{ + u32 start; /* start address of group */ + u32 len; /* length of group */ +}ov8865_group_address_t; + +typedef struct module_information { + u8 mid; + u8 calibration_version; + u8 year; + u8 month; + u8 day; + u8 sensor_id; + u8 lens_id; + u8 vcm_id; + u8 driver_ic_id; + u8 IR_BG_id; + u8 color_ctc; + u8 af_flag; + u8 light_type; + u8 reserved; +}module_info_t; + +/* CRC 16 */ +static uint16_t crc16table[] = +{ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040}; + diff --git a/include/linux/atomisp.h b/include/linux/atomisp.h new file mode 100644 index 000000000..e80b6a2a2 --- /dev/null +++ b/include/linux/atomisp.h @@ -0,0 +1,1330 @@ +/* + * Support for Medifield PNW Camera Imaging ISP subsystem. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#ifdef CSS15 +#include +#else + +#ifndef _ATOM_ISP_H +#define _ATOM_ISP_H + +#include +#include + +/* struct media_device_info.driver_version */ +#define ATOMISP_CSS_VERSION_MASK 0x00ffffff +#define ATOMISP_CSS_VERSION_15 KERNEL_VERSION(1, 5, 0) +#define ATOMISP_CSS_VERSION_20 KERNEL_VERSION(2, 0, 0) +#define ATOMISP_CSS_VERSION_21 KERNEL_VERSION(2, 1, 0) + +/* struct media_device_info.hw_revision */ +#define ATOMISP_HW_REVISION_MASK 0x0000ff00 +#define ATOMISP_HW_REVISION_SHIFT 8 +#define ATOMISP_HW_REVISION_ISP2300 0x00 +#define ATOMISP_HW_REVISION_ISP2400 0x10 +#define ATOMISP_HW_REVISION_ISP2401_LEGACY 0x11 +#define ATOMISP_HW_REVISION_ISP2401 0x20 + +#define ATOMISP_HW_STEPPING_MASK 0x000000ff +#define ATOMISP_HW_STEPPING_A0 0x00 +#define ATOMISP_HW_STEPPING_B0 0x10 + +/*ISP binary running mode*/ +#define CI_MODE_PREVIEW 0x8000 +#define CI_MODE_VIDEO 0x4000 +#define CI_MODE_STILL_CAPTURE 0x2000 +#define CI_MODE_CONTINUOUS 0x1000 +#define CI_MODE_NONE 0x0000 + +#define OUTPUT_MODE_FILE 0x0100 +#define OUTPUT_MODE_TEXT 0x0200 + +/* + * Camera HAL sets this flag in v4l2_buffer reserved2 to indicate this + * buffer has a per-frame parameter. + */ +#define ATOMISP_BUFFER_HAS_PER_FRAME_SETTING 0x80000000 + +/* Custom format for RAW capture from M10MO 0x3130314d */ +#define V4L2_PIX_FMT_CUSTOM_M10MO_RAW v4l2_fourcc('M', '1', '0', '1') + +/* Custom media bus formats being used in atomisp */ +#define V4L2_MBUS_FMT_CUSTOM_YUV420 0x8001 +#define V4L2_MBUS_FMT_CUSTOM_YVU420 0x8002 +#define V4L2_MBUS_FMT_CUSTOM_YUV422P 0x8003 +#define V4L2_MBUS_FMT_CUSTOM_YUV444 0x8004 +#define V4L2_MBUS_FMT_CUSTOM_NV12 0x8005 +#define V4L2_MBUS_FMT_CUSTOM_NV21 0x8006 +#define V4L2_MBUS_FMT_CUSTOM_NV16 0x8007 +#define V4L2_MBUS_FMT_CUSTOM_YUYV 0x8008 +#define V4L2_MBUS_FMT_CUSTOM_SBGGR16 0x8009 +#define V4L2_MBUS_FMT_CUSTOM_RGB32 0x800a + +/* Custom media bus format for M10MO RAW capture */ +#define V4L2_MBUS_FMT_CUSTOM_M10MO_RAW 0x800b + +/* Configuration used by Bayer noise reduction and YCC noise reduction */ +struct atomisp_nr_config { + /* [gain] Strength of noise reduction for Bayer NR (Used by Bayer NR) */ + unsigned int bnr_gain; + /* [gain] Strength of noise reduction for YCC NR (Used by YCC NR) */ + unsigned int ynr_gain; + /* [intensity] Sensitivity of Edge (Used by Bayer NR) */ + unsigned int direction; + /* [intensity] coring threshold for Cb (Used by YCC NR) */ + unsigned int threshold_cb; + /* [intensity] coring threshold for Cr (Used by YCC NR) */ + unsigned int threshold_cr; +}; + +/* Temporal noise reduction configuration */ +struct atomisp_tnr_config { + unsigned int gain; /* [gain] Strength of NR */ + unsigned int threshold_y;/* [intensity] Motion sensitivity for Y */ + unsigned int threshold_uv;/* [intensity] Motion sensitivity for U/V */ +}; + +/* Histogram. This contains num_elements values of type unsigned int. + * The data pointer is a DDR pointer (virtual address). + */ +struct atomisp_histogram { + unsigned int num_elements; + void __user *data; +}; + +enum atomisp_ob_mode { + atomisp_ob_mode_none, + atomisp_ob_mode_fixed, + atomisp_ob_mode_raster +}; + +/* Optical black level configuration */ +struct atomisp_ob_config { + /* Obtical black level mode (Fixed / Raster) */ + enum atomisp_ob_mode mode; + /* [intensity] optical black level for GR (relevant for fixed mode) */ + unsigned int level_gr; + /* [intensity] optical black level for R (relevant for fixed mode) */ + unsigned int level_r; + /* [intensity] optical black level for B (relevant for fixed mode) */ + unsigned int level_b; + /* [intensity] optical black level for GB (relevant for fixed mode) */ + unsigned int level_gb; + /* [BQ] 0..63 start position of OB area (relevant for raster mode) */ + unsigned short start_position; + /* [BQ] start..63 end position of OB area (relevant for raster mode) */ + unsigned short end_position; +}; + +/* Edge enhancement (sharpen) configuration */ +struct atomisp_ee_config { + /* [gain] The strength of sharpness. u5_11 */ + unsigned int gain; + /* [intensity] The threshold that divides noises from edge. u8_8 */ + unsigned int threshold; + /* [gain] The strength of sharpness in pell-mell area. u5_11 */ + unsigned int detail_gain; +}; + +struct atomisp_3a_output { + int ae_y; + int awb_cnt; + int awb_gr; + int awb_r; + int awb_b; + int awb_gb; + int af_hpf1; + int af_hpf2; +}; + +enum atomisp_calibration_type { + calibration_type1, + calibration_type2, + calibration_type3 +}; + +struct atomisp_calibration_group { + unsigned int size; + unsigned int type; + unsigned short *calb_grp_values; +}; + +struct atomisp_gc_config { + __u16 gain_k1; + __u16 gain_k2; +}; + +struct atomisp_3a_config { + unsigned int ae_y_coef_r; /* [gain] Weight of R for Y */ + unsigned int ae_y_coef_g; /* [gain] Weight of G for Y */ + unsigned int ae_y_coef_b; /* [gain] Weight of B for Y */ + unsigned int awb_lg_high_raw; /* [intensity] + AWB level gate high for raw */ + unsigned int awb_lg_low; /* [intensity] AWB level gate low */ + unsigned int awb_lg_high; /* [intensity] AWB level gate high */ + int af_fir1_coef[7]; /* [factor] AF FIR coefficients of fir1 */ + int af_fir2_coef[7]; /* [factor] AF FIR coefficients of fir2 */ +}; + +struct atomisp_dvs_grid_info { + uint32_t enable; + uint32_t width; + uint32_t aligned_width; + uint32_t height; + uint32_t aligned_height; + uint32_t bqs_per_grid_cell; + uint32_t num_hor_coefs; + uint32_t num_ver_coefs; +}; + +struct atomisp_dvs_envelop { + unsigned int width; + unsigned int height; +}; + +struct atomisp_grid_info { + uint32_t enable; + uint32_t use_dmem; + uint32_t has_histogram; + uint32_t s3a_width; + uint32_t s3a_height; + uint32_t aligned_width; + uint32_t aligned_height; + uint32_t s3a_bqs_per_grid_cell; + uint32_t deci_factor_log2; + uint32_t elem_bit_depth; +}; + +struct atomisp_dis_vector { + int x; + int y; +}; + + +/** DVS 2.0 Coefficient types. This structure contains 4 pointers to + * arrays that contain the coeffients for each type. + */ +struct atomisp_dvs2_coef_types { + short __user *odd_real; /**< real part of the odd coefficients*/ + short __user *odd_imag; /**< imaginary part of the odd coefficients*/ + short __user *even_real;/**< real part of the even coefficients*/ + short __user *even_imag;/**< imaginary part of the even coefficients*/ +}; + +/* + * DVS 2.0 Statistic types. This structure contains 4 pointers to + * arrays that contain the statistics for each type. + */ +struct atomisp_dvs2_stat_types { + int __user *odd_real; /**< real part of the odd statistics*/ + int __user *odd_imag; /**< imaginary part of the odd statistics*/ + int __user *even_real;/**< real part of the even statistics*/ + int __user *even_imag;/**< imaginary part of the even statistics*/ +}; + +struct atomisp_dis_coefficients { + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_coef_types hor_coefs; + struct atomisp_dvs2_coef_types ver_coefs; +}; + +struct atomisp_dvs2_statistics { + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_stat_types hor_prod; + struct atomisp_dvs2_stat_types ver_prod; +}; + +struct atomisp_dis_statistics { + struct atomisp_dvs2_statistics dvs2_stat; + uint32_t exp_id; +}; + +struct atomisp_3a_rgby_output { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t y; +}; + +/* + * Because we have 2 pipes at max to output metadata, therefore driver will use + * ATOMISP_MAIN_METADATA to specify the metadata from the pipe which keeps + * streaming always and use ATOMISP_SEC_METADATA to specify the metadata from + * the pipe which is streaming by request like capture pipe of ZSL or SDV mode + * as secondary metadata. And for the use case which has only one pipe + * streaming like online capture, ATOMISP_MAIN_METADATA will be used. + */ +enum atomisp_metadata_type { + ATOMISP_MAIN_METADATA = 0, + ATOMISP_SEC_METADATA, + ATOMISP_METADATA_TYPE_NUM, +}; + +struct atomisp_metadata_with_type { + /* to specify which type of metadata to get */ + enum atomisp_metadata_type type; + void __user *data; + uint32_t width; + uint32_t height; + uint32_t stride; /* in bytes */ + uint32_t exp_id; /* exposure ID */ + uint32_t *effective_width; /* mipi packets valid data size */ +}; + +struct atomisp_metadata { + void __user *data; + uint32_t width; + uint32_t height; + uint32_t stride; /* in bytes */ + uint32_t exp_id; /* exposure ID */ + uint32_t *effective_width; /* mipi packets valid data size */ +}; + +struct atomisp_ext_isp_ctrl { + uint32_t id; + uint32_t data; +}; + +struct atomisp_3a_statistics { + struct atomisp_grid_info grid_info; + struct atomisp_3a_output __user *data; + struct atomisp_3a_rgby_output __user *rgby_data; + uint32_t exp_id; /* exposure ID */ +}; + +/** + * struct atomisp_cont_capture_conf - continuous capture parameters + * @num_captures: number of still images to capture + * @skip_frames: number of frames to skip between 2 captures + * @offset: offset in ring buffer to start capture + * + * For example, to capture 1 frame from past, current, and 1 from future + * and skip one frame between each capture, parameters would be: + * num_captures:3 + * skip_frames:1 + * offset:-2 + */ + +struct atomisp_cont_capture_conf { + int num_captures; + unsigned int skip_frames; + int offset; + __u32 reserved[5]; +}; + +struct atomisp_ae_window { + int x_left; + int x_right; + int y_top; + int y_bottom; + int weight; +}; + +/* White Balance (Gain Adjust) */ +struct atomisp_wb_config { + unsigned int integer_bits; + unsigned int gr; /* unsigned .<16-integer_bits> */ + unsigned int r; /* unsigned .<16-integer_bits> */ + unsigned int b; /* unsigned .<16-integer_bits> */ + unsigned int gb; /* unsigned .<16-integer_bits> */ +}; + +/* Color Space Conversion settings */ +struct atomisp_cc_config { + unsigned int fraction_bits; + int matrix[3 * 3]; /* RGB2YUV Color matrix, signed + <13-fraction_bits>. */ +}; + +/* De pixel noise configuration */ +struct atomisp_de_config { + unsigned int pixelnoise; + unsigned int c1_coring_threshold; + unsigned int c2_coring_threshold; +}; + +/* Chroma enhancement */ +struct atomisp_ce_config { + unsigned char uv_level_min; + unsigned char uv_level_max; +}; + +/* Defect pixel correction configuration */ +struct atomisp_dp_config { + /* [intensity] The threshold of defect Pixel Correction, representing + * the permissible difference of intensity between one pixel and its + * surrounding pixels. Smaller values result in more frequent pixel + * corrections. u0_16 + */ + unsigned int threshold; + /* [gain] The sensitivity of mis-correction. ISP will miss a lot of + * defects if the value is set too large. u8_8 + */ + unsigned int gain; + unsigned int gr; + unsigned int r; + unsigned int b; + unsigned int gb; +}; + +/* XNR threshold */ +struct atomisp_xnr_config { + __u16 threshold; +}; + +/* metadata config */ +struct atomisp_metadata_config { + uint32_t metadata_height; + uint32_t metadata_stride; +}; + +/* + * Generic resolution structure. + */ +struct atomisp_resolution { + uint32_t width; /**< Width */ + uint32_t height; /**< Height */ +}; + +/* + * This specifies the coordinates (x,y) + */ +struct atomisp_zoom_point { + int32_t x; /**< x coordinate */ + int32_t y; /**< y coordinate */ +}; + +/* + * This specifies the region + */ +struct atomisp_zoom_region { + struct atomisp_zoom_point origin; /* Starting point coordinates for the region */ + struct atomisp_resolution resolution; /* Region resolution */ +}; + +struct atomisp_dz_config { + uint32_t dx; /**< Horizontal zoom factor */ + uint32_t dy; /**< Vertical zoom factor */ + struct atomisp_zoom_region zoom_region; /**< region for zoom */ +}; + +struct atomisp_parm { + struct atomisp_grid_info info; + struct atomisp_dvs_grid_info dvs_grid; + struct atomisp_dvs_envelop dvs_envelop; + struct atomisp_wb_config wb_config; + struct atomisp_cc_config cc_config; + struct atomisp_ob_config ob_config; + struct atomisp_de_config de_config; + struct atomisp_dz_config dz_config; + struct atomisp_ce_config ce_config; + struct atomisp_dp_config dp_config; + struct atomisp_nr_config nr_config; + struct atomisp_ee_config ee_config; + struct atomisp_tnr_config tnr_config; + struct atomisp_metadata_config metadata_config; +}; + +struct dvs2_bq_resolution { + int width_bq; /* width [BQ] */ + int height_bq; /* height [BQ] */ +}; + +struct atomisp_dvs2_bq_resolutions { + /* GDC source image size [BQ] */ + struct dvs2_bq_resolution source_bq; + /* GDC output image size [BQ] */ + struct dvs2_bq_resolution output_bq; + /* GDC effective envelope size [BQ] */ + struct dvs2_bq_resolution envelope_bq; + /* isp pipe filter size [BQ] */ + struct dvs2_bq_resolution ispfilter_bq; + /* GDC shit size [BQ] */ + struct dvs2_bq_resolution gdc_shift_bq; +}; + +struct atomisp_dvs_6axis_config { + uint32_t exp_id; + uint32_t width_y; + uint32_t height_y; + uint32_t width_uv; + uint32_t height_uv; + uint32_t *xcoords_y; + uint32_t *ycoords_y; + uint32_t *xcoords_uv; + uint32_t *ycoords_uv; +}; + +struct atomisp_formats_config { + uint32_t video_full_range_flag; +}; + +struct atomisp_parameters { + struct atomisp_wb_config *wb_config; /* White Balance config */ + struct atomisp_cc_config *cc_config; /* Color Correction config */ + struct atomisp_tnr_config *tnr_config; /* Temporal Noise Reduction */ + struct atomisp_ecd_config *ecd_config; /* Eigen Color Demosaicing */ + struct atomisp_ynr_config *ynr_config; /* Y(Luma) Noise Reduction */ + struct atomisp_fc_config *fc_config; /* Fringe Control */ + struct atomisp_formats_config *formats_config; /* Formats Control */ + struct atomisp_cnr_config *cnr_config; /* Chroma Noise Reduction */ + struct atomisp_macc_config *macc_config; /* MACC */ + struct atomisp_ctc_config *ctc_config; /* Chroma Tone Control */ + struct atomisp_aa_config *aa_config; /* Anti-Aliasing */ + struct atomisp_aa_config *baa_config; /* Anti-Aliasing */ + struct atomisp_ce_config *ce_config; + struct atomisp_dvs_6axis_config *dvs_6axis_config; + struct atomisp_ob_config *ob_config; /* Objective Black config */ + struct atomisp_dp_config *dp_config; /* Dead Pixel config */ + struct atomisp_nr_config *nr_config; /* Noise Reduction config */ + struct atomisp_ee_config *ee_config; /* Edge Enhancement config */ + struct atomisp_de_config *de_config; /* Demosaic config */ + struct atomisp_gc_config *gc_config; /* Gamma Correction config */ + struct atomisp_anr_config *anr_config; /* Advanced Noise Reduction */ + struct atomisp_3a_config *a3a_config; /* 3A Statistics config */ + struct atomisp_xnr_config *xnr_config; /* eXtra Noise Reduction */ + struct atomisp_dz_config *dz_config; /* Digital Zoom */ + struct atomisp_cc_config *yuv2rgb_cc_config; /* Color + Correction config */ + struct atomisp_cc_config *rgb2yuv_cc_config; /* Color + Correction config */ + struct atomisp_macc_table *macc_table; + struct atomisp_gamma_table *gamma_table; + struct atomisp_ctc_table *ctc_table; + struct atomisp_xnr_table *xnr_table; + struct atomisp_rgb_gamma_table *r_gamma_table; + struct atomisp_rgb_gamma_table *g_gamma_table; + struct atomisp_rgb_gamma_table *b_gamma_table; + struct atomisp_vector *motion_vector; /* For 2-axis DVS */ + struct atomisp_shading_table *shading_table; + struct atomisp_morph_table *morph_table; + struct atomisp_dvs_coefficients *dvs_coefs; /* DVS 1.0 coefficients */ + struct atomisp_dvs2_coefficients *dvs2_coefs; /* DVS 2.0 coefficients */ + struct atomisp_capture_config *capture_config; + struct atomisp_anr_thres *anr_thres; + + void *lin_2500_config; /* Skylake: Linearization config */ + void *obgrid_2500_config; /* Skylake: OBGRID config */ + void *bnr_2500_config; /* Skylake: bayer denoise config */ + void *shd_2500_config; /* Skylake: shading config */ + void *dm_2500_config; /* Skylake: demosaic config */ + void *rgbpp_2500_config; /* Skylake: RGBPP config */ + void *dvs_stat_2500_config; /* Skylake: DVS STAT config */ + void *lace_stat_2500_config; /* Skylake: LACE STAT config */ + void *yuvp1_2500_config; /* Skylake: yuvp1 config */ + void *yuvp2_2500_config; /* Skylake: yuvp2 config */ + void *tnr_2500_config; /* Skylake: TNR config */ + void *dpc_2500_config; /* Skylake: DPC config */ + void *awb_2500_config; /* Skylake: auto white balance config */ + void *awb_fr_2500_config; /* Skylake: auto white balance filter response config */ + void *anr_2500_config; /* Skylake: ANR config */ + void *af_2500_config; /* Skylake: auto focus config */ + void *ae_2500_config; /* Skylake: auto exposure config */ + void *bds_2500_config; /* Skylake: bayer downscaler config */ + void *dvs_2500_config; /* Skylake: digital video stabilization config */ + void *res_mgr_2500_config; + + /* + * Output frame pointer the config is to be applied to (optional), + * set to NULL to make this config is applied as global. + */ + void *output_frame; + /* + * Unique ID to track which config was actually applied to a particular + * frame, driver will send this id back with output frame together. + */ + uint32_t isp_config_id; +}; + +#define ATOMISP_GAMMA_TABLE_SIZE 1024 +struct atomisp_gamma_table { + unsigned short data[ATOMISP_GAMMA_TABLE_SIZE]; +}; + +/* Morphing table for advanced ISP. + * Each line of width elements takes up COORD_TABLE_EXT_WIDTH elements + * in memory. + */ +#define ATOMISP_MORPH_TABLE_NUM_PLANES 6 +struct atomisp_morph_table { + unsigned int enabled; + + unsigned int height; + unsigned int width; /* number of valid elements per line */ + unsigned short __user *coordinates_x[ATOMISP_MORPH_TABLE_NUM_PLANES]; + unsigned short __user *coordinates_y[ATOMISP_MORPH_TABLE_NUM_PLANES]; +}; + +#define ATOMISP_NUM_SC_COLORS 4 +#define ATOMISP_SC_FLAG_QUERY (1 << 0) + +struct atomisp_shading_table { + __u32 enable; + + __u32 sensor_width; + __u32 sensor_height; + __u32 width; + __u32 height; + __u32 fraction_bits; + + __u16 *data[ATOMISP_NUM_SC_COLORS]; +}; + +struct atomisp_makernote_info { + /* bits 31-16: numerator, bits 15-0: denominator */ + unsigned int focal_length; + /* bits 31-16: numerator, bits 15-0: denominator*/ + unsigned int f_number_curr; + /* + * bits 31-24: max f-number numerator + * bits 23-16: max f-number denominator + * bits 15-8: min f-number numerator + * bits 7-0: min f-number denominator + */ + unsigned int f_number_range; +}; + +/* parameter for MACC */ +#define ATOMISP_NUM_MACC_AXES 16 +struct atomisp_macc_table { + short data[4 * ATOMISP_NUM_MACC_AXES]; +}; + +struct atomisp_macc_config { + int color_effect; + struct atomisp_macc_table table; +}; + +/* Parameter for ctc parameter control */ +#define ATOMISP_CTC_TABLE_SIZE 1024 +struct atomisp_ctc_table { + unsigned short data[ATOMISP_CTC_TABLE_SIZE]; +}; + +/* Parameter for overlay image loading */ +struct atomisp_overlay { + /* the frame containing the overlay data The overlay frame width should + * be the multiples of 2*ISP_VEC_NELEMS. The overlay frame height + * should be the multiples of 2. + */ + struct v4l2_framebuffer *frame; + /* Y value of overlay background */ + unsigned char bg_y; + /* U value of overlay background */ + char bg_u; + /* V value of overlay background */ + char bg_v; + /* the blending percent of input data for Y subpixels */ + unsigned char blend_input_perc_y; + /* the blending percent of input data for U subpixels */ + unsigned char blend_input_perc_u; + /* the blending percent of input data for V subpixels */ + unsigned char blend_input_perc_v; + /* the blending percent of overlay data for Y subpixels */ + unsigned char blend_overlay_perc_y; + /* the blending percent of overlay data for U subpixels */ + unsigned char blend_overlay_perc_u; + /* the blending percent of overlay data for V subpixels */ + unsigned char blend_overlay_perc_v; + /* the overlay start x pixel position on output frame It should be the + multiples of 2*ISP_VEC_NELEMS. */ + unsigned int overlay_start_x; + /* the overlay start y pixel position on output frame It should be the + multiples of 2. */ + unsigned int overlay_start_y; +}; + +/* Sensor resolution specific data for AE calculation.*/ +struct atomisp_sensor_mode_data { + unsigned int coarse_integration_time_min; + unsigned int coarse_integration_time_max_margin; + unsigned int fine_integration_time_min; + unsigned int fine_integration_time_max_margin; + unsigned int fine_integration_time_def; + unsigned int frame_length_lines; + unsigned int line_length_pck; + unsigned int read_mode; + unsigned int vt_pix_clk_freq_mhz; + unsigned int crop_horizontal_start; /* Sensor crop start cord. (x0,y0)*/ + unsigned int crop_vertical_start; + unsigned int crop_horizontal_end; /* Sensor crop end cord. (x1,y1)*/ + unsigned int crop_vertical_end; + unsigned int output_width; /* input size to ISP after binning/scaling */ + unsigned int output_height; + uint8_t binning_factor_x; /* horizontal binning factor used */ + uint8_t binning_factor_y; /* vertical binning factor used */ + uint8_t reserved[2]; +}; + +struct atomisp_exposure { + unsigned int integration_time[8]; + unsigned int shutter_speed[8]; + unsigned int gain[4]; + unsigned int aperture; +}; + +/* For texture streaming. */ +struct atomisp_bc_video_package { + int ioctl_cmd; + int device_id; + int inputparam; + int outputparam; +}; + +enum atomisp_focus_hp { + ATOMISP_FOCUS_HP_IN_PROGRESS = (1U << 2), + ATOMISP_FOCUS_HP_COMPLETE = (2U << 2), + ATOMISP_FOCUS_HP_FAILED = (3U << 2) +}; + +/* Masks */ +#define ATOMISP_FOCUS_STATUS_MOVING (1U << 0) +#define ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE (1U << 1) +#define ATOMISP_FOCUS_STATUS_HOME_POSITION (3U << 2) + +enum atomisp_camera_port { + ATOMISP_CAMERA_PORT_SECONDARY, + ATOMISP_CAMERA_PORT_PRIMARY, + ATOMISP_CAMERA_PORT_TERTIARY, + ATOMISP_CAMERA_NR_PORTS +}; + +/* Flash modes. Default is off. + * Setting a flash to TORCH or INDICATOR mode will automatically + * turn it on. Setting it to FLASH mode will not turn on the flash + * until the FLASH_STROBE command is sent. */ +enum atomisp_flash_mode { + ATOMISP_FLASH_MODE_OFF, + ATOMISP_FLASH_MODE_FLASH, + ATOMISP_FLASH_MODE_TORCH, + ATOMISP_FLASH_MODE_INDICATOR, +}; + +/* Flash statuses, used by atomisp driver to check before starting + * flash and after having started flash. */ +enum atomisp_flash_status { + ATOMISP_FLASH_STATUS_OK, + ATOMISP_FLASH_STATUS_HW_ERROR, + ATOMISP_FLASH_STATUS_INTERRUPTED, + ATOMISP_FLASH_STATUS_TIMEOUT, +}; + +/* Frame status. This is used to detect corrupted frames and flash + * exposed frames. Usually, the first 2 frames coming out of the sensor + * are corrupted. When using flash, the frame before and the frame after + * the flash exposed frame may be partially exposed by flash. The ISP + * statistics for these frames should not be used by the 3A library. + * The frame status value can be found in the "reserved" field in the + * v4l2_buffer struct. */ +enum atomisp_frame_status { + ATOMISP_FRAME_STATUS_OK, + ATOMISP_FRAME_STATUS_CORRUPTED, + ATOMISP_FRAME_STATUS_FLASH_EXPOSED, + ATOMISP_FRAME_STATUS_FLASH_PARTIAL, + ATOMISP_FRAME_STATUS_FLASH_FAILED, +}; + +enum atomisp_acc_type { + ATOMISP_ACC_STANDALONE, /* Stand-alone acceleration */ + ATOMISP_ACC_OUTPUT, /* Accelerator stage on output frame */ + ATOMISP_ACC_VIEWFINDER /* Accelerator stage on viewfinder frame */ +}; + +enum atomisp_acc_arg_type { + ATOMISP_ACC_ARG_SCALAR_IN, /* Scalar input argument */ + ATOMISP_ACC_ARG_SCALAR_OUT, /* Scalar output argument */ + ATOMISP_ACC_ARG_SCALAR_IO, /* Scalar in/output argument */ + ATOMISP_ACC_ARG_PTR_IN, /* Pointer input argument */ + ATOMISP_ACC_ARG_PTR_OUT, /* Pointer output argument */ + ATOMISP_ACC_ARG_PTR_IO, /* Pointer in/output argument */ + ATOMISP_ARG_PTR_NOFLUSH, /* Pointer argument will not be flushed */ + ATOMISP_ARG_PTR_STABLE, /* Pointer input argument that is stable */ + ATOMISP_ACC_ARG_FRAME /* Frame argument */ +}; + +/** ISP memories, isp2400 */ +enum atomisp_acc_memory { + ATOMISP_ACC_MEMORY_PMEM0 = 0, + ATOMISP_ACC_MEMORY_DMEM0, + /* for backward compatibility */ + ATOMISP_ACC_MEMORY_DMEM = ATOMISP_ACC_MEMORY_DMEM0, + ATOMISP_ACC_MEMORY_VMEM0, + ATOMISP_ACC_MEMORY_VAMEM0, + ATOMISP_ACC_MEMORY_VAMEM1, + ATOMISP_ACC_MEMORY_VAMEM2, + ATOMISP_ACC_MEMORY_HMEM0, + ATOMISP_ACC_NR_MEMORY +}; + +enum atomisp_ext_isp_id { + EXT_ISP_CID_ISO = 0, + EXT_ISP_CID_CAPTURE_HDR, + EXT_ISP_CID_CAPTURE_LLS, + EXT_ISP_CID_FOCUS_MODE, + EXT_ISP_CID_FOCUS_EXECUTION, + EXT_ISP_CID_TOUCH_POSX, + EXT_ISP_CID_TOUCH_POSY, + EXT_ISP_CID_CAF_STATUS, + EXT_ISP_CID_AF_STATUS, + EXT_ISP_CID_GET_AF_MODE, + EXT_ISP_CID_CAPTURE_BURST, + EXT_ISP_CID_FLASH_MODE, + EXT_ISP_CID_ZOOM, + EXT_ISP_CID_SHOT_MODE +}; + +#define EXT_ISP_FOCUS_MODE_NORMAL 0 +#define EXT_ISP_FOCUS_MODE_MACRO 1 +#define EXT_ISP_FOCUS_MODE_TOUCH_AF 2 +#define EXT_ISP_FOCUS_MODE_PREVIEW_CAF 3 +#define EXT_ISP_FOCUS_MODE_MOVIE_CAF 4 +#define EXT_ISP_FOCUS_MODE_FACE_CAF 5 +#define EXT_ISP_FOCUS_MODE_TOUCH_MACRO 6 +#define EXT_ISP_FOCUS_MODE_TOUCH_CAF 7 + +#define EXT_ISP_FOCUS_STOP 0 +#define EXT_ISP_FOCUS_SEARCH 1 +#define EXT_ISP_PAN_FOCUSING 2 + +#define EXT_ISP_CAF_RESTART_CHECK 1 +#define EXT_ISP_CAF_STATUS_FOCUSING 2 +#define EXT_ISP_CAF_STATUS_SUCCESS 3 +#define EXT_ISP_CAF_STATUS_FAIL 4 + +#define EXT_ISP_AF_STATUS_INVALID 1 +#define EXT_ISP_AF_STATUS_FOCUSING 2 +#define EXT_ISP_AF_STATUS_SUCCESS 3 +#define EXT_ISP_AF_STATUS_FAIL 4 + +enum atomisp_burst_capture_options { + EXT_ISP_BURST_CAPTURE_CTRL_START = 0, + EXT_ISP_BURST_CAPTURE_CTRL_STOP +}; + +#define EXT_ISP_FLASH_MODE_OFF 0 +#define EXT_ISP_FLASH_MODE_ON 1 +#define EXT_ISP_FLASH_MODE_AUTO 2 +#define EXT_ISP_LED_TORCH_OFF 3 +#define EXT_ISP_LED_TORCH_ON 4 + +#define EXT_ISP_SHOT_MODE_AUTO 0 +#define EXT_ISP_SHOT_MODE_BEAUTY_FACE 1 +#define EXT_ISP_SHOT_MODE_BEST_PHOTO 2 +#define EXT_ISP_SHOT_MODE_DRAMA 3 +#define EXT_ISP_SHOT_MODE_BEST_FACE 4 +#define EXT_ISP_SHOT_MODE_ERASER 5 +#define EXT_ISP_SHOT_MODE_PANORAMA 6 +#define EXT_ISP_SHOT_MODE_RICH_TONE_HDR 7 +#define EXT_ISP_SHOT_MODE_NIGHT 8 +#define EXT_ISP_SHOT_MODE_SOUND_SHOT 9 +#define EXT_ISP_SHOT_MODE_ANIMATED_PHOTO 10 +#define EXT_ISP_SHOT_MODE_SPORTS 11 + +struct atomisp_sp_arg { + enum atomisp_acc_arg_type type; /* Type of SP argument */ + void *value; /* Value of SP argument */ + unsigned int size; /* Size of SP argument */ +}; + +/* Acceleration API */ + +/* For CSS 1.0 only */ +struct atomisp_acc_fw_arg { + unsigned int fw_handle; + unsigned int index; + void __user *value; + size_t size; +}; + +/* + * Set arguments after first mapping with ATOMISP_IOC_ACC_S_MAPPED_ARG. + */ +struct atomisp_acc_s_mapped_arg { + unsigned int fw_handle; + __u32 memory; /* one of enum atomisp_acc_memory */ + size_t length; + unsigned long css_ptr; +}; + +struct atomisp_acc_fw_abort { + unsigned int fw_handle; + /* Timeout in us */ + unsigned int timeout; +}; + +struct atomisp_acc_fw_load { + unsigned int size; + unsigned int fw_handle; + void __user *data; +}; + +/* + * Load firmware to specified pipeline. + */ +struct atomisp_acc_fw_load_to_pipe { + __u32 flags; /* Flags, see below for valid values */ + unsigned int fw_handle; /* Handle, filled by kernel. */ + __u32 size; /* Firmware binary size */ + void __user *data; /* Pointer to firmware */ + __u32 type; /* Binary type */ + __u32 reserved[3]; /* Set to zero */ +}; + +#define ATOMISP_ACC_FW_LOAD_FL_PREVIEW (1 << 0) +#define ATOMISP_ACC_FW_LOAD_FL_COPY (1 << 1) +#define ATOMISP_ACC_FW_LOAD_FL_VIDEO (1 << 2) +#define ATOMISP_ACC_FW_LOAD_FL_CAPTURE (1 << 3) +#define ATOMISP_ACC_FW_LOAD_FL_ACC (1 << 4) +#define ATOMISP_ACC_FW_LOAD_FL_ENABLE (1 << 16) + +#define ATOMISP_ACC_FW_LOAD_TYPE_NONE 0 /* Normal binary: don't use */ +#define ATOMISP_ACC_FW_LOAD_TYPE_OUTPUT 1 /* Stage on output */ +#define ATOMISP_ACC_FW_LOAD_TYPE_VIEWFINDER 2 /* Stage on viewfinder */ +#define ATOMISP_ACC_FW_LOAD_TYPE_STANDALONE 3 /* Stand-alone acceleration */ + +struct atomisp_acc_map { + __u32 flags; /* Flags, see list below */ + __u32 length; /* Length of data in bytes */ + void __user *user_ptr; /* Pointer into user space */ + unsigned long css_ptr; /* Pointer into CSS address space */ + __u32 reserved[4]; /* Set to zero */ +}; + +#define ATOMISP_MAP_FLAG_NOFLUSH 0x0001 /* Do not flush cache */ +#define ATOMISP_MAP_FLAG_CACHED 0x0002 /* Enable cache */ + +struct atomisp_acc_state { + __u32 flags; /* Flags, see list below */ +#define ATOMISP_STATE_FLAG_ENABLE ATOMISP_ACC_FW_LOAD_FL_ENABLE + unsigned int fw_handle; +}; + +/* + * V4L2 private internal data interface. + * ----------------------------------------------------------------------------- + * struct v4l2_private_int_data - request private data stored in video device + * internal memory. + * @size: sanity check to ensure userspace's buffer fits whole private data. + * If not, kernel will make partial copy (or nothing if @size == 0). + * @size is always corrected for the minimum necessary if IOCTL returns + * no error. + * @data: pointer to userspace buffer. + */ +struct v4l2_private_int_data { + __u32 size; + void __user *data; + __u32 reserved[2]; +}; + +enum atomisp_sensor_ae_bracketing_mode { + SENSOR_AE_BRACKETING_MODE_OFF = 0, + SENSOR_AE_BRACKETING_MODE_SINGLE, /* back to SW standby after bracketing */ + SENSOR_AE_BRACKETING_MODE_SINGLE_TO_STREAMING, /* back to normal streaming after bracketing */ + SENSOR_AE_BRACKETING_MODE_LOOP, /* continue AE bracketing in loop mode */ +}; + +struct atomisp_sensor_ae_bracketing_info { + unsigned int modes; /* bit mask to indicate supported modes */ + unsigned int lut_depth; +}; + +struct atomisp_sensor_ae_bracketing_lut_entry { + __u16 coarse_integration_time; + __u16 analog_gain; + __u16 digital_gain; +}; + +struct atomisp_sensor_ae_bracketing_lut { + struct atomisp_sensor_ae_bracketing_lut_entry *lut; + unsigned int lut_size; +}; + +/*Private IOCTLs for ISP */ +#define ATOMISP_IOC_G_XNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 0, int) +#define ATOMISP_IOC_S_XNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 0, int) +#define ATOMISP_IOC_G_NR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 1, struct atomisp_nr_config) +#define ATOMISP_IOC_S_NR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 1, struct atomisp_nr_config) +#define ATOMISP_IOC_G_TNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct atomisp_tnr_config) +#define ATOMISP_IOC_S_TNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 2, struct atomisp_tnr_config) +#define ATOMISP_IOC_G_HISTOGRAM \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram) +#define ATOMISP_IOC_S_HISTOGRAM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram) +#define ATOMISP_IOC_G_BLACK_LEVEL_COMP \ + _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct atomisp_ob_config) +#define ATOMISP_IOC_S_BLACK_LEVEL_COMP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 4, struct atomisp_ob_config) +#define ATOMISP_IOC_G_EE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 5, struct atomisp_ee_config) +#define ATOMISP_IOC_S_EE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct atomisp_ee_config) +/* Digital Image Stabilization: + * 1. get dis statistics: reads DIS statistics from ISP (every frame) + * 2. set dis coefficients: set DIS filter coefficients (one time) + * 3. set dis motion vecotr: set motion vector (result of DIS, every frame) + */ +#define ATOMISP_IOC_G_DIS_STAT \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dis_statistics) + +#define ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS \ + _IOR('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dvs2_bq_resolutions) + +#define ATOMISP_IOC_S_DIS_COEFS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dis_coefficients) + +#define ATOMISP_IOC_S_DIS_VECTOR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dvs_6axis_config) + +#define ATOMISP_IOC_G_3A_STAT \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 7, struct atomisp_3a_statistics) +#define ATOMISP_IOC_G_ISP_PARM \ + _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct atomisp_parm) +#define ATOMISP_IOC_S_ISP_PARM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 8, struct atomisp_parm) +#define ATOMISP_IOC_G_ISP_GAMMA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 9, struct atomisp_gamma_table) +#define ATOMISP_IOC_S_ISP_GAMMA \ + _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct atomisp_gamma_table) +#define ATOMISP_IOC_G_ISP_GDC_TAB \ + _IOR('v', BASE_VIDIOC_PRIVATE + 10, struct atomisp_morph_table) +#define ATOMISP_IOC_S_ISP_GDC_TAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 10, struct atomisp_morph_table) +#define ATOMISP_IOC_ISP_MAKERNOTE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 11, struct atomisp_makernote_info) + +/* macc parameter control*/ +#define ATOMISP_IOC_G_ISP_MACC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct atomisp_macc_config) +#define ATOMISP_IOC_S_ISP_MACC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 12, struct atomisp_macc_config) + +/* Defect pixel detection & Correction */ +#define ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 13, struct atomisp_dp_config) +#define ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct atomisp_dp_config) + +/* False Color Correction */ +#define ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 14, struct atomisp_de_config) +#define ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 14, struct atomisp_de_config) + +/* ctc parameter control */ +#define ATOMISP_IOC_G_ISP_CTC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 15, struct atomisp_ctc_table) +#define ATOMISP_IOC_S_ISP_CTC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct atomisp_ctc_table) + +/* white balance Correction */ +#define ATOMISP_IOC_G_ISP_WHITE_BALANCE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_wb_config) +#define ATOMISP_IOC_S_ISP_WHITE_BALANCE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_wb_config) + +/* fpn table loading */ +#define ATOMISP_IOC_S_ISP_FPN_TABLE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 17, struct v4l2_framebuffer) + +/* overlay image loading */ +#define ATOMISP_IOC_G_ISP_OVERLAY \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay) +#define ATOMISP_IOC_S_ISP_OVERLAY \ + _IOW('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay) + +/* bcd driver bridge */ +#define ATOMISP_IOC_CAMERA_BRIDGE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 19, struct atomisp_bc_video_package) + +/* Sensor resolution specific info for AE */ +#define ATOMISP_IOC_G_SENSOR_MODE_DATA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 20, struct atomisp_sensor_mode_data) + +#define ATOMISP_IOC_S_EXPOSURE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_exposure) + +/* sensor calibration registers group */ +#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group) + +/* white balance Correction */ +#define ATOMISP_IOC_G_3A_CONFIG \ + _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) +#define ATOMISP_IOC_S_3A_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) + +/* Accelerate ioctls */ +#define ATOMISP_IOC_ACC_LOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 24, struct atomisp_acc_fw_load) + +#define ATOMISP_IOC_ACC_UNLOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 24, unsigned int) + +/* For CSS 1.0 only */ +#define ATOMISP_IOC_ACC_S_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 24, struct atomisp_acc_fw_arg) + +#define ATOMISP_IOC_ACC_START \ + _IOW('v', BASE_VIDIOC_PRIVATE + 24, unsigned int) + +#define ATOMISP_IOC_ACC_WAIT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, unsigned int) + +#define ATOMISP_IOC_ACC_ABORT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, struct atomisp_acc_fw_abort) + +#define ATOMISP_IOC_ACC_DESTAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, struct atomisp_acc_fw_arg) + +/* sensor OTP memory read */ +#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data) + +/* LCS (shading) table write */ +#define ATOMISP_IOC_S_ISP_SHD_TAB \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table) + +/* Gamma Correction */ +#define ATOMISP_IOC_G_ISP_GAMMA_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) + +#define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) + +/* motor internal memory read */ +#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data) + +/* + * Ioctls to map and unmap user buffers to CSS address space for acceleration. + * User fills fields length and user_ptr and sets other fields to zero, + * kernel may modify the flags and sets css_ptr. + */ +#define ATOMISP_IOC_ACC_MAP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_map) + +/* User fills fields length, user_ptr, and css_ptr and zeroes other fields. */ +#define ATOMISP_IOC_ACC_UNMAP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_map) + +#define ATOMISP_IOC_ACC_S_MAPPED_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_s_mapped_arg) + +#define ATOMISP_IOC_ACC_LOAD_TO_PIPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 31, struct atomisp_acc_fw_load_to_pipe) + +#define ATOMISP_IOC_S_PARAMETERS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters) + +#define ATOMISP_IOC_S_CONT_CAPTURE_CONFIG \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 33, struct atomisp_cont_capture_conf) + +#define ATOMISP_IOC_G_METADATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata) + +#define ATOMISP_IOC_G_METADATA_BY_TYPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type) + +#define ATOMISP_IOC_EXT_ISP_CTRL \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 35, struct atomisp_ext_isp_ctrl) + +#define ATOMISP_IOC_EXP_ID_UNLOCK \ + _IOW('v', BASE_VIDIOC_PRIVATE + 36, int) + +#define ATOMISP_IOC_EXP_ID_CAPTURE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 37, int) + +#define ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 38, unsigned int) + +#define ATOMISP_IOC_G_FORMATS_CONFIG \ + _IOR('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) + +#define ATOMISP_IOC_S_FORMATS_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) + +#define ATOMISP_IOC_S_EXPOSURE_WINDOW \ + _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_ae_window) + +#define ATOMISP_IOC_S_ACC_STATE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 41, struct atomisp_acc_state) + +#define ATOMISP_IOC_G_ACC_STATE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 41, struct atomisp_acc_state) + +#define ATOMISP_IOC_INJECT_A_FAKE_EVENT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 42, int) + +#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO \ + _IOR('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_info) + +#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) + +#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) + +#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut) + +#define ATOMISP_IOC_G_INVALID_FRAME_NUM \ + _IOR('v', BASE_VIDIOC_PRIVATE + 44, unsigned int) + +#define ATOMISP_IOC_G_EFFECTIVE_RESOLUTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 45, struct atomisp_resolution) + + +/* + * Reserved ioctls. We have customer implementing it internally. + * We can't use both numbers to not cause ABI conflict. + * Anyway, those ioctls are hacks and not implemented by us: + * + * #define ATOMISP_IOC_G_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 55, struct atomisp_sensor_regs) + * #define ATOMISP_IOC_S_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 56, struct atomisp_sensor_regs) + */ + +/* ISP Private control IDs */ +#define V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION \ + (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC \ + (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_ATOMISP_VIDEO_STABLIZATION \ + (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_ATOMISP_FIXED_PATTERN_NR \ + (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION \ + (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_ATOMISP_LOW_LIGHT \ + (V4L2_CID_PRIVATE_BASE + 5) + +/* Camera class: + * Exposure, Flash and privacy (indicator) light controls, to be upstreamed */ +#define V4L2_CID_CAMERA_LASTP1 (V4L2_CID_CAMERA_CLASS_BASE + 1024) + +#define V4L2_CID_FOCAL_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 0) +#define V4L2_CID_FNUMBER_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 1) +#define V4L2_CID_FNUMBER_RANGE (V4L2_CID_CAMERA_LASTP1 + 2) + +/* Flash related CIDs, see also: + * http://linuxtv.org/downloads/v4l-dvb-apis/extended-controls.html\ + * #flash-controls */ + +/* Request a number of flash-exposed frames. The frame status can be + * found in the reserved field in the v4l2_buffer struct. */ +#define V4L2_CID_REQUEST_FLASH (V4L2_CID_CAMERA_LASTP1 + 3) +/* Query flash driver status. See enum atomisp_flash_status above. */ +#define V4L2_CID_FLASH_STATUS (V4L2_CID_CAMERA_LASTP1 + 5) +/* Set the flash mode (see enum atomisp_flash_mode) */ +#define V4L2_CID_FLASH_MODE (V4L2_CID_CAMERA_LASTP1 + 10) + +/* VCM slew control */ +#define V4L2_CID_VCM_SLEW (V4L2_CID_CAMERA_LASTP1 + 11) +/* VCM step time */ +#define V4L2_CID_VCM_TIMEING (V4L2_CID_CAMERA_LASTP1 + 12) + +/* Query Focus Status */ +#define V4L2_CID_FOCUS_STATUS (V4L2_CID_CAMERA_LASTP1 + 14) + +/* Query sensor's binning factor */ +#define V4L2_CID_BIN_FACTOR_HORZ (V4L2_CID_CAMERA_LASTP1 + 15) +#define V4L2_CID_BIN_FACTOR_VERT (V4L2_CID_CAMERA_LASTP1 + 16) + +/* number of frames to skip at stream start */ +#define V4L2_CID_G_SKIP_FRAMES (V4L2_CID_CAMERA_LASTP1 + 17) + +/* Query sensor's 2A status */ +#define V4L2_CID_2A_STATUS (V4L2_CID_CAMERA_LASTP1 + 18) +#define V4L2_2A_STATUS_AE_READY (1 << 0) +#define V4L2_2A_STATUS_AWB_READY (1 << 1) + +#define V4L2_CID_FMT_AUTO (V4L2_CID_CAMERA_LASTP1 + 19) + +#define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20) +#define ATOMISP_RUN_MODE_VIDEO 1 +#define ATOMISP_RUN_MODE_STILL_CAPTURE 2 +#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3 +#define ATOMISP_RUN_MODE_PREVIEW 4 +#define ATOMISP_RUN_MODE_SDV 5 + +#define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21) +#define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22) +#define V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE \ + (V4L2_CID_CAMERA_LASTP1 + 23) +#define V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER \ + (V4L2_CID_CAMERA_LASTP1 + 24) + +#define V4L2_CID_VFPP (V4L2_CID_CAMERA_LASTP1 + 25) +#define ATOMISP_VFPP_ENABLE 0 +#define ATOMISP_VFPP_DISABLE_SCALER 1 +#define ATOMISP_VFPP_DISABLE_LOWLAT 2 + +/* Query real flash status register value */ +#define V4L2_CID_FLASH_STATUS_REGISTER (V4L2_CID_CAMERA_LASTP1 + 26) + +#define V4L2_CID_START_ZSL_CAPTURE (V4L2_CID_CAMERA_LASTP1 + 28) +/* Lock and unlock raw buffer */ +#define V4L2_CID_ENABLE_RAW_BUFFER_LOCK (V4L2_CID_CAMERA_LASTP1 + 29) + +#define V4L2_CID_DEPTH_MODE (V4L2_CID_CAMERA_LASTP1 + 30) + +#define V4L2_CID_EXPOSURE_ZONE_NUM (V4L2_CID_CAMERA_LASTP1 + 31) +/* Disable digital zoom */ +#define V4L2_CID_DISABLE_DZ (V4L2_CID_CAMERA_LASTP1 + 32) + +#define V4L2_CID_TEST_PATTERN_COLOR_R (V4L2_CID_CAMERA_LASTP1 + 33) +#define V4L2_CID_TEST_PATTERN_COLOR_GR (V4L2_CID_CAMERA_LASTP1 + 34) +#define V4L2_CID_TEST_PATTERN_COLOR_GB (V4L2_CID_CAMERA_LASTP1 + 35) +#define V4L2_CID_TEST_PATTERN_COLOR_B (V4L2_CID_CAMERA_LASTP1 + 36) + +#define V4L2_BUF_FLAG_BUFFER_INVALID 0x0400 +#define V4L2_BUF_FLAG_BUFFER_VALID 0x0800 + +#define V4L2_BUF_TYPE_VIDEO_CAPTURE_ION (V4L2_BUF_TYPE_PRIVATE + 1024) + +#define V4L2_EVENT_ATOMISP_3A_STATS_READY (V4L2_EVENT_PRIVATE_START + 1) +#define V4L2_EVENT_ATOMISP_METADATA_READY (V4L2_EVENT_PRIVATE_START + 2) +#define V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE (V4L2_EVENT_PRIVATE_START + 3) +#define V4L2_EVENT_ATOMISP_ACC_COMPLETE (V4L2_EVENT_PRIVATE_START + 4) + +/* Nonstandard color effects for V4L2_CID_COLORFX */ +enum { + V4L2_COLORFX_SKIN_WHITEN_LOW = 1001, + V4L2_COLORFX_SKIN_WHITEN_HIGH = 1002, + V4L2_COLORFX_WARM = 1003, + V4L2_COLORFX_COLD = 1004, + V4L2_COLORFX_WASHED = 1005, + V4L2_COLORFX_RED = 1006, + V4L2_COLORFX_GREEN = 1007, + V4L2_COLORFX_BLUE = 1008, + V4L2_COLORFX_PINK = 1009, + V4L2_COLORFX_YELLOW = 1010, + V4L2_COLORFX_PURPLE = 1011, +}; + +#endif /* _ATOM_ISP_H */ +#endif /* CSS15*/ diff --git a/include/linux/atomisp_css15.h b/include/linux/atomisp_css15.h new file mode 100644 index 000000000..ea02615af --- /dev/null +++ b/include/linux/atomisp_css15.h @@ -0,0 +1,1097 @@ +/* + * Support for Medifield PNW Camera Imaging ISP subsystem. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifndef _ATOM_ISP_CSS15_H +#define _ATOM_ISP_CSS15_H + +#include +#include + +/* struct media_device_info.driver_version */ +#define ATOMISP_CSS_VERSION_MASK 0x00ffffff +#define ATOMISP_CSS_VERSION_15 KERNEL_VERSION(1, 5, 0) +#define ATOMISP_CSS_VERSION_20 KERNEL_VERSION(2, 0, 0) +#define ATOMISP_CSS_VERSION_21 KERNEL_VERSION(2, 1, 0) + +/* struct media_device_info.hw_revision */ +#define ATOMISP_HW_REVISION_MASK 0x0000ff00 +#define ATOMISP_HW_REVISION_SHIFT 8 +#define ATOMISP_HW_REVISION_ISP2300 0x00 +#define ATOMISP_HW_REVISION_ISP2400 0x10 +#define ATOMISP_HW_REVISION_ISP2401_LEGACY 0x11 +#define ATOMISP_HW_REVISION_ISP2401 0x20 + +#define ATOMISP_HW_STEPPING_MASK 0x000000ff +#define ATOMISP_HW_STEPPING_A0 0x00 +#define ATOMISP_HW_STEPPING_B0 0x10 + +/*ISP binary running mode*/ +#define CI_MODE_PREVIEW 0x8000 +#define CI_MODE_VIDEO 0x4000 +#define CI_MODE_STILL_CAPTURE 0x2000 +#define CI_MODE_CONTINUOUS 0x1000 +#define CI_MODE_NONE 0x0000 + +#define OUTPUT_MODE_FILE 0x0100 +#define OUTPUT_MODE_TEXT 0x0200 + +/* Configuration used by Bayer noise reduction and YCC noise reduction */ +struct atomisp_nr_config { + /* [gain] Strength of noise reduction for Bayer NR (Used by Bayer NR) */ + unsigned int bnr_gain; + /* [gain] Strength of noise reduction for YCC NR (Used by YCC NR) */ + unsigned int ynr_gain; + /* [intensity] Sensitivity of Edge (Used by Bayer NR) */ + unsigned int direction; + /* [intensity] coring threshold for Cb (Used by YCC NR) */ + unsigned int threshold_cb; + /* [intensity] coring threshold for Cr (Used by YCC NR) */ + unsigned int threshold_cr; +}; + +/* Temporal noise reduction configuration */ +struct atomisp_tnr_config { + unsigned int gain; /* [gain] Strength of NR */ + unsigned int threshold_y;/* [intensity] Motion sensitivity for Y */ + unsigned int threshold_uv;/* [intensity] Motion sensitivity for U/V */ +}; + +/* Histogram. This contains num_elements values of type unsigned int. + * The data pointer is a DDR pointer (virtual address). + */ +struct atomisp_histogram { + unsigned int num_elements; + void __user *data; +}; + +enum atomisp_ob_mode { + atomisp_ob_mode_none, + atomisp_ob_mode_fixed, + atomisp_ob_mode_raster +}; + +/* Optical black level configuration */ +struct atomisp_ob_config { + /* Obtical black level mode (Fixed / Raster) */ + enum atomisp_ob_mode mode; + /* [intensity] optical black level for GR (relevant for fixed mode) */ + unsigned int level_gr; + /* [intensity] optical black level for R (relevant for fixed mode) */ + unsigned int level_r; + /* [intensity] optical black level for B (relevant for fixed mode) */ + unsigned int level_b; + /* [intensity] optical black level for GB (relevant for fixed mode) */ + unsigned int level_gb; + /* [BQ] 0..63 start position of OB area (relevant for raster mode) */ + unsigned short start_position; + /* [BQ] start..63 end position of OB area (relevant for raster mode) */ + unsigned short end_position; +}; + +/* Edge enhancement (sharpen) configuration */ +struct atomisp_ee_config { + /* [gain] The strength of sharpness. u5_11 */ + unsigned int gain; + /* [intensity] The threshold that divides noises from edge. u8_8 */ + unsigned int threshold; + /* [gain] The strength of sharpness in pell-mell area. u5_11 */ + unsigned int detail_gain; +}; + +struct atomisp_3a_output { + int ae_y; + int awb_cnt; + int awb_gr; + int awb_r; + int awb_b; + int awb_gb; + int af_hpf1; + int af_hpf2; +}; + +enum atomisp_calibration_type { + calibration_type1, + calibration_type2, + calibration_type3 +}; + +struct atomisp_calibration_group { + unsigned int size; + unsigned int type; + unsigned short *calb_grp_values; +}; + +struct atomisp_gc_config { + __u16 gain_k1; + __u16 gain_k2; +}; + +struct atomisp_3a_config { + unsigned int ae_y_coef_r; /* [gain] Weight of R for Y */ + unsigned int ae_y_coef_g; /* [gain] Weight of G for Y */ + unsigned int ae_y_coef_b; /* [gain] Weight of B for Y */ + unsigned int awb_lg_high_raw; /* [intensity] + AWB level gate high for raw */ + unsigned int awb_lg_low; /* [intensity] AWB level gate low */ + unsigned int awb_lg_high; /* [intensity] AWB level gate high */ + int af_fir1_coef[7]; /* [factor] AF FIR coefficients of fir1 */ + int af_fir2_coef[7]; /* [factor] AF FIR coefficients of fir2 */ +}; + +struct atomisp_dvs_grid_info { + uint32_t enable; + uint32_t width; + uint32_t aligned_width; + uint32_t height; + uint32_t aligned_height; + uint32_t bqs_per_grid_cell; + uint32_t num_hor_coefs; + uint32_t num_ver_coefs; +}; + +struct atomisp_dvs_envelop { + unsigned int width; + unsigned int height; +}; + +#ifdef CSS20 +struct atomisp_grid_info { + uint32_t enable; + uint32_t use_dmem; + uint32_t has_histogram; + uint32_t s3a_width; + uint32_t s3a_height; + uint32_t aligned_width; + uint32_t aligned_height; + uint32_t s3a_bqs_per_grid_cell; + uint32_t deci_factor_log2; + uint32_t elem_bit_depth; +}; +#else /* CSS20 */ +/* structure that describes the 3A and DIS grids shared with 3A lib*/ +struct atomisp_grid_info { + /* ISP input size that is visible for user */ + unsigned int isp_in_width; + unsigned int isp_in_height; + /* 3A statistics grid: */ + unsigned int s3a_width; + unsigned int s3a_height; + unsigned int s3a_bqs_per_grid_cell; + /* DIS grid: */ + unsigned int dis_width; /* also used for vertical projections */ + unsigned int dis_aligned_width; + unsigned int dis_height; /* also used for horizontal projections */ + unsigned int dis_aligned_height; + unsigned int dis_bqs_per_grid_cell; + unsigned int dis_hor_coef_num; + unsigned int dis_ver_coef_num; +}; +#endif /* CSS20 */ +struct atomisp_dis_vector { + int x; + int y; +}; + + +/** DVS 2.0 Coefficient types. This structure contains 4 pointers to + * arrays that contain the coeffients for each type. + */ +struct atomisp_dvs2_coef_types { + short __user *odd_real; /**< real part of the odd coefficients*/ + short __user *odd_imag; /**< imaginary part of the odd coefficients*/ + short __user *even_real;/**< real part of the even coefficients*/ + short __user *even_imag;/**< imaginary part of the even coefficients*/ +}; + +/* + * DVS 2.0 Statistic types. This structure contains 4 pointers to + * arrays that contain the statistics for each type. + */ +struct atomisp_dvs2_stat_types { + int __user *odd_real; /**< real part of the odd statistics*/ + int __user *odd_imag; /**< imaginary part of the odd statistics*/ + int __user *even_real;/**< real part of the even statistics*/ + int __user *even_imag;/**< imaginary part of the even statistics*/ +}; + +struct atomisp_dis_coefficients { +#ifdef CSS20 + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_coef_types hor_coefs; + struct atomisp_dvs2_coef_types ver_coefs; +#else /* CSS20 */ + struct atomisp_grid_info grid_info; + short __user *vertical_coefficients; + short __user *horizontal_coefficients; +#endif /* CSS20 */ +}; + +struct atomisp_dvs2_statistics { + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_stat_types hor_prod; + struct atomisp_dvs2_stat_types ver_prod; +}; + +struct atomisp_dis_statistics { +#ifdef CSS20 + struct atomisp_dvs2_statistics dvs2_stat; + uint32_t exp_id; +#else /* CSS20 */ + struct atomisp_grid_info grid_info; + int __user *vertical_projections; + int __user *horizontal_projections; +#endif +}; + +struct atomisp_3a_rgby_output { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t y; +}; + +#ifdef CSS20 +struct atomisp_3a_statistics { + struct atomisp_grid_info grid_info; + struct atomisp_3a_output __user *data; + struct atomisp_3a_rgby_output __user *rgby_data; +}; +#else /* CSS20 */ +struct atomisp_3a_statistics { + struct atomisp_grid_info grid_info; + struct atomisp_3a_output __user *data; +}; +#endif /* CSS20 */ +/** + * struct atomisp_cont_capture_conf - continuous capture parameters + * @num_captures: number of still images to capture + * @skip_frames: number of frames to skip between 2 captures + * @offset: offset in ring buffer to start capture + * + * For example, to capture 1 frame from past, current, and 1 from future + * and skip one frame between each capture, parameters would be: + * num_captures:3 + * skip_frames:1 + * offset:-2 + */ + +struct atomisp_cont_capture_conf { + int num_captures; + unsigned int skip_frames; + int offset; + __u32 reserved[5]; +}; + +/* White Balance (Gain Adjust) */ +struct atomisp_wb_config { + unsigned int integer_bits; + unsigned int gr; /* unsigned .<16-integer_bits> */ + unsigned int r; /* unsigned .<16-integer_bits> */ + unsigned int b; /* unsigned .<16-integer_bits> */ + unsigned int gb; /* unsigned .<16-integer_bits> */ +}; + +/* Color Space Conversion settings */ +struct atomisp_cc_config { + unsigned int fraction_bits; + int matrix[3 * 3]; /* RGB2YUV Color matrix, signed + <13-fraction_bits>. */ +}; + +/* De pixel noise configuration */ +struct atomisp_de_config { + unsigned int pixelnoise; + unsigned int c1_coring_threshold; + unsigned int c2_coring_threshold; +}; + +/* Chroma enhancement */ +#ifdef CSS20 +struct atomisp_ce_config { + unsigned char uv_level_min; + unsigned char uv_level_max; +}; +#else +struct atomisp_ce_config { + unsigned int uv_level_min; + unsigned int uv_level_max; +}; +#endif + +/* Defect pixel correction configuration */ +struct atomisp_dp_config { + /* [intensity] The threshold of defect Pixel Correction, representing + * the permissible difference of intensity between one pixel and its + * surrounding pixels. Smaller values result in more frequent pixel + * corrections. u0_16 + */ + unsigned int threshold; + /* [gain] The sensitivity of mis-correction. ISP will miss a lot of + * defects if the value is set too large. u8_8 + */ + unsigned int gain; +#ifdef CSS21 + unsigned int gr; + unsigned int r; + unsigned int b; + unsigned int gb; +#endif +}; + +/* XNR threshold */ +struct atomisp_xnr_config { +#ifdef CSS21 + __u16 threshold; +#else + unsigned int threshold; +#endif +}; + +struct atomisp_parm { + struct atomisp_grid_info info; +#ifdef CSS20 + struct atomisp_dvs_grid_info dvs_grid; + struct atomisp_dvs_envelop dvs_envelop; +#endif + struct atomisp_wb_config wb_config; + struct atomisp_cc_config cc_config; + struct atomisp_ob_config ob_config; + struct atomisp_de_config de_config; + struct atomisp_ce_config ce_config; + struct atomisp_dp_config dp_config; + struct atomisp_nr_config nr_config; + struct atomisp_ee_config ee_config; + struct atomisp_tnr_config tnr_config; +}; + +struct atomisp_dvs_6axis_config { + uint32_t exp_id; + uint32_t width_y; + uint32_t height_y; + uint32_t width_uv; + uint32_t height_uv; + uint32_t *xcoords_y; + uint32_t *ycoords_y; + uint32_t *xcoords_uv; + uint32_t *ycoords_uv; +}; + +#ifdef CSS20 +struct atomisp_parameters { + struct atomisp_wb_config *wb_config; /* White Balance config */ + struct atomisp_cc_config *cc_config; /* Color Correction config */ + struct atomisp_tnr_config *tnr_config; /* Temporal Noise Reduction */ + struct atomisp_ecd_config *ecd_config; /* Eigen Color Demosaicing */ + struct atomisp_ynr_config *ynr_config; /* Y(Luma) Noise Reduction */ + struct atomisp_fc_config *fc_config; /* Fringe Control */ + struct atomisp_cnr_config *cnr_config; /* Chroma Noise Reduction */ + struct atomisp_macc_config *macc_config; /* MACC */ + struct atomisp_ctc_config *ctc_config; /* Chroma Tone Control */ + struct atomisp_aa_config *aa_config; /* Anti-Aliasing */ + struct atomisp_aa_config *baa_config; /* Anti-Aliasing */ + struct atomisp_ce_config *ce_config; + struct atomisp_dvs_6axis_config *dvs_6axis_config; + struct atomisp_ob_config *ob_config; /* Objective Black config */ + struct atomisp_dp_config *dp_config; /* Dead Pixel config */ + struct atomisp_nr_config *nr_config; /* Noise Reduction config */ + struct atomisp_ee_config *ee_config; /* Edge Enhancement config */ + struct atomisp_de_config *de_config; /* Demosaic config */ + struct atomisp_gc_config *gc_config; /* Gamma Correction config */ + struct atomisp_anr_config *anr_config; /* Advanced Noise Reduction */ + struct atomisp_3a_config *a3a_config; /* 3A Statistics config */ + struct atomisp_xnr_config *xnr_config; /* eXtra Noise Reduction */ + struct atomisp_dz_config *dz_config; /* Digital Zoom */ + struct atomisp_cc_config *yuv2rgb_cc_config; /* Color + Correction config */ + struct atomisp_cc_config *rgb2yuv_cc_config; /* Color + Correction config */ + struct atomisp_macc_table *macc_table; + struct atomisp_gamma_table *gamma_table; + struct atomisp_ctc_table *ctc_table; + struct atomisp_xnr_table *xnr_table; + struct atomisp_rgb_gamma_table *r_gamma_table; + struct atomisp_rgb_gamma_table *g_gamma_table; + struct atomisp_rgb_gamma_table *b_gamma_table; + struct atomisp_vector *motion_vector; /* For 2-axis DVS */ + struct atomisp_shading_table *shading_table; + struct atomisp_morph_table *morph_table; + struct atomisp_dvs_coefficients *dvs_coefs; /* DVS 1.0 coefficients */ + struct atomisp_dvs2_coefficients *dvs2_coefs; /* DVS 2.0 coefficients */ + struct atomisp_capture_config *capture_config; + struct atomisp_anr_thres *anr_thres; +}; +#else /* CSS20 */ +struct atomisp_parameters { + struct atomisp_wb_config *wb_config; + struct atomisp_cc_config *cc_config; + struct atomisp_ob_config *ob_config; + struct atomisp_de_config *de_config; + struct atomisp_ce_config *ce_config; + struct atomisp_dp_config *dp_config; + struct atomisp_nr_config *nr_config; + struct atomisp_ee_config *ee_config; + struct atomisp_tnr_config *tnr_config; + struct atomisp_shading_table *shading_table; + struct atomisp_morph_table *morph_table; + struct atomisp_macc_config *macc_config; + struct atomisp_gamma_table *gamma_table; + struct atomisp_ctc_table *ctc_table; + struct atomisp_xnr_config *xnr_config; + struct atomisp_gc_config *gc_config; + struct atomisp_3a_config *a3a_config; +}; +#endif /* CSS20 */ +#define ATOMISP_GAMMA_TABLE_SIZE 1024 +struct atomisp_gamma_table { + unsigned short data[ATOMISP_GAMMA_TABLE_SIZE]; +}; + +/* Morphing table for advanced ISP. + * Each line of width elements takes up COORD_TABLE_EXT_WIDTH elements + * in memory. + */ +#define ATOMISP_MORPH_TABLE_NUM_PLANES 6 +struct atomisp_morph_table { +#ifdef CSS20 + unsigned int enabled; +#endif + unsigned int height; + unsigned int width; /* number of valid elements per line */ + unsigned short __user *coordinates_x[ATOMISP_MORPH_TABLE_NUM_PLANES]; + unsigned short __user *coordinates_y[ATOMISP_MORPH_TABLE_NUM_PLANES]; +}; + +#define ATOMISP_NUM_SC_COLORS 4 +#define ATOMISP_SC_FLAG_QUERY (1 << 0) + +#ifdef CSS20 +struct atomisp_shading_table { + __u32 enable; + + __u32 sensor_width; + __u32 sensor_height; + __u32 width; + __u32 height; + __u32 fraction_bits; + + __u16 *data[ATOMISP_NUM_SC_COLORS]; +}; +#else /* CSS20 */ +struct atomisp_shading_table { + /* + * If flag ATOMISP_SC_FLAG_QUERY is set, IOCTL will only query current + * LSC status and return, otherwise it will set LSC according to + * userspace's input. + */ + __u8 flags; + /* + * If ATOMISP_SC_FLAG_QUERY is set, enable is output parameter, + * otherwise it is an input parameter and will enable/disable LSC + * engine + */ + __u8 enable; + /* native sensor resolution */ + __u32 sensor_width; + __u32 sensor_height; + /* number of data points per line per color (bayer quads) */ + __u32 width; + /* number of lines of data points per color (bayer quads) */ + __u32 height; + /* bits of fraction part for shading table values */ + __u32 fraction_bits; + /* one table for each color (use sh_css_sc_color to index) */ + __u16 __user *data[ATOMISP_NUM_SC_COLORS]; +}; +#endif /* CSS20 */ + +struct atomisp_makernote_info { + /* bits 31-16: numerator, bits 15-0: denominator */ + unsigned int focal_length; + /* bits 31-16: numerator, bits 15-0: denominator*/ + unsigned int f_number_curr; + /* + * bits 31-24: max f-number numerator + * bits 23-16: max f-number denominator + * bits 15-8: min f-number numerator + * bits 7-0: min f-number denominator + */ + unsigned int f_number_range; +}; + +/* parameter for MACC */ +#define ATOMISP_NUM_MACC_AXES 16 +struct atomisp_macc_table { + short data[4 * ATOMISP_NUM_MACC_AXES]; +}; + +struct atomisp_macc_config { + int color_effect; + struct atomisp_macc_table table; +}; + +/* Parameter for ctc parameter control */ +#define ATOMISP_CTC_TABLE_SIZE 1024 +struct atomisp_ctc_table { + unsigned short data[ATOMISP_CTC_TABLE_SIZE]; +}; + +/* Parameter for overlay image loading */ +struct atomisp_overlay { + /* the frame containing the overlay data The overlay frame width should + * be the multiples of 2*ISP_VEC_NELEMS. The overlay frame height + * should be the multiples of 2. + */ + struct v4l2_framebuffer *frame; + /* Y value of overlay background */ + unsigned char bg_y; + /* U value of overlay background */ + char bg_u; + /* V value of overlay background */ + char bg_v; + /* the blending percent of input data for Y subpixels */ + unsigned char blend_input_perc_y; + /* the blending percent of input data for U subpixels */ + unsigned char blend_input_perc_u; + /* the blending percent of input data for V subpixels */ + unsigned char blend_input_perc_v; + /* the blending percent of overlay data for Y subpixels */ + unsigned char blend_overlay_perc_y; + /* the blending percent of overlay data for U subpixels */ + unsigned char blend_overlay_perc_u; + /* the blending percent of overlay data for V subpixels */ + unsigned char blend_overlay_perc_v; + /* the overlay start x pixel position on output frame It should be the + multiples of 2*ISP_VEC_NELEMS. */ + unsigned int overlay_start_x; + /* the overlay start y pixel position on output frame It should be the + multiples of 2. */ + unsigned int overlay_start_y; +}; + +/* Sensor resolution specific data for AE calculation.*/ +struct atomisp_sensor_mode_data { + unsigned int coarse_integration_time_min; + unsigned int coarse_integration_time_max_margin; + unsigned int fine_integration_time_min; + unsigned int fine_integration_time_max_margin; + unsigned int fine_integration_time_def; + unsigned int frame_length_lines; + unsigned int line_length_pck; + unsigned int read_mode; + unsigned int vt_pix_clk_freq_mhz; + unsigned int crop_horizontal_start; /* Sensor crop start cord. (x0,y0)*/ + unsigned int crop_vertical_start; + unsigned int crop_horizontal_end; /* Sensor crop end cord. (x1,y1)*/ + unsigned int crop_vertical_end; + unsigned int output_width; /* input size to ISP after binning/scaling */ + unsigned int output_height; + uint8_t binning_factor_x; /* horizontal binning factor used */ + uint8_t binning_factor_y; /* vertical binning factor used */ + uint8_t reserved[2]; +}; + +struct atomisp_exposure { + unsigned int integration_time[8]; + unsigned int shutter_speed[8]; + unsigned int gain[4]; + unsigned int aperture; +}; + +/* For texture streaming. */ +struct atomisp_bc_video_package { + int ioctl_cmd; + int device_id; + int inputparam; + int outputparam; +}; + +enum atomisp_focus_hp { + ATOMISP_FOCUS_HP_IN_PROGRESS = (1U << 2), + ATOMISP_FOCUS_HP_COMPLETE = (2U << 2), + ATOMISP_FOCUS_HP_FAILED = (3U << 2) +}; + +/* Masks */ +#define ATOMISP_FOCUS_STATUS_MOVING (1U << 0) +#define ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE (1U << 1) +#define ATOMISP_FOCUS_STATUS_HOME_POSITION (3U << 2) + +enum atomisp_camera_port { + ATOMISP_CAMERA_PORT_SECONDARY, + ATOMISP_CAMERA_PORT_PRIMARY, + ATOMISP_CAMERA_PORT_TERTIARY, + ATOMISP_CAMERA_NR_PORTS +}; + +/* Flash modes. Default is off. + * Setting a flash to TORCH or INDICATOR mode will automatically + * turn it on. Setting it to FLASH mode will not turn on the flash + * until the FLASH_STROBE command is sent. */ +enum atomisp_flash_mode { + ATOMISP_FLASH_MODE_OFF, + ATOMISP_FLASH_MODE_FLASH, + ATOMISP_FLASH_MODE_TORCH, + ATOMISP_FLASH_MODE_INDICATOR, +}; + +/* Flash statuses, used by atomisp driver to check before starting + * flash and after having started flash. */ +enum atomisp_flash_status { + ATOMISP_FLASH_STATUS_OK, + ATOMISP_FLASH_STATUS_HW_ERROR, + ATOMISP_FLASH_STATUS_INTERRUPTED, + ATOMISP_FLASH_STATUS_TIMEOUT, +}; + +/* Frame status. This is used to detect corrupted frames and flash + * exposed frames. Usually, the first 2 frames coming out of the sensor + * are corrupted. When using flash, the frame before and the frame after + * the flash exposed frame may be partially exposed by flash. The ISP + * statistics for these frames should not be used by the 3A library. + * The frame status value can be found in the "reserved" field in the + * v4l2_buffer struct. */ +enum atomisp_frame_status { + ATOMISP_FRAME_STATUS_OK, + ATOMISP_FRAME_STATUS_CORRUPTED, + ATOMISP_FRAME_STATUS_FLASH_EXPOSED, + ATOMISP_FRAME_STATUS_FLASH_PARTIAL, + ATOMISP_FRAME_STATUS_FLASH_FAILED, +}; + +enum atomisp_acc_type { + ATOMISP_ACC_STANDALONE, /* Stand-alone acceleration */ + ATOMISP_ACC_OUTPUT, /* Accelerator stage on output frame */ + ATOMISP_ACC_VIEWFINDER /* Accelerator stage on viewfinder frame */ +}; + +enum atomisp_acc_arg_type { + ATOMISP_ACC_ARG_SCALAR_IN, /* Scalar input argument */ + ATOMISP_ACC_ARG_SCALAR_OUT, /* Scalar output argument */ + ATOMISP_ACC_ARG_SCALAR_IO, /* Scalar in/output argument */ + ATOMISP_ACC_ARG_PTR_IN, /* Pointer input argument */ + ATOMISP_ACC_ARG_PTR_OUT, /* Pointer output argument */ + ATOMISP_ACC_ARG_PTR_IO, /* Pointer in/output argument */ + ATOMISP_ARG_PTR_NOFLUSH, /* Pointer argument will not be flushed */ + ATOMISP_ARG_PTR_STABLE, /* Pointer input argument that is stable */ + ATOMISP_ACC_ARG_FRAME /* Frame argument */ +}; + +#if defined(ISP2400) || defined(ISP2400B0) +/** ISP memories, isp2400 */ +enum atomisp_acc_memory { + ATOMISP_ACC_MEMORY_PMEM0 = 0, + ATOMISP_ACC_MEMORY_DMEM0, + ATOMISP_ACC_MEMORY_VMEM0, + ATOMISP_ACC_MEMORY_VAMEM0, + ATOMISP_ACC_MEMORY_VAMEM1, + ATOMISP_ACC_MEMORY_VAMEM2, + ATOMISP_ACC_MEMORY_HMEM0, + ATOMISP_ACC_NR_MEMORY +}; +#else /* defined(ISP2400) || defined(ISP2400B0) */ +/** ISP memories, isp2300 */ +enum atomisp_acc_memory { + ATOMISP_ACC_MEMORY_PMEM = 0, + ATOMISP_ACC_MEMORY_DMEM, + ATOMISP_ACC_MEMORY_VMEM, + ATOMISP_ACC_MEMORY_VAMEM1, + ATOMISP_ACC_MEMORY_VAMEM2, + ATOMISP_ACC_NR_MEMORY /* Must be last */ +}; +#endif /* defined(ISP2400) || defined(ISP2400B0) */ + +struct atomisp_sp_arg { + enum atomisp_acc_arg_type type; /* Type of SP argument */ + void *value; /* Value of SP argument */ + unsigned int size; /* Size of SP argument */ +}; + +/* Acceleration API */ + +/* For CSS 1.0 only */ +struct atomisp_acc_fw_arg { + unsigned int fw_handle; + unsigned int index; + void __user *value; + size_t size; +}; + +/* + * Set arguments after first mapping with ATOMISP_IOC_ACC_S_MAPPED_ARG. + * For CSS 1.5 only. + */ +struct atomisp_acc_s_mapped_arg { + unsigned int fw_handle; + __u32 memory; /* one of enum atomisp_acc_memory */ + size_t length; + unsigned long css_ptr; +}; + +struct atomisp_acc_fw_abort { + unsigned int fw_handle; + /* Timeout in us */ + unsigned int timeout; +}; + +struct atomisp_acc_fw_load { + unsigned int size; + unsigned int fw_handle; + void __user *data; +}; + +/* + * Load firmware to specified pipeline. + * For CSS 1.5 only. + */ +struct atomisp_acc_fw_load_to_pipe { + __u32 flags; /* Flags, see below for valid values */ + unsigned int fw_handle; /* Handle, filled by kernel. */ + __u32 size; /* Firmware binary size */ + void __user *data; /* Pointer to firmware */ + __u32 type; /* Binary type */ + __u32 reserved[3]; /* Set to zero */ +}; + +#define ATOMISP_ACC_FW_LOAD_FL_PREVIEW (1 << 0) +#define ATOMISP_ACC_FW_LOAD_FL_COPY (1 << 1) +#define ATOMISP_ACC_FW_LOAD_FL_VIDEO (1 << 2) +#define ATOMISP_ACC_FW_LOAD_FL_CAPTURE (1 << 3) +#define ATOMISP_ACC_FW_LOAD_FL_ACC (1 << 4) + +#define ATOMISP_ACC_FW_LOAD_TYPE_NONE 0 /* Normal binary: don't use */ +#define ATOMISP_ACC_FW_LOAD_TYPE_OUTPUT 1 /* Stage on output */ +#define ATOMISP_ACC_FW_LOAD_TYPE_VIEWFINDER 2 /* Stage on viewfinder */ +#define ATOMISP_ACC_FW_LOAD_TYPE_STANDALONE 3 /* Stand-alone acceleration */ + +struct atomisp_acc_map { + __u32 flags; /* Flags, see list below */ + __u32 length; /* Length of data in bytes */ + void __user *user_ptr; /* Pointer into user space */ + unsigned long css_ptr; /* Pointer into CSS address space */ + __u32 reserved[4]; /* Set to zero */ +}; + +#define ATOMISP_MAP_FLAG_NOFLUSH 0x0001 /* Do not flush cache */ + +/* + * V4L2 private internal data interface. + * ----------------------------------------------------------------------------- + * struct v4l2_private_int_data - request private data stored in video device + * internal memory. + * @size: sanity check to ensure userspace's buffer fits whole private data. + * If not, kernel will make partial copy (or nothing if @size == 0). + * @size is always corrected for the minimum necessary if IOCTL returns + * no error. + * @data: pointer to userspace buffer. + */ +struct v4l2_private_int_data { + __u32 size; + void __user *data; + __u32 reserved[2]; +}; + +/*Private IOCTLs for ISP */ +#define ATOMISP_IOC_G_XNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 0, int) +#define ATOMISP_IOC_S_XNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 1, int) +#define ATOMISP_IOC_G_NR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct atomisp_nr_config) +#define ATOMISP_IOC_S_NR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_nr_config) +#define ATOMISP_IOC_G_TNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct atomisp_tnr_config) +#define ATOMISP_IOC_S_TNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct atomisp_tnr_config) +#define ATOMISP_IOC_G_HISTOGRAM \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_histogram) +#define ATOMISP_IOC_S_HISTOGRAM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 7, struct atomisp_histogram) +#define ATOMISP_IOC_G_BLACK_LEVEL_COMP \ + _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct atomisp_ob_config) +#define ATOMISP_IOC_S_BLACK_LEVEL_COMP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct atomisp_ob_config) +#define ATOMISP_IOC_G_EE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct atomisp_ee_config) +#define ATOMISP_IOC_S_EE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct atomisp_ee_config) +/* Digital Image Stabilization: + * 1. get dis statistics: reads DIS statistics from ISP (every frame) + * 2. set dis coefficients: set DIS filter coefficients (one time) + * 3. set dis motion vecotr: set motion vector (result of DIS, every frame) + */ +#define ATOMISP_IOC_G_DIS_STAT \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 14, struct atomisp_dis_statistics) +#define ATOMISP_IOC_S_DIS_COEFS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct atomisp_dis_coefficients) + +#ifdef CSS20 +#define ATOMISP_IOC_S_DIS_VECTOR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_dvs_6axis_config) +#else +#define ATOMISP_IOC_S_DIS_VECTOR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_dis_vector) +#endif + +#define ATOMISP_IOC_G_3A_STAT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 17, struct atomisp_3a_statistics) +#define ATOMISP_IOC_G_ISP_PARM \ + _IOR('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_parm) +#define ATOMISP_IOC_S_ISP_PARM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 19, struct atomisp_parm) +#define ATOMISP_IOC_G_ISP_GAMMA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 20, struct atomisp_gamma_table) +#define ATOMISP_IOC_S_ISP_GAMMA \ + _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_gamma_table) +#define ATOMISP_IOC_G_ISP_GDC_TAB \ + _IOR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_morph_table) +#define ATOMISP_IOC_S_ISP_GDC_TAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_morph_table) +#define ATOMISP_IOC_ISP_MAKERNOTE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 24, struct atomisp_makernote_info) + +/* macc parameter control*/ +#define ATOMISP_IOC_G_ISP_MACC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 25, struct atomisp_macc_config) +#define ATOMISP_IOC_S_ISP_MACC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 26, struct atomisp_macc_config) + +/* Defect pixel detection & Correction */ +#define ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_dp_config) +#define ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_dp_config) + +/* False Color Correction */ +#define ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 29, struct atomisp_de_config) +#define ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_de_config) + +/* ctc parameter control */ +#define ATOMISP_IOC_G_ISP_CTC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 31, struct atomisp_ctc_table) +#define ATOMISP_IOC_S_ISP_CTC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_ctc_table) + +/* white balance Correction */ +#define ATOMISP_IOC_G_ISP_WHITE_BALANCE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 33, struct atomisp_wb_config) +#define ATOMISP_IOC_S_ISP_WHITE_BALANCE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_wb_config) + +/* fpn table loading */ +#define ATOMISP_IOC_S_ISP_FPN_TABLE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 35, struct v4l2_framebuffer) + +/* overlay image loading */ +#define ATOMISP_IOC_G_ISP_OVERLAY \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 36, struct atomisp_overlay) +#define ATOMISP_IOC_S_ISP_OVERLAY \ + _IOW('v', BASE_VIDIOC_PRIVATE + 37, struct atomisp_overlay) + +/* bcd driver bridge */ +#define ATOMISP_IOC_CAMERA_BRIDGE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 38, struct atomisp_bc_video_package) + +/* Sensor resolution specific info for AE */ +#define ATOMISP_IOC_G_SENSOR_MODE_DATA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_sensor_mode_data) + +#define ATOMISP_IOC_S_EXPOSURE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_exposure) + +/* sensor calibration registers group */ +#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 41, struct atomisp_calibration_group) + +/* white balance Correction */ +#define ATOMISP_IOC_G_3A_CONFIG \ + _IOR('v', BASE_VIDIOC_PRIVATE + 42, struct atomisp_3a_config) +#define ATOMISP_IOC_S_3A_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_3a_config) + +/* Accelerate ioctls */ +#define ATOMISP_IOC_ACC_LOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 44, struct atomisp_acc_fw_load) + +#define ATOMISP_IOC_ACC_UNLOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 45, unsigned int) + +/* For CSS 1.0 only */ +#define ATOMISP_IOC_ACC_S_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 46, struct atomisp_acc_fw_arg) + +#define ATOMISP_IOC_ACC_START \ + _IOW('v', BASE_VIDIOC_PRIVATE + 47, unsigned int) + +#define ATOMISP_IOC_ACC_WAIT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 48, unsigned int) + +#define ATOMISP_IOC_ACC_ABORT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 49, struct atomisp_acc_fw_abort) + +/* sensor OTP memory read */ +#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 50, struct v4l2_private_int_data) + +/* LCS (shading) table write */ +#define ATOMISP_IOC_S_ISP_SHD_TAB \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 51, struct atomisp_shading_table) + +/* Gamma Correction */ +#define ATOMISP_IOC_G_ISP_GAMMA_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 52, struct atomisp_gc_config) + +#define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 53, struct atomisp_gc_config) + +#define ATOMISP_IOC_ACC_DESTAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 54, struct atomisp_acc_fw_arg) + +/* + * Reserved ioctls. We have customer implementing it internally. + * We can't use both numbers to not cause ABI conflict. + * Anyway, those ioctls are hacks and not implemented by us: + * + * #define ATOMISP_IOC_G_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 55, struct atomisp_sensor_regs) + * #define ATOMISP_IOC_S_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 56, struct atomisp_sensor_regs) + */ + +/* motor internal memory read */ +#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 57, struct v4l2_private_int_data) + +/* + * Ioctls to map and unmap user buffers to CSS address space for acceleration. + * User fills fields length and user_ptr and sets other fields to zero, + * kernel may modify the flags and sets css_ptr. + */ +#define ATOMISP_IOC_ACC_MAP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 58, struct atomisp_acc_map) + +/* User fills fields length, user_ptr, and css_ptr and zeroes other fields. */ +#define ATOMISP_IOC_ACC_UNMAP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 59, struct atomisp_acc_map) + +#define ATOMISP_IOC_ACC_S_MAPPED_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 60, struct atomisp_acc_s_mapped_arg) + +#define ATOMISP_IOC_S_PARAMETERS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 61, struct atomisp_parameters) + +#define ATOMISP_IOC_S_CONT_CAPTURE_CONFIG \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 62, struct atomisp_cont_capture_conf) + +#define ATOMISP_IOC_ACC_LOAD_TO_PIPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 63, struct atomisp_acc_fw_load_to_pipe) + +/* ISP Private control IDs */ +#define V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION \ + (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC \ + (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_ATOMISP_VIDEO_STABLIZATION \ + (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_ATOMISP_FIXED_PATTERN_NR \ + (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION \ + (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_ATOMISP_LOW_LIGHT \ + (V4L2_CID_PRIVATE_BASE + 5) + +/* Camera class: + * Exposure, Flash and privacy (indicator) light controls, to be upstreamed */ +#define V4L2_CID_CAMERA_LASTP1 (V4L2_CID_CAMERA_CLASS_BASE + 1024) + +#define V4L2_CID_FOCAL_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 0) +#define V4L2_CID_FNUMBER_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 1) +#define V4L2_CID_FNUMBER_RANGE (V4L2_CID_CAMERA_LASTP1 + 2) + +/* Flash related CIDs, see also: + * http://linuxtv.org/downloads/v4l-dvb-apis/extended-controls.html\ + * #flash-controls */ + +/* Request a number of flash-exposed frames. The frame status can be + * found in the reserved field in the v4l2_buffer struct. */ +#define V4L2_CID_REQUEST_FLASH (V4L2_CID_CAMERA_LASTP1 + 3) +/* Query flash driver status. See enum atomisp_flash_status above. */ +#define V4L2_CID_FLASH_STATUS (V4L2_CID_CAMERA_LASTP1 + 5) +/* Set the flash mode (see enum atomisp_flash_mode) */ +#define V4L2_CID_FLASH_MODE (V4L2_CID_CAMERA_LASTP1 + 10) + +/* VCM slew control */ +#define V4L2_CID_VCM_SLEW (V4L2_CID_CAMERA_LASTP1 + 11) +/* VCM step time */ +#define V4L2_CID_VCM_TIMEING (V4L2_CID_CAMERA_LASTP1 + 12) + +/* Query Focus Status */ +#define V4L2_CID_FOCUS_STATUS (V4L2_CID_CAMERA_LASTP1 + 14) + +/* Query sensor's binning factor */ +#define V4L2_CID_BIN_FACTOR_HORZ (V4L2_CID_CAMERA_LASTP1 + 15) +#define V4L2_CID_BIN_FACTOR_VERT (V4L2_CID_CAMERA_LASTP1 + 16) + +/* number of frames to skip at stream start */ +#define V4L2_CID_G_SKIP_FRAMES (V4L2_CID_CAMERA_LASTP1 + 17) + +/* Query sensor's 2A status */ +#define V4L2_CID_2A_STATUS (V4L2_CID_CAMERA_LASTP1 + 18) +#define V4L2_2A_STATUS_AE_READY (1 << 0) +#define V4L2_2A_STATUS_AWB_READY (1 << 1) + +#define V4L2_CID_FMT_AUTO (V4L2_CID_CAMERA_LASTP1 + 19) + +#define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20) +#define ATOMISP_RUN_MODE_VIDEO 1 +#define ATOMISP_RUN_MODE_STILL_CAPTURE 2 +#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3 +#define ATOMISP_RUN_MODE_PREVIEW 4 +#define ATOMISP_RUN_MODE_SDV 5 + +#define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21) +#define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22) +#define V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE \ + (V4L2_CID_CAMERA_LASTP1 + 23) +#define V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER \ + (V4L2_CID_CAMERA_LASTP1 + 24) + +#define V4L2_CID_VFPP (V4L2_CID_CAMERA_LASTP1 + 25) +#define ATOMISP_VFPP_ENABLE 0 +#define ATOMISP_VFPP_DISABLE_SCALER 1 +#define ATOMISP_VFPP_DISABLE_LOWLAT 2 + +#define V4L2_BUF_FLAG_BUFFER_INVALID 0x0400 +#define V4L2_BUF_FLAG_BUFFER_VALID 0x0800 + +#define V4L2_BUF_TYPE_VIDEO_CAPTURE_ION (V4L2_BUF_TYPE_PRIVATE + 1024) + +#define V4L2_EVENT_ATOMISP_3A_STATS_READY (V4L2_EVENT_PRIVATE_START + 1) + +/* Nonstandard color effects for V4L2_CID_COLORFX */ +enum { + V4L2_COLORFX_SKIN_WHITEN_LOW = 1001, + V4L2_COLORFX_SKIN_WHITEN_HIGH = 1002, +}; + +#endif /* _ATOM_ISP_H */ diff --git a/include/linux/atomisp_platform.h b/include/linux/atomisp_platform.h new file mode 100644 index 000000000..3c34d298f --- /dev/null +++ b/include/linux/atomisp_platform.h @@ -0,0 +1,224 @@ +/* + * Support for Medifield PNW Camera Imaging ISP subsystem. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#ifdef CSS15 +#include +#else +#ifndef ATOMISP_PLATFORM_H_ +#define ATOMISP_PLATFORM_H_ + +#include +#include +#include +#include "atomisp.h" + +#define MAX_SENSORS_PER_PORT 4 +#define MAX_STREAMS_PER_CHANNEL 2 + +enum atomisp_bayer_order { + atomisp_bayer_order_grbg, + atomisp_bayer_order_rggb, + atomisp_bayer_order_bggr, + atomisp_bayer_order_gbrg +}; + +enum atomisp_input_stream_id { + ATOMISP_INPUT_STREAM_GENERAL = 0, + ATOMISP_INPUT_STREAM_CAPTURE = 0, + ATOMISP_INPUT_STREAM_POSTVIEW, + ATOMISP_INPUT_STREAM_PREVIEW, + ATOMISP_INPUT_STREAM_VIDEO, + ATOMISP_INPUT_STREAM_NUM +}; + +enum atomisp_input_format { + ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY,/* 8 bits per subpixel (legacy) */ + ATOMISP_INPUT_FORMAT_YUV420_8, /* 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV420_10,/* 10 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV420_16,/* 16 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV422_8, /* UYVY..UVYV, 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV422_10,/* UYVY..UVYV, 10 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV422_16,/* UYVY..UVYV, 16 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_444, /* BGR..BGR, 4 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_555, /* BGR..BGR, 5 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_565, /* BGR..BGR, 5 bits B and R, 6 bits G */ + ATOMISP_INPUT_FORMAT_RGB_666, /* BGR..BGR, 6 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_888, /* BGR..BGR, 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RAW_6, /* RAW data, 6 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_7, /* RAW data, 7 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_8, /* RAW data, 8 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_10, /* RAW data, 10 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_12, /* RAW data, 12 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_14, /* RAW data, 14 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_16, /* RAW data, 16 bits per pixel */ + ATOMISP_INPUT_FORMAT_BINARY_8, /* Binary byte stream. */ + + /* CSI2-MIPI specific format: Generic short packet data. It is used to + * keep the timing information for the opening/closing of shutters, + * triggering of flashes and etc. + */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT1, /* Generic Short Packet Code 1 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT2, /* Generic Short Packet Code 2 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT3, /* Generic Short Packet Code 3 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT4, /* Generic Short Packet Code 4 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT5, /* Generic Short Packet Code 5 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT6, /* Generic Short Packet Code 6 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT7, /* Generic Short Packet Code 7 */ + ATOMISP_INPUT_FORMAT_GENERIC_SHORT8, /* Generic Short Packet Code 8 */ + + /* CSI2-MIPI specific format: YUV data. + */ + ATOMISP_INPUT_FORMAT_YUV420_8_SHIFT, /* YUV420 8-bit (Chroma Shifted + Pixel Sampling) */ + ATOMISP_INPUT_FORMAT_YUV420_10_SHIFT, /* YUV420 8-bit (Chroma Shifted + Pixel Sampling) */ + + /* CSI2-MIPI specific format: Generic long packet data + */ + ATOMISP_INPUT_FORMAT_EMBEDDED, /* Embedded 8-bit non Image Data */ + + /* CSI2-MIPI specific format: User defined byte-based data. For example, + * the data transmitter (e.g. the SoC sensor) can keep the JPEG data as + * the User Defined Data Type 4 and the MPEG data as the + * User Defined Data Type 7. + */ + ATOMISP_INPUT_FORMAT_USER_DEF1, /* User defined 8-bit data type 1 */ + ATOMISP_INPUT_FORMAT_USER_DEF2, /* User defined 8-bit data type 2 */ + ATOMISP_INPUT_FORMAT_USER_DEF3, /* User defined 8-bit data type 3 */ + ATOMISP_INPUT_FORMAT_USER_DEF4, /* User defined 8-bit data type 4 */ + ATOMISP_INPUT_FORMAT_USER_DEF5, /* User defined 8-bit data type 5 */ + ATOMISP_INPUT_FORMAT_USER_DEF6, /* User defined 8-bit data type 6 */ + ATOMISP_INPUT_FORMAT_USER_DEF7, /* User defined 8-bit data type 7 */ + ATOMISP_INPUT_FORMAT_USER_DEF8, /* User defined 8-bit data type 8 */ +}; + +enum intel_v4l2_subdev_type { + RAW_CAMERA = 1, + SOC_CAMERA = 2, + CAMERA_MOTOR = 3, + LED_FLASH = 4, + XENON_FLASH = 5, + FILE_INPUT = 6, + TEST_PATTERN = 7, +}; + +struct intel_v4l2_subdev_id { + char name[17]; + enum intel_v4l2_subdev_type type; + enum atomisp_camera_port port; +}; + +struct intel_v4l2_subdev_i2c_board_info { + struct i2c_board_info board_info; + int i2c_adapter_id; +}; + +struct intel_v4l2_subdev_table { + struct intel_v4l2_subdev_i2c_board_info v4l2_subdev; + enum intel_v4l2_subdev_type type; + enum atomisp_camera_port port; +}; + +struct atomisp_platform_data { + struct intel_v4l2_subdev_table *subdevs; + const struct soft_platform_id *spid; +}; + +/* Describe the capacities of one single sensor. */ +struct atomisp_sensor_caps { + /* The number of streams this sensor can output. */ + int stream_num; + bool is_slave; +}; + +/* Describe the capacities of sensors connected to one camera port. */ +struct atomisp_camera_caps { + /* The number of sensors connected to this camera port. */ + int sensor_num; + /* The capacities of each sensor. */ + struct atomisp_sensor_caps sensor[MAX_SENSORS_PER_PORT]; + /* Define whether stream control is required for multiple streams. */ + bool multi_stream_ctrl; +}; + +/* + * Sensor of external ISP can send multiple steams with different mipi data + * type in the same virtual channel. This information needs to come from the + * sensor or external ISP + */ +struct atomisp_isys_config_info { + u8 input_format; + u16 width; + u16 height; +}; + +struct atomisp_input_stream_info { + enum atomisp_input_stream_id stream; + u8 enable; + /* Sensor driver fills ch_id with the id + of the virtual channel. */ + u8 ch_id; + /* Tells how many streams in this virtual channel. If 0 ignore rest + * and the input format will be from mipi_info */ + u8 isys_configs; + /* + * if more isys_configs is more than 0, sensor needs to configure the + * input format differently. width and height can be 0. If width and + * height is not zero, then the corresponsing data needs to be set + */ + struct atomisp_isys_config_info isys_info[MAX_STREAMS_PER_CHANNEL]; +}; + +struct camera_sensor_platform_data { + int (*gpio_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*flisclk_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*power_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*csi_cfg)(struct v4l2_subdev *subdev, int flag); + bool (*low_fps)(void); + int (*platform_init)(struct i2c_client *); + int (*platform_deinit)(void); + char *(*msr_file_name)(void); + struct atomisp_camera_caps *(*get_camera_caps)(void); + int (*gpio_intr_ctrl)(struct v4l2_subdev *subdev); +}; + +struct camera_af_platform_data { + int (*power_ctrl)(struct v4l2_subdev *subdev, int flag); +}; + +const struct camera_af_platform_data *camera_get_af_platform_data(void); + +struct camera_mipi_info { + enum atomisp_camera_port port; + unsigned int num_lanes; + enum atomisp_input_format input_format; + enum atomisp_bayer_order raw_bayer_order; + struct atomisp_sensor_mode_data data; + enum atomisp_input_format metadata_format; + uint32_t metadata_width; + uint32_t metadata_height; + const uint32_t *metadata_effective_width; +}; + +extern const struct atomisp_platform_data *atomisp_get_platform_data(void); +extern const struct atomisp_camera_caps *atomisp_get_default_camera_caps(void); + +#endif /* ATOMISP_PLATFORM_H_ */ +#endif diff --git a/include/linux/atomisp_platform_css15.h b/include/linux/atomisp_platform_css15.h new file mode 100644 index 000000000..3588cf167 --- /dev/null +++ b/include/linux/atomisp_platform_css15.h @@ -0,0 +1,151 @@ +/* + * Support for Medifield PNW Camera Imaging ISP subsystem. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#ifndef ATOMISP_PLATFORM_CSS15_H_ +#define ATOMISP_PLATFORM_CSS15_H_ + +#include +#include +#include +#include "atomisp.h" + +#define MAX_SENSORS_PER_PORT 4 + +enum atomisp_bayer_order { + atomisp_bayer_order_grbg, + atomisp_bayer_order_rggb, + atomisp_bayer_order_bggr, + atomisp_bayer_order_gbrg +}; + +enum atomisp_input_stream_id { + ATOMISP_INPUT_STREAM_GENERAL = 0, + ATOMISP_INPUT_STREAM_CAPTURE = 0, + ATOMISP_INPUT_STREAM_POSTVIEW, + ATOMISP_INPUT_STREAM_PREVIEW, + ATOMISP_INPUT_STREAM_VIDEO, + ATOMISP_INPUT_STREAM_NUM +}; + +enum atomisp_input_format { + ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY,/* 8 bits per subpixel (legacy) */ + ATOMISP_INPUT_FORMAT_YUV420_8, /* 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV420_10,/* 10 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV422_8, /* UYVY..UVYV, 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_YUV422_10,/* UYVY..UVYV, 10 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_444, /* BGR..BGR, 4 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_555, /* BGR..BGR, 5 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_565, /* BGR..BGR, 5 bits B and $, 6 bits G */ + ATOMISP_INPUT_FORMAT_RGB_666, /* BGR..BGR, 6 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RGB_888, /* BGR..BGR, 8 bits per subpixel */ + ATOMISP_INPUT_FORMAT_RAW_6, /* RAW data, 6 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_7, /* RAW data, 7 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_8, /* RAW data, 8 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_10, /* RAW data, 10 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_12, /* RAW data, 12 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_14, /* RAW data, 14 bits per pixel */ + ATOMISP_INPUT_FORMAT_RAW_16, /* RAW data, 16 bits per pixel */ + ATOMISP_INPUT_FORMAT_BINARY_8, /* Binary byte stream. */ +}; + +enum intel_v4l2_subdev_type { + RAW_CAMERA = 1, + SOC_CAMERA = 2, + CAMERA_MOTOR = 3, + LED_FLASH = 4, + XENON_FLASH = 5, + FILE_INPUT = 6, + TEST_PATTERN = 7, +}; + +struct intel_v4l2_subdev_id { + char name[17]; + enum intel_v4l2_subdev_type type; + enum atomisp_camera_port port; +}; + +struct intel_v4l2_subdev_i2c_board_info { + struct i2c_board_info board_info; + int i2c_adapter_id; +}; + +struct intel_v4l2_subdev_table { + struct intel_v4l2_subdev_i2c_board_info v4l2_subdev; + enum intel_v4l2_subdev_type type; + enum atomisp_camera_port port; +}; + +struct atomisp_platform_data { + struct intel_v4l2_subdev_table *subdevs; + const struct soft_platform_id *spid; +}; + +/* Describe the capacities of one single sensor. */ +struct atomisp_sensor_caps { + /* The number of streams this sensor can output. */ + int stream_num; +}; + +/* Describe the capacities of sensors connected to one camera port. */ +struct atomisp_camera_caps { + /* The number of sensors connected to this camera port. */ + int sensor_num; + /* The capacities of each sensor. */ + struct atomisp_sensor_caps sensor[MAX_SENSORS_PER_PORT]; +}; + +struct atomisp_input_stream_info { + enum atomisp_input_stream_id stream; + unsigned int enable; + /* Sensor driver fills ch_id with the id + of the virtual channel. */ + unsigned int ch_id; +}; + +struct camera_sensor_platform_data { + int (*gpio_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*flisclk_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*power_ctrl)(struct v4l2_subdev *subdev, int flag); + int (*csi_cfg)(struct v4l2_subdev *subdev, int flag); + bool (*low_fps)(void); + int (*platform_init)(struct i2c_client *); + int (*platform_deinit)(void); + char *(*msr_file_name)(void); + struct atomisp_camera_caps *(*get_camera_caps)(void); +}; + +struct camera_af_platform_data { + int (*power_ctrl)(struct v4l2_subdev *subdev, int flag); +}; + +const struct camera_af_platform_data *camera_get_af_platform_data(void); + +struct camera_mipi_info { + enum atomisp_camera_port port; + unsigned int num_lanes; + enum atomisp_input_format input_format; + enum atomisp_bayer_order raw_bayer_order; + struct atomisp_sensor_mode_data data; +}; + +extern const struct atomisp_platform_data *atomisp_get_platform_data(void); +extern const struct atomisp_camera_caps *atomisp_get_default_camera_caps(void); + +#endif /* ATOMISP_PLATFORM_H_ */ diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h new file mode 100644 index 000000000..c259b36bf --- /dev/null +++ b/include/media/v4l2-chip-ident.h @@ -0,0 +1,352 @@ +/* + v4l2 chip identifiers header + + This header provides a list of chip identifiers that can be returned + through the VIDIOC_DBG_G_CHIP_IDENT ioctl. + + Copyright (C) 2007 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef V4L2_CHIP_IDENT_H_ +#define V4L2_CHIP_IDENT_H_ + +/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ + +/* KEEP THIS LIST ORDERED BY ID! + Otherwise it will be hard to see which ranges are already in use when + adding support to a new chip family. */ +enum { + /* general idents: reserved range 0-49 */ + V4L2_IDENT_NONE = 0, /* No chip matched */ + V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */ + V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */ + + /* module tvaudio: reserved range 50-99 */ + V4L2_IDENT_TVAUDIO = 50, /* A tvaudio chip, unknown which it is exactly */ + + /* Sony IMX074 */ + V4L2_IDENT_IMX074 = 74, + + /* module saa7110: just ident 100 */ + V4L2_IDENT_SAA7110 = 100, + + /* module saa7115: reserved range 101-149 */ + V4L2_IDENT_SAA7111 = 101, + V4L2_IDENT_SAA7111A = 102, + V4L2_IDENT_SAA7113 = 103, + V4L2_IDENT_SAA7114 = 104, + V4L2_IDENT_SAA7115 = 105, + V4L2_IDENT_SAA7118 = 108, + + /* module saa7127: reserved range 150-199 */ + V4L2_IDENT_SAA7127 = 157, + V4L2_IDENT_SAA7129 = 159, + + /* module cx25840: reserved range 200-249 */ + V4L2_IDENT_CX25836 = 236, + V4L2_IDENT_CX25837 = 237, + V4L2_IDENT_CX25840 = 240, + V4L2_IDENT_CX25841 = 241, + V4L2_IDENT_CX25842 = 242, + V4L2_IDENT_CX25843 = 243, + + /* OmniVision sensors: reserved range 250-299 */ + V4L2_IDENT_OV7670 = 250, + V4L2_IDENT_OV7720 = 251, + V4L2_IDENT_OV7725 = 252, + V4L2_IDENT_OV7660 = 253, + V4L2_IDENT_OV9650 = 254, + V4L2_IDENT_OV9655 = 255, + V4L2_IDENT_SOI968 = 256, + V4L2_IDENT_OV9640 = 257, + V4L2_IDENT_OV6650 = 258, + V4L2_IDENT_OV2640 = 259, + V4L2_IDENT_OV9740 = 260, + V4L2_IDENT_OV5642 = 261, + + /* module saa7146: reserved range 300-309 */ + V4L2_IDENT_SAA7146 = 300, + + /* Conexant MPEG encoder/decoders: reserved range 400-420 */ + V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ + V4L2_IDENT_CX23415 = 415, + V4L2_IDENT_CX23416 = 416, + V4L2_IDENT_CX23417 = 417, + V4L2_IDENT_CX23418 = 418, + + /* module bt819: reserved range 810-819 */ + V4L2_IDENT_BT815A = 815, + V4L2_IDENT_BT817A = 817, + V4L2_IDENT_BT819A = 819, + + /* module au0828 */ + V4L2_IDENT_AU0828 = 828, + + /* module bttv: ident 848 + 849 */ + V4L2_IDENT_BT848 = 848, + V4L2_IDENT_BT849 = 849, + + /* module bt856: just ident 856 */ + V4L2_IDENT_BT856 = 856, + + /* module bt866: just ident 866 */ + V4L2_IDENT_BT866 = 866, + + /* module bttv: ident 878 + 879 */ + V4L2_IDENT_BT878 = 878, + V4L2_IDENT_BT879 = 879, + + /* module ks0127: reserved range 1120-1129 */ + V4L2_IDENT_KS0122S = 1122, + V4L2_IDENT_KS0127 = 1127, + V4L2_IDENT_KS0127B = 1128, + + /* module indycam: just ident 2000 */ + V4L2_IDENT_INDYCAM = 2000, + + /* module vp27smpx: just ident 2700 */ + V4L2_IDENT_VP27SMPX = 2700, + + /* module vpx3220: reserved range: 3210-3229 */ + V4L2_IDENT_VPX3214C = 3214, + V4L2_IDENT_VPX3216B = 3216, + V4L2_IDENT_VPX3220A = 3220, + + /* VX855 just ident 3409 */ + /* Other via devs could use 3314, 3324, 3327, 3336, 3364, 3353 */ + V4L2_IDENT_VIA_VX855 = 3409, + + /* module tvp5150 */ + V4L2_IDENT_TVP5150 = 5150, + + /* module saa5246a: just ident 5246 */ + V4L2_IDENT_SAA5246A = 5246, + + /* module saa5249: just ident 5249 */ + V4L2_IDENT_SAA5249 = 5249, + + /* module cs5345: just ident 5345 */ + V4L2_IDENT_CS5345 = 5345, + + /* module tea6415c: just ident 6415 */ + V4L2_IDENT_TEA6415C = 6415, + + /* module tea6420: just ident 6420 */ + V4L2_IDENT_TEA6420 = 6420, + + /* module saa6588: just ident 6588 */ + V4L2_IDENT_SAA6588 = 6588, + + /* module vs6624: just ident 6624 */ + V4L2_IDENT_VS6624 = 6624, + + /* module saa6752hs: reserved range 6750-6759 */ + V4L2_IDENT_SAA6752HS = 6752, + V4L2_IDENT_SAA6752HS_AC3 = 6753, + + /* modules tef6862: just ident 6862 */ + V4L2_IDENT_TEF6862 = 6862, + + /* module tvp7002: just ident 7002 */ + V4L2_IDENT_TVP7002 = 7002, + + /* module adv7170: just ident 7170 */ + V4L2_IDENT_ADV7170 = 7170, + + /* module adv7175: just ident 7175 */ + V4L2_IDENT_ADV7175 = 7175, + + /* module adv7180: just ident 7180 */ + V4L2_IDENT_ADV7180 = 7180, + + /* module adv7183: just ident 7183 */ + V4L2_IDENT_ADV7183 = 7183, + + /* module saa7185: just ident 7185 */ + V4L2_IDENT_SAA7185 = 7185, + + /* module saa7191: just ident 7191 */ + V4L2_IDENT_SAA7191 = 7191, + + /* module ths7303: just ident 7303 */ + V4L2_IDENT_THS7303 = 7303, + + /* module adv7343: just ident 7343 */ + V4L2_IDENT_ADV7343 = 7343, + + /* module ths7353: just ident 7353 */ + V4L2_IDENT_THS7353 = 7353, + + /* module adv7393: just ident 7393 */ + V4L2_IDENT_ADV7393 = 7393, + + /* module adv7604: just ident 7604 */ + V4L2_IDENT_ADV7604 = 7604, + + /* module saa7706h: just ident 7706 */ + V4L2_IDENT_SAA7706H = 7706, + + /* module mt9v011, just ident 8243 */ + V4L2_IDENT_MT9V011 = 8243, + + /* module wm8739: just ident 8739 */ + V4L2_IDENT_WM8739 = 8739, + + /* module wm8775: just ident 8775 */ + V4L2_IDENT_WM8775 = 8775, + + /* Marvell controllers starting at 8801 */ + V4L2_IDENT_CAFE = 8801, + V4L2_IDENT_ARMADA610 = 8802, + + /* AKM AK8813/AK8814 */ + V4L2_IDENT_AK8813 = 8813, + V4L2_IDENT_AK8814 = 8814, + + /* module cx23885 and cx25840 */ + V4L2_IDENT_CX23885 = 8850, + V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */ + V4L2_IDENT_CX23887 = 8870, + V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */ + V4L2_IDENT_CX23888 = 8880, + V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ + V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ + + /* module ad9389b: just ident 9389 */ + V4L2_IDENT_AD9389B = 9389, + + /* module tda9840: just ident 9840 */ + V4L2_IDENT_TDA9840 = 9840, + + /* module tw9910: just ident 9910 */ + V4L2_IDENT_TW9910 = 9910, + + /* module sn9c20x: just ident 10000 */ + V4L2_IDENT_SN9C20X = 10000, + + /* module cx231xx and cx25840 */ + V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */ + V4L2_IDENT_CX23100 = 23100, + V4L2_IDENT_CX23101 = 23101, + V4L2_IDENT_CX23102 = 23102, + + /* module msp3400: reserved range 34000-34999 for msp34xx */ + V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only + use internally (tveeprom.c). */ + + V4L2_IDENT_MSP3400B = 34002, + V4L2_IDENT_MSP3400C = 34003, + V4L2_IDENT_MSP3400D = 34004, + V4L2_IDENT_MSP3400G = 34007, + V4L2_IDENT_MSP3401G = 34017, + V4L2_IDENT_MSP3402G = 34027, + V4L2_IDENT_MSP3405D = 34054, + V4L2_IDENT_MSP3405G = 34057, + V4L2_IDENT_MSP3407D = 34074, + V4L2_IDENT_MSP3407G = 34077, + + V4L2_IDENT_MSP3410B = 34102, + V4L2_IDENT_MSP3410C = 34103, + V4L2_IDENT_MSP3410D = 34104, + V4L2_IDENT_MSP3410G = 34107, + V4L2_IDENT_MSP3411G = 34117, + V4L2_IDENT_MSP3412G = 34127, + V4L2_IDENT_MSP3415D = 34154, + V4L2_IDENT_MSP3415G = 34157, + V4L2_IDENT_MSP3417D = 34174, + V4L2_IDENT_MSP3417G = 34177, + + V4L2_IDENT_MSP3420G = 34207, + V4L2_IDENT_MSP3421G = 34217, + V4L2_IDENT_MSP3422G = 34227, + V4L2_IDENT_MSP3425G = 34257, + V4L2_IDENT_MSP3427G = 34277, + + V4L2_IDENT_MSP3430G = 34307, + V4L2_IDENT_MSP3431G = 34317, + V4L2_IDENT_MSP3435G = 34357, + V4L2_IDENT_MSP3437G = 34377, + + V4L2_IDENT_MSP3440G = 34407, + V4L2_IDENT_MSP3441G = 34417, + V4L2_IDENT_MSP3442G = 34427, + V4L2_IDENT_MSP3445G = 34457, + V4L2_IDENT_MSP3447G = 34477, + + V4L2_IDENT_MSP3450G = 34507, + V4L2_IDENT_MSP3451G = 34517, + V4L2_IDENT_MSP3452G = 34527, + V4L2_IDENT_MSP3455G = 34557, + V4L2_IDENT_MSP3457G = 34577, + + V4L2_IDENT_MSP3460G = 34607, + V4L2_IDENT_MSP3461G = 34617, + V4L2_IDENT_MSP3465G = 34657, + V4L2_IDENT_MSP3467G = 34677, + + /* module msp3400: reserved range 44000-44999 for msp44xx */ + V4L2_IDENT_MSP4400G = 44007, + V4L2_IDENT_MSP4408G = 44087, + V4L2_IDENT_MSP4410G = 44107, + V4L2_IDENT_MSP4418G = 44187, + V4L2_IDENT_MSP4420G = 44207, + V4L2_IDENT_MSP4428G = 44287, + V4L2_IDENT_MSP4440G = 44407, + V4L2_IDENT_MSP4448G = 44487, + V4L2_IDENT_MSP4450G = 44507, + V4L2_IDENT_MSP4458G = 44587, + + /* Micron CMOS sensor chips: 45000-45099 */ + V4L2_IDENT_MT9M001C12ST = 45000, + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9M111 = 45007, + V4L2_IDENT_MT9M112 = 45008, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ + V4L2_IDENT_MT9T031 = 45020, + V4L2_IDENT_MT9T111 = 45021, + V4L2_IDENT_MT9T112 = 45022, + V4L2_IDENT_MT9V111 = 45031, + V4L2_IDENT_MT9V112 = 45032, + + /* HV7131R CMOS sensor: just ident 46000 */ + V4L2_IDENT_HV7131R = 46000, + + /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ + V4L2_IDENT_RJ54N1CB0C = 51980, + + /* module m52790: just ident 52790 */ + V4L2_IDENT_M52790 = 52790, + + /* module cs53132a: just ident 53132 */ + V4L2_IDENT_CS53l32A = 53132, + + /* modules upd61151 MPEG2 encoder: just ident 54000 */ + V4L2_IDENT_UPD61161 = 54000, + /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */ + V4L2_IDENT_UPD61162 = 54001, + + /* module upd64031a: just ident 64031 */ + V4L2_IDENT_UPD64031A = 64031, + + /* module upd64083: just ident 64083 */ + V4L2_IDENT_UPD64083 = 64083, + + /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */ +}; + +#endif