adding drivers for rear surface camera

This commit is contained in:
Jake Day 2017-08-16 11:24:50 -04:00 committed by Unknown
parent 9230acd105
commit 848b0c53fa
13 changed files with 9141 additions and 0 deletions

View file

@ -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

View file

@ -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

226
drivers/media/i2c/ad5823.c Normal file
View file

@ -0,0 +1,226 @@
#include <asm/intel-mid.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-device.h>
#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;
}

View file

@ -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 <linux/atomisp_platform.h>
#include <linux/types.h>
#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

2176
drivers/media/i2c/ov8865.c Normal file

File diff suppressed because it is too large Load diff

2723
drivers/media/i2c/ov8865.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -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. 5000LSC和AWB : 0x7030~0x70CB 0x70CF~0x716A
2. 3000LSC和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<tmp_len;i++) {
sum += tmp[i];
//OTP_LOG("data: %2x sum:%4x NO:%3d \n", tmp[i], sum, i);
}
sum = sum & 0xffff;
otp_sum = (ov8865_data_ptr[offset+len-2] << 8) + ov8865_data_ptr[offset+len-3];
OTP_LOG("sum:%x otp_sum:%x sum_read1:%x sum_read2:%x\n", sum, otp_sum, ov8865_data_ptr[offset+len-2], ov8865_data_ptr[offset+len-3]);
if(sum != otp_sum) {
OTP_LOG("%s %d overall checksum failed\n", __func__, __LINE__);
return -1;
}
OTP_LOG("all data sum check successfully!\n");
return 0;
}
static int ov8865_data_check(const unsigned char *ov8865_data_ptr, int ov8865_size)
{
int offset = 0;
int ret = 0;
/* check ov8865 module information table */
offset = OV8865_MODULE_INFORMATION_OFFSET;
ret = check_ov8865_Module_Information(ov8865_data_ptr,offset);
if(ret == -1)
return ret;
else
ov8865_data_group_pos.module_info = ret;/* record the valid position */
dump_ov8865_module_info(ov8865_data_ptr);
/* check ov8865 AWB and LSC of light source 1 table */
offset = OV8865_AWB_LSC_LIGHT_SOURCE_ONE_OFFSET;
ret = check_ov8865_AWB_LSC_light_source(ov8865_data_ptr,offset);
if(ret == -1)
return ret;
else
ov8865_data_group_pos.awb_lsc_light_source_one = ret;
/* check ov8865 AWB and LSC of light source 2 table */
offset = OV8865_AWB_LSC_LIGHT_SOURCE_TWO_OFFSET;
ret = check_ov8865_AWB_LSC_light_source(ov8865_data_ptr,offset);
if(ret == -1)
return ret;
else
ov8865_data_group_pos.awb_lsc_light_source_two = ret;
/* check ov8865 AF table */
if(check_ov8865_calibration_ver13(ov8865_data_ptr) == 1) {
offset = OV8865_AF_OFFSET_VER13;
OTP_LOG("This is ver1.3 calibration AF flag offset:%x\n", offset);
} else {
offset = OV8865_AF_OFFSET_NON_VER13;
OTP_LOG("This is not ver1.3 calibration AF flag offset:%x\n", offset);
}
ret = check_ov8865_AF(ov8865_data_ptr, offset);
if(ret == -1)
return ret;
else
ov8865_data_group_pos.af = ret;
ret = check_all_calibration_data(ov8865_data_ptr, ov8865_data_group_pos.awb_lsc_light_source_two, lsc_awb_light_src_two_group_addr[0].len);
if (ret == -1)
return ret;
return 0;
}
static ov8865_group_address_t module_info_group_addr[2] = {
{0x01, 0x0F},
{0x10, 0x0F},
};
static int check_ov8865_Module_Information(const unsigned char *ov8865_data_ptr, int offset)
{
unsigned char flag = ov8865_data_ptr[offset];
int i;
int ret;
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 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<len-1;i++) {
sum += ov8865_data_ptr[offset+i];
//OTP_LOG("i:%d data:%x sum:%x\n", i, ov8865_data_ptr[offset+i], sum);
}
sum = sum % 255 + 1;
if(sum != ov8865_data_ptr[offset+i]) {
OTP_LOG("sum:%x needed:%x\n", sum, ov8865_data_ptr[offset+i]);
return -1;
}
return 0;
}
static uint16_t get_nvm_checksum(const uint8_t *a_data_ptr, int32_t a_size)
{
uint16_t crc = 0;
int32_t i;
for (i = 0; i < a_size; i++)
{
uint8_t index = crc ^ a_data_ptr[i];
crc = (crc >> 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;
}

View file

@ -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 <stdio.h>
#include <stdint.h>
#include <string.h>
#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};

1330
include/linux/atomisp.h Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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 <linux/atomisp_platform_css15.h>
#else
#ifndef ATOMISP_PLATFORM_H_
#define ATOMISP_PLATFORM_H_
#include <linux/i2c.h>
#include <linux/sfi.h>
#include <media/v4l2-subdev.h>
#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

View file

@ -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 <linux/i2c.h>
#include <linux/sfi.h>
#include <media/v4l2-subdev.h>
#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_ */

View file

@ -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 <hverkuil@xs4all.nl>
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