Hi Xiaolin! The comments I make here also apply to all the other subdev drivers you posted. On Sunday 28 March 2010 09:47:28 Zhang, Xiaolin wrote: > From f09b86fb073db95eaeefb1e9ffb4e448e6359bd3 Mon Sep 17 00:00:00 2001 > From: Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx> > Date: Sun, 28 Mar 2010 14:01:01 +0800 > Subject: [PATCH 04/10] this patch is 2mp camera (ov2650) sensor subdev driver for intel moorestown camera imaging. > > Signed-off-by: Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx> > --- > drivers/media/video/mrstci/mrstov2650/Kconfig | 9 + > drivers/media/video/mrstci/mrstov2650/Makefile | 3 + > drivers/media/video/mrstci/mrstov2650/mrstov2650.c | 772 ++++++++++++++++++++ > drivers/media/video/mrstci/mrstov2650/ov2650.h | 717 ++++++++++++++++++ > 4 files changed, 1501 insertions(+), 0 deletions(-) > create mode 100644 drivers/media/video/mrstci/mrstov2650/Kconfig > create mode 100644 drivers/media/video/mrstci/mrstov2650/Makefile > create mode 100644 drivers/media/video/mrstci/mrstov2650/mrstov2650.c > create mode 100644 drivers/media/video/mrstci/mrstov2650/ov2650.h > > diff --git a/drivers/media/video/mrstci/mrstov2650/Kconfig b/drivers/media/video/mrstci/mrstov2650/Kconfig > new file mode 100644 > index 0000000..d39d894 > --- /dev/null > +++ b/drivers/media/video/mrstci/mrstov2650/Kconfig > @@ -0,0 +1,9 @@ > +config VIDEO_MRST_OV2650 > + tristate "Moorestown OV2650 SoC Sensor" > + depends on I2C && VIDEO_MRST_ISP These i2c devices are not an integral part of Moorestown, are they? These are i2c devices that can also be found in other products. So they should not depend on Moorestown and the drivers should be placed in drivers/media/video and any references to Moorestown should be removed. > + > + ---help--- > + Say Y here if your platform support OV2650 SoC Sensor. > + > + To compile this driver as a module, choose M here: the > + module will be called mrstov2650.ko. > diff --git a/drivers/media/video/mrstci/mrstov2650/Makefile b/drivers/media/video/mrstci/mrstov2650/Makefile > new file mode 100644 > index 0000000..fb16d57 > --- /dev/null > +++ b/drivers/media/video/mrstci/mrstov2650/Makefile > @@ -0,0 +1,3 @@ > +obj-$(CONFIG_VIDEO_MRST_OV2650) += mrstov2650.o > + > +EXTRA_CFLAGS += -I$(src)/../include > \ No newline at end of file > diff --git a/drivers/media/video/mrstci/mrstov2650/mrstov2650.c b/drivers/media/video/mrstci/mrstov2650/mrstov2650.c > new file mode 100644 > index 0000000..84aee57 > --- /dev/null > +++ b/drivers/media/video/mrstci/mrstov2650/mrstov2650.c > @@ -0,0 +1,772 @@ > +/* > + * Support for Moorestown Langwell Camera Imaging ISP subsystem. > + * > + * Copyright (c) 2009 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. > + * > + * > + * Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx> > + */ > + > +#include <linux/module.h> > +#include <linux/types.h> > +#include <linux/kernel.h> > +#include <linux/mm.h> > +#include <linux/string.h> > +#include <linux/errno.h> > +#include <linux/init.h> > +#include <linux/kmod.h> > +#include <linux/device.h> > +#include <linux/delay.h> > +#include <linux/fs.h> > +#include <linux/init.h> > +#include <linux/slab.h> > +#include <linux/delay.h> > +#include <linux/i2c.h> > +#include <linux/gpio.h> Please prune this list of includes. Things like delay, gpio, slab, fs and no doubt more are not needed. > +#include <linux/videodev2.h> > +#include <media/v4l2-device.h> > +#include <media/v4l2-chip-ident.h> > +#include <media/v4l2-i2c-drv.h> Don't use this header! It is for backwards compatibility of older i2c drivers and should not be used with modern drivers. See for example tvp514x.c on how to implement this without using v4l2-i2c-drv.h. > + > +#include "ci_sensor_common.h" > +#include "ov2650.h" > + > +static int mrstov2650_debug; > +module_param(mrstov2650_debug, int, 0644); > +MODULE_PARM_DESC(mrstov2650_debug, "Debug level (0-1)"); > + > +#define dprintk(level, fmt, arg...) do { \ > + if (mrstov2650_debug >= level) \ > + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \ > + __func__, ## arg); } \ > + while (0) > + > +#define eprintk(fmt, arg...) \ > + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \ > + __func__, __LINE__, ## arg); > + > +#define DBG_entering dprintk(2, "entering"); > +#define DBG_leaving dprintk(2, "leaving"); > +#define DBG_line dprintk(2, " line: %d", __LINE__); As mentioned in the comments in patch 0/10 I think debug constructions like this probably should just be removed. > + > +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd) > +{ > + return container_of(sd, struct ci_sensor_config, sd); > +} > + > +static struct ov2650_format_struct { > + __u8 *desc; > + __u32 pixelformat; > + struct regval_list *regs; > +} ov2650_formats[] = { > + { > + .desc = "YUYV 4:2:2", > + .pixelformat = SENSOR_MODE_BT601, Don't use Moorestown formats in a driver that can be used in other products as well. See also the comments made below on how to setup formats. > + .regs = NULL, > + }, > +}; > +#define N_OV2650_FMTS ARRAY_SIZE(ov2650_formats) > + > +static struct ov2650_res_struct { > + __u8 *desc; > + int res; > + int width; > + int height; > + int fps; > + bool used; > + struct regval_list *regs; > +} ov2650_res[] = { > + { > + .desc = "UXGA", > + .res = SENSOR_RES_UXGA, > + .width = 1600, > + .height = 1200, > + .fps = 15, > + .used = 0, > + .regs = ov2650_res_uxga, > + }, > + { > + .desc = "SXGA", > + .res = SENSOR_RES_SXGA, > + .width = 1280, > + .height = 1024, > + .fps = 15, > + .used = 0, > + .regs = ov2650_res_sxga, > + }, > + { > + .desc = "SVGA", > + .res = SENSOR_RES_SVGA, > + .width = 800, > + .height = 600, > + .fps = 15, > + .used = 0, > + .regs = ov2650_res_svga, > + }, > + { > + .desc = "VGA", > + .res = SENSOR_RES_VGA, > + .width = 640, > + .height = 480, > + .fps = 15, > + .used = 0, > + .regs = ov2650_res_vga_vario, > + }, > + { > + .desc = "QVGA", > + .res = SENSOR_RES_QVGA, > + .width = 320, > + .height = 240, > + .fps = 15, > + .used = 0, > + .regs = ov2650_res_qvga, > + }, > +}; > + > +#define N_RES (ARRAY_SIZE(ov2650_res)) > + > +static int ov2650_read(struct i2c_client *c, u16 reg, u8 *value) > +{ > + int ret; > + int i; > + struct i2c_msg msg[2]; > + u8 msgbuf[2]; > + u8 ret_val = 0; > + *value = 0; > + memset(&msg, 0, sizeof(msg)); > + msgbuf[0] = 0; > + msgbuf[1] = 0; > + i = 0; > + msgbuf[i++] = reg >> 8; > + msgbuf[i++] = reg; > + msg[0].addr = c->addr; > + msg[0].buf = msgbuf; > + msg[0].len = i; > + > + msg[1].addr = c->addr; > + msg[1].flags = I2C_M_RD; > + msg[1].buf = &ret_val; > + msg[1].len = 1; > + > + ret = i2c_transfer(c->adapter, &msg[0], 2); > + *value = ret_val; > + > + ret = (ret == 2) ? 0 : -1; > + return ret; > +} > + > +static int ov2650_write(struct i2c_client *c, u16 reg, u8 value) > +{ > + int ret, i; > + struct i2c_msg msg; > + u8 msgbuf[3]; > + > + memset(&msg, 0, sizeof(msg)); > + i = 0; > + msgbuf[i++] = reg >> 8; > + msgbuf[i++] = reg; > + msgbuf[i++] = value; > + > + msg.addr = c->addr; > + msg.flags = 0; > + msg.buf = msgbuf; > + msg.len = i; > + > + ret = i2c_transfer(c->adapter, &msg, 1); > + > + /* If this is a reset register, wait for 1ms */ > + if (reg == OV2650_SYS && (value & 0x80)) > + msleep(3); > + > + ret = (ret == 1) ? 0 : -1; > + return ret; > +} > + > +static int ov2650_write_array(struct i2c_client *c, struct regval_list *vals) > +{ > + struct regval_list *p; > + u8 read_val = 0; > + int err_num = 0; > + int i = 0; > + p = vals; > + while (p->reg_num != 0xffff) { > + ov2650_write(c, p->reg_num, p->value); > + ov2650_read(c, p->reg_num, &read_val); > + if (read_val != p->value) > + err_num++; > + p++; > + i++; > + } > + return 0; > +} > + > +static int ov2650_set_data_pin_in(struct i2c_client *client) > +{ > + int ret = 0; > + u8 reg; > + > + ret += ov2650_write(client, 0x30b0, 0x00); > + > + ret += ov2650_read(client, 0x30b1, ®); > + reg &= 0xfc; > + ret += ov2650_write(client, 0x30b1, reg); > + > + return ret; > +} > + > +static int ov2650_set_data_pin_out(struct i2c_client *client) > +{ > + int ret = 0; > + u8 reg; > + > + ret += ov2650_write(client, 0x30b0, 0xff); > + > + ret += ov2650_read(client, 0x30b1, ®); > + reg &= 0xfc; > + reg |= 0x03; > + ret += ov2650_write(client, 0x30b1, reg); > + > + return ret; > +} > + > +static int ov2650_wakeup(void) > +{ > + gpio_set_value(GPIO_STDBY_PIN, 0); This is not right. The Moorestown driver should do this. In a generic subdev driver you do not know how it is hooked up to the bridge driver and how it should be woken up. One option is to use the v4l2_device notify callback. See for example how that is used in bt819.c. > + return 0; > +} > + > +static int ov2650_init(struct i2c_client *c) > +{ > + int ret; > + struct v4l2_subdev *sd = i2c_get_clientdata(c); > + struct ci_sensor_config *info = to_sensor_config(sd); > + > + info->mode = ov2650_formats[0].pixelformat; > + info->res = ov2650_res[0].res; > + info->type = SENSOR_TYPE_SOC; > + info->bls = SENSOR_BLS_OFF; > + info->gamma = SENSOR_GAMMA_ON; > + info->cconv = SENSOR_CCONV_ON; > + info->blc = SENSOR_BLC_AUTO; > + info->agc = SENSOR_AGC_AUTO; > + info->awb = SENSOR_AWB_AUTO; > + info->aec = SENSOR_AEC_AUTO; > + info->bus_width = SENSOR_BUSWIDTH_8BIT_ZZ; > + info->ycseq = SENSOR_YCSEQ_YCBYCR; > + info->conv422 = SENSOR_CONV422_COSITED; > + info->bpat = SENSOR_BPAT_BGBGGRGR; > + info->field_inv = SENSOR_FIELDINV_NOSWAP; > + info->field_sel = SENSOR_FIELDSEL_BOTH; > + info->hpol = SENSOR_HPOL_REFPOS; > + info->vpol = SENSOR_VPOL_POS; > + info->edge = SENSOR_EDGE_RISING; > + info->flicker_freq = SENSOR_FLICKER_100; > + info->cie_profile = 0; This is the wrong way around. Remember, this ov2650 driver knows nothing about how it is connected to some bridge driver. So you cannot use Moorestown specific structs and defines here, otherwise this driver would be impossible to reuse in e.g. a USB webcam. The bridge driver (or platform driver in the case of Moorestown) is the only one that knows about which subdevs are hooked up and how they are hooked up. So typically the platform code will have to tell the main Moorestown v4l driver what is where and any other config data that is needed. If a sensor driver needs specific setup config data, then a sensor-specific header should be added in include/media. See for example include/media/mt9t112.h. > + memcpy(info->name, "ov2650", 7); Use strlcpy. > + > + ret = ov2650_write(c, OV2650_SYS, 0x80); > + ret += ov2650_write_array(c, ov2650_def_reg); > + > + ov2650_write(c, 0x3086, 0x0f); > + ov2650_set_data_pin_in(c); > + ssleep(1); > + > + return ret; > +} > + > +static int distance(struct ov2650_res_struct *res, u32 w, u32 h) > +{ > + int ret; > + if (res->width < w || res->height < h) > + return -1; > + > + ret = ((res->width - w) + (res->height - h)); > + return ret; > +} Add empty line. > +static int ov2650_try_res(u32 *w, u32 *h) > +{ > + struct ov2650_res_struct *res_index, *p = NULL; > + int dis, last_dis = ov2650_res->width + ov2650_res->height; > + > + dprintk(1, "&&&&& before %dx%d", *w, *h); > + for (res_index = ov2650_res; > + res_index < ov2650_res + N_RES; > + res_index++) { > + if ((res_index->width <= *w) && (res_index->height <= *h)) > + break; > + dis = distance(res_index, *w, *h); > + if (dis < last_dis) { > + last_dis = dis; > + p = res_index; > + } > + } > + > + if (res_index == ov2650_res + N_RES) > + res_index = ov2650_res + N_RES - 1; > + > + *w = res_index->width; > + *h = res_index->height; > + > + return 0; > +} > + > +static struct ov2650_res_struct *ov2650_to_res(u32 w, u32 h) > +{ > + struct ov2650_res_struct *res_index; > + > + for (res_index = ov2650_res; > + res_index < ov2650_res + N_RES; > + res_index++) > + if ((res_index->width == w) && (res_index->height == h)) > + break; > + > + if (res_index >= ov2650_res + N_RES) > + res_index--; > + > + return res_index; > +} > + > +static int ov2650_try_fmt(struct v4l2_subdev *sd, > + struct v4l2_format *fmt) Don't use try/g/s_fmt in a subdev driver. Instead use the newer try/g/s_mbus_fmt calls. The reason behind this is that v4l2_format really deals with what the data looks like in memory, after it has passed through the DMA engine. But between a sensor and e.g. Moorestown there is just a bus and no memory is involved. So the new mbus_fmt ops should be used instead of the older _fmt ops to negotiate bus formats. I'm working on replacing _fmt with mbus_fmt in existing subdev drivers and eventually the old _fmt ops will disappear. > +{ > + return ov2650_try_res(&fmt->fmt.pix.width, &fmt->fmt.pix.height); > +} > + > +static int ov2650_get_fmt(struct v4l2_subdev *sd, > + struct v4l2_format *fmt) > +{ > + struct ci_sensor_config *info = to_sensor_config(sd); > + unsigned short width, height; > + int index; > + > + ci_sensor_res2size(info->res, &width, &height); > + > + /* Marked the current sensor res as being "used" */ > + for (index = 0; index < N_RES; index++) { > + if ((width == ov2650_res[index].width) && > + (height == ov2650_res[index].height)) { > + ov2650_res[index].used = 1; > + continue; > + } > + ov2650_res[index].used = 0; > + } > + > + fmt->fmt.pix.width = width; > + fmt->fmt.pix.height = height; > + return 0; > +} > + > +static int ov2650_set_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + struct ci_sensor_config *info = to_sensor_config(sd); > + int ret = 0; > + struct ov2650_res_struct *res_index; > + u32 width, height; > + int index; > + > + DBG_entering; > + > + width = fmt->fmt.pix.width; > + height = fmt->fmt.pix.height; > + > + ret = ov2650_try_res(&width, &height); > + res_index = ov2650_to_res(width, height); > + > + if ((info->res != res_index->res) && (res_index->regs)) { > + > + dprintk(2, "changing res from to %dx%d", width, height); > + ret = ov2650_write(client, OV2650_SYS, 0x80); > + ret += ov2650_write_array(client, ov2650_def_reg); > + ret += ov2650_write_array(client, res_index->regs); > + > + for (index = 0; index < N_RES; index++) { > + if ((width == ov2650_res[index].width) && > + (height == ov2650_res[index].height)) { > + ov2650_res[index].used = 1; > + continue; > + } > + ov2650_res[index].used = 0; > + } > + > + for (index = 0; index < N_RES; index++) > + dprintk(2, "index = %d, used = %d\n", index, > + ov2650_res[index].used); > + > + } > + > + info->res = res_index->res; > + > + DBG_leaving; > + > + return ret; > +} > + > +static int ov2650_q_hflip(struct v4l2_subdev *sd, __s32 *value) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + int err; > + unsigned char v; > + > + err = ov2650_read(client, OV2650_TMC_6, &v); > + *value = (v & 0x02) == 0x02; > + return err; > +} > + > +static int ov2650_t_hflip(struct v4l2_subdev *sd, int value) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + struct ci_sensor_config *info = to_sensor_config(sd); > + unsigned char v, v1 = 0; > + int err; > + > + value = value >= 1 ? 1 : 0; > + err = ov2650_read(client, OV2650_TMC_6, &v); > + if (value) { > + v |= 0x02; > + v1 |= 0x08; > + info->bpat = SENSOR_BPAT_GRGRBGBG; > + } else { > + v &= ~0x02; > + v1 &= ~0x08; > + info->bpat = SENSOR_BPAT_BGBGGRGR; > + } > + err += ov2650_write(client, OV2650_TMC_6, v); > + err += ov2650_write(client, 0x3090, v1); > + msleep(10); > + > + return err; > +} > + > +static int ov2650_q_vflip(struct v4l2_subdev *sd, __s32 *value) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + int err; > + unsigned char v; > + > + err = ov2650_read(client, OV2650_TMC_6, &v); > + *value = (v & 0x01) == 0x01; > + return err; > +} > + > + > +static int ov2650_t_vflip(struct v4l2_subdev *sd, int value) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + int err = 0; > + unsigned char v; > + > + value = value >= 1 ? 1 : 0; > + err = ov2650_read(client, OV2650_TMC_6, &v); > + if (value) > + v |= 0x01; > + else > + v &= ~0x01; > + err += ov2650_write(client, OV2650_TMC_6, v); > + msleep(10); > + > + return err; > +} > + > +static struct ov2650_control { > + struct v4l2_queryctrl qc; > + int (*query)(struct v4l2_subdev *sd, __s32 *value); > + int (*tweak)(struct v4l2_subdev *sd, int value); > +} ov2650_controls[] = { > + { > + .qc = { > + .id = V4L2_CID_VFLIP, > + .type = V4L2_CTRL_TYPE_BOOLEAN, > + .name = "Vertical flip", > + .minimum = 0, > + .maximum = 1, > + .step = 1, > + .default_value = 0, > + }, > + .tweak = ov2650_t_vflip, > + .query = ov2650_q_vflip, > + }, > + { > + .qc = { > + .id = V4L2_CID_HFLIP, > + .type = V4L2_CTRL_TYPE_BOOLEAN, > + .name = "Horizontal mirror", > + .minimum = 0, > + .maximum = 1, > + .step = 1, > + .default_value = 0, > + }, > + .tweak = ov2650_t_hflip, > + .query = ov2650_q_hflip, > + }, > +}; > +#define N_CONTROLS (ARRAY_SIZE(ov2650_controls)) > + > +static struct ov2650_control *ov2650_find_control(__u32 id) > +{ > + int i; > + > + for (i = 0; i < N_CONTROLS; i++) > + if (ov2650_controls[i].qc.id == id) > + return ov2650_controls + i; > + return NULL; > +} > + > +static int ov2650_queryctrl(struct v4l2_subdev *sd, > + struct v4l2_queryctrl *qc) > +{ > + struct ov2650_control *octrl; > + octrl = ov2650_find_control(qc->id); Don't use this. Use v4l2_ctrl_query_fill() instead. See e.g. tvp514x.c for an example of how to use this. Using this function ensures consistent control names and will also make it easier to integrate later into a new control framework that I am working on. > + if (NULL == octrl) > + return -EINVAL; > + *qc = octrl->qc; > + return 0; > +} > + > +static int ov2650_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) > +{ > + struct ov2650_control *octrl = ov2650_find_control(ctrl->id); > + int ret; > + > + if (octrl == NULL) > + return -EINVAL; > + ret = octrl->query(sd, &ctrl->value); > + if (ret >= 0) > + return 0; > + return ret; > +} > + > +static int ov2650_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) > +{ > + struct ov2650_control *octrl = ov2650_find_control(ctrl->id); > + int ret; > + > + if (octrl == NULL) > + return -EINVAL; > + ret = octrl->tweak(sd, ctrl->value); > + if (ret >= 0) > + return 0; > + return ret; > +} > +static int ov2650_s_stream(struct v4l2_subdev *sd, int enable) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + > + DBG_entering; > + > + > + if (enable) { > + ov2650_write(client, 0x3086, 0x00); > + ov2650_set_data_pin_out(client); > + msleep(2000); > + } else { > + ov2650_write(client, 0x3086, 0x0f); > + ov2650_set_data_pin_in(client); > + } > + > + DBG_leaving; > + return 0; > +} > + > +static int ov2650_enum_framesizes(struct v4l2_subdev *sd, > + struct v4l2_frmsizeenum *fsize) > +{ > + unsigned int index = fsize->index; > + > + DBG_entering; > + > + if (index >= N_RES) > + return -EINVAL; > + > + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; > + fsize->discrete.width = ov2650_res[index].width; > + fsize->discrete.height = ov2650_res[index].height; > + fsize->reserved[0] = ov2650_res[index].used; > + > + DBG_leaving; > + > + return 0; > +} > + > +static int ov2650_enum_frameintervals(struct v4l2_subdev *sd, > + struct v4l2_frmivalenum *fival) > +{ > + unsigned int index = fival->index; > + > + DBG_entering; > + > + if (index >= N_RES) > + return -EINVAL; > + > + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; > + fival->discrete.numerator = 1; > + fival->discrete.denominator = ov2650_res[index].fps; > + > + DBG_leaving; > + > + return 0; > +} > +static int ov2650_g_chip_ident(struct v4l2_subdev *sd, > + struct v4l2_dbg_chip_ident *chip) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + > + #define V4L2_IDENT_OV2650 8244 > + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV2650, 0); > +} > + > +#ifdef CONFIG_VIDEO_ADV_DEBUG > +static int ov2650_g_register(struct v4l2_subdev *sd, > + struct v4l2_dbg_register *reg) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + unsigned char val = 0; > + int ret; > + > + if (!v4l2_chip_match_i2c_client(client, ®->match)) > + return -EINVAL; > + if (!capable(CAP_SYS_ADMIN)) > + return -EPERM; > + ret = ov2650_read(client, reg->reg & 0xffff, &val); > + reg->val = val; > + reg->size = 1; > + return ret; > +} > + > +static int ov2650_s_register(struct v4l2_subdev *sd, > + struct v4l2_dbg_register *reg) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(sd); > + > + if (!v4l2_chip_match_i2c_client(client, ®->match)) > + return -EINVAL; > + if (!capable(CAP_SYS_ADMIN)) > + return -EPERM; > + ov2650_write(client, reg->reg & 0xffff, reg->val & 0xff); > + return 0; > +} > +#endif > + > +static const struct v4l2_subdev_video_ops ov2650_video_ops = { > + .try_fmt = ov2650_try_fmt, > + .s_fmt = ov2650_set_fmt, > + .g_fmt = ov2650_get_fmt, > + .s_stream = ov2650_s_stream, > + .enum_framesizes = ov2650_enum_framesizes, > + .enum_frameintervals = ov2650_enum_frameintervals, > +}; > + > +static const struct v4l2_subdev_core_ops ov2650_core_ops = { > + .g_chip_ident = ov2650_g_chip_ident, > + .queryctrl = ov2650_queryctrl, > + .g_ctrl = ov2650_g_ctrl, > + .s_ctrl = ov2650_s_ctrl, > + #ifdef CONFIG_VIDEO_ADV_DEBUG > + .g_register = ov2650_g_register, > + .s_register = ov2650_s_register, > + #endif > +}; > + > +static const struct v4l2_subdev_ops ov2650_ops = { > + .core = &ov2650_core_ops, > + .video = &ov2650_video_ops, > +}; > + > +static int ov2650_detect(struct i2c_client *client) > +{ > + struct i2c_adapter *adapter = client->adapter; > + int adap_id = i2c_adapter_id(adapter); > + u8 value; > + > + printk(KERN_WARNING "Now start ov2650 detect\n"); > + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) > + return -ENODEV; > + > + if (adap_id != 1) > + return -ENODEV; > + > + ov2650_wakeup(); > + ov2650_read(client, OV2650_PID_L, &value); > + if (value != 0x52) > + return -ENODEV; > + > + return 0; > +} > + > +static int ov2650_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct ci_sensor_config *info; > + struct v4l2_subdev *sd; > + int ret = -1; > + > + DBG_entering; > + > + printk(KERN_INFO "Init ov2650 sensor \n"); > + > + v4l_info(client, "chip found @ 0x%x (%s)\n", > + client->addr << 1, client->adapter->name); > + /* > + * Setup sensor configuration structure > + */ > + info = kzalloc(sizeof(struct ci_sensor_config), GFP_KERNEL); > + if (!info) > + return -ENOMEM; > + > + ret = ov2650_detect(client); > + if (ret) { > + kfree(info); > + return -ENODEV; > + } > + > + sd = &info->sd; > + v4l2_i2c_subdev_init(sd, client, &ov2650_ops); > + > + ret += ov2650_init(client); > + > + printk(KERN_INFO "Init ov2650 sensor success, ret = %d\n", ret); > + > + DBG_leaving; > + return 0; > +} > + > +static int ov2650_remove(struct i2c_client *client) > +{ > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > + > + v4l2_device_unregister_subdev(sd); > + kfree(to_sensor_config(sd)); > + return 0; > +} > + > +static const struct i2c_device_id ov2650_id[] = { > + {"ov2650", 0}, > + {} > +}; > + > +MODULE_DEVICE_TABLE(i2c, ov2650_id); > + > +static struct v4l2_i2c_driver_data v4l2_i2c_data = { > + .name = "ov2650", > + .probe = ov2650_probe, > + .remove = ov2650_remove, > + .id_table = ov2650_id, > +}; > + > +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx>"); > +MODULE_DESCRIPTION("A low-level driver for OmniVision 2650 sensors"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/media/video/mrstci/mrstov2650/ov2650.h b/drivers/media/video/mrstci/mrstov2650/ov2650.h > new file mode 100644 > index 0000000..146e0f4 > --- /dev/null > +++ b/drivers/media/video/mrstci/mrstov2650/ov2650.h > @@ -0,0 +1,717 @@ > +/* > + * Support for Moorestown Langwell Camera Imaging ISP subsystem. > + * > + * Copyright (c) 2009 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. > + * > + * > + * Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx> > + */ > + > +#define I2C_OV2650 0x60 > +#define I2C_DRIVERID_OV2650 1047 > + > +#define GPIO_SCLK_25 44 > +#define GPIO_STB_PIN 47 > +#define GPIO_STDBY_PIN 48 > +#define GPIO_RESET_PIN 50 > + > +/* System control register */ > +#define OV2650_AGC 0x3000 > +#define OV2650_AGCS 0x3001 > +#define OV2650_AEC_H 0x3002 > +#define OV2650_AEC_L 0x3003 > +#define OV2650_AECL 0x3004 > +#define OV2650_AECS_H 0x3008 > +#define OV2650_AECS_L 0x3009 > +#define OV2650_PID_H 0x300A > +#define OV2650_PID_L 0x300B > +#define OV2650_SCCB 0x300C > +#define OV2650_PCLK 0x300D > +#define OV2650_PLL_1 0x300E > +#define OV2650_PLL_2 0x300F > +#define OV2650_PLL_3 0x3010 > +#define OV2650_CLK 0x3011 > +#define OV2650_SYS 0x3012 > +#define OV2650_AUTO_1 0x3013 > +#define OV2650_AUTO_2 0x3014 > +#define OV2650_AUTO_3 0x3015 > +#define OV2650_AUTO_4 0x3016 > +#define OV2650_AUTO_5 0x3017 > +#define OV2650_WPT 0x3018 > +#define OV2650_BPT 0x3019 > +#define OV2650_VPT 0x301A > +#define OV2650_YAVG 0x301B > +#define OV2650_AECG_50 0x301C > +#define OV2650_AECG_60 0x301D > +#define OV2650_RZM_H 0x301E > +#define OV2650_RZM_L 0x301F > +#define OV2650_HS_H 0x3020 > +#define OV2650_HS_L 0x3021 > +#define OV2650_VS_H 0x3022 > +#define OV2650_VS_L 0x3023 > +#define OV2650_HW_H 0x3024 > +#define OV2650_HW_L 0x3025 > +#define OV2650_VH_H 0x3026 > +#define OV2650_VH_L 0x3027 > +#define OV2650_HTS_H 0x3028 > +#define OV2650_HTS_L 0x3029 > +#define OV2650_VTS_H 0x302A > +#define OV2650_VTS_L 0x302B > +#define OV2650_EXHTS 0x302C > +#define OV2650_EXVTS_H 0x302D > +#define OV2650_EXVTS_L 0x302E > +#define OV2650_WET_0 0x3030 > +#define OV2650_WET_1 0x3031 > +#define OV2650_WET_2 0x3032 > +#define OV2650_WET_3 0x3033 > +#define OV2650_AHS_H 0x3038 > +#define OV2650_AHS_L 0x3039 > +#define OV2650_AVS_H 0x303A > +#define OV2650_AVS_L 0x303B > +#define OV2650_AHW_H 0x303C > +#define OV2650_AHW_L 0x303D > +#define OV2650_AVH_H 0x303E > +#define OV2650_AVH_L 0x303F > +#define OV2650_HISTO_0 0x3040 > +#define OV2650_HISTO_1 0x3041 > +#define OV2650_HISTO_2 0x3042 > +#define OV2650_HISTO_3 0x3043 > +#define OV2650_HISTO_4 0x3044 > +#define OV2650_BLC9A 0x3069 > +#define OV2650_BLCC 0x306C > +#define OV2650_BLCD 0x306D > +#define OV2650_BLCF 0x306F > +#define OV2650_BD50_L 0x3070 > +#define OV2650_BD50_H 0x3071 > +#define OV2650_BD60_L 0x3072 > +#define OV2650_BD60_H 0x3073 > +#define OV2650_TMC_0 0x3076 > +#define OV2650_TMC_1 0x3077 > +#define OV2650_TMC_2 0x3078 > +#define OV2650_TMC_4 0x307A > +#define OV2650_TMC_6 0x307C > +#define OV2650_TMC_8 0x307E > +#define OV2650_TMC_I2C 0x3084 > +#define OV2650_TMC_10 0x3086 > +#define OV2650_TMC_11 0x3087 > +#define OV2650_ISP_XO_H 0x3088 > +#define OV2650_ISP_XO_L 0x3089 > +#define OV2650_ISP_YO_H 0x308A > +#define OV2650_ISP_YO_L 0x308B > +#define OV2650_TMC_12 0x308C > +#define OV2650_TMC_13 0x308D > +#define OV2650_EFUSE 0x308F > +#define OV2650_IO_CTL_0 0x30B0 > +#define OV2650_IO_CRL_1 0x30B1 > +#define OV2650_IO_CTL_2 0x30B2 > +#define OV2650_LAEC 0x30F0 > +#define OV2650_GRP_EOP 0x30FF > + > +/* SC registers */ > +#define OV2650_SC_CTL_0 0x3100 > +#define OV2650_SC_SYN_CTL_0 0x3104 > +#define OV2650_SC_SYN_CTL_1 0x3105 > +#define OV2650_SC_SYN_CTL_3 0x3107 > +#define OV2650_SC_SYN_CTL_4 0x3108 > + > +/* DSP control register */ > +#define OV2650_ISP_CTL_0 0x3300 > +#define OV2650_ISP_CTL_1 0x3301 > +#define OV2650_ISP_CTL_2 0x3302 > +#define OV2650_ISP_CTL_3 0x3303 > +#define OV2650_ISP_CTL_4 0x3304 > +#define OV2650_ISP_CTL_5 0x3305 > +#define OV2650_ISP_CTL_6 0x3306 > +#define OV2650_ISP_CTL_7 0x3307 > +#define OV2650_ISP_CTL_8 0x3308 > +#define OV2650_ISP_CTL_9 0x3309 > +#define OV2650_ISP_CTL_A 0x330A > +#define OV2650_ISP_CTL_B 0x330B > +#define OV2650_ISP_CTL_10 0x3310 > +#define OV2650_ISP_CTL_11 0x3311 > +#define OV2650_ISP_CTL_12 0x3312 > +#define OV2650_ISP_CTL_13 0x3313 > +#define OV2650_ISP_CTL_14 0x3314 > +#define OV2650_ISP_CTL_15 0x3315 > +#define OV2650_ISP_CTL_16 0x3316 > +#define OV2650_ISP_CTL_17 0x3317 > +#define OV2650_ISP_CTL_18 0x3318 > +#define OV2650_ISP_CTL_19 0x3319 > +#define OV2650_ISP_CTL_1A 0x331A > +#define OV2650_ISP_CTL_1B 0x331B > +#define OV2650_ISP_CTL_1C 0x331C > +#define OV2650_ISP_CTL_1D 0x331D > +#define OV2650_ISP_CTL_1E 0x331E > +#define OV2650_ISP_CTL_20 0x3320 > +#define OV2650_ISP_CTL_21 0x3321 > +#define OV2650_ISP_CTL_22 0x3322 > +#define OV2650_ISP_CTL_23 0x3323 > +#define OV2650_ISP_CTL_24 0x3324 > +#define OV2650_ISP_CTL_27 0x3327 > +#define OV2650_ISP_CTL_28 0x3328 > +#define OV2650_ISP_CTL_29 0x3329 > +#define OV2650_ISP_CTL_2A 0x332A > +#define OV2650_ISP_CTL_2B 0x332B > +#define OV2650_ISP_CTL_2C 0x332C > +#define OV2650_ISP_CTL_2D 0x332D > +#define OV2650_ISP_CTL_2E 0x332E > +#define OV2650_ISP_CTL_2F 0x332F > +#define OV2650_ISP_CTL_30 0x3330 > +#define OV2650_ISP_CTL_31 0x3331 > +#define OV2650_ISP_CTL_32 0x3332 > +#define OV2650_ISP_CTL_33 0x3333 > +#define OV2650_ISP_CTL_34 0x3334 > +#define OV2650_ISP_CTL_35 0x3335 > +#define OV2650_ISP_CTL_36 0x3336 > +#define OV2650_ISP_CTL_40 0x3340 > +#define OV2650_ISP_CTL_41 0x3341 > +#define OV2650_ISP_CTL_42 0x3342 > +#define OV2650_ISP_CTL_43 0x3343 > +#define OV2650_ISP_CTL_44 0x3344 > +#define OV2650_ISP_CTL_45 0x3345 > +#define OV2650_ISP_CTL_46 0x3346 > +#define OV2650_ISP_CTL_47 0x3347 > +#define OV2650_ISP_CTL_48 0x3348 > +#define OV2650_ISP_CTL_49 0x3349 > +#define OV2650_ISP_CTL_4A 0x334A > +#define OV2650_ISP_CTL_4B 0x334B > +#define OV2650_ISP_CTL_4C 0x334C > +#define OV2650_ISP_CTL_4D 0x334D > +#define OV2650_ISP_CTL_4E 0x334E > +#define OV2650_ISP_CTL_4F 0x334F > +#define OV2650_ISP_CTL_50 0x3350 > +#define OV2650_ISP_CTL_51 0x3351 > +#define OV2650_ISP_CTL_52 0x3352 > +#define OV2650_ISP_CTL_53 0x3353 > +#define OV2650_ISP_CTL_54 0x3354 > +#define OV2650_ISP_CTL_55 0x3355 > +#define OV2650_ISP_CTL_56 0x3356 > +#define OV2650_ISP_CTL_57 0x3357 > +#define OV2650_ISP_CTL_58 0x3358 > +#define OV2650_ISP_CTL_59 0x3359 > +#define OV2650_ISP_CTL_5A 0x335A > +#define OV2650_ISP_CTL_5B 0x335B > +#define OV2650_ISP_CTL_5C 0x335C > +#define OV2650_ISP_CTL_5D 0x335D > +#define OV2650_ISP_CTL_5E 0x335E > +#define OV2650_ISP_CTL_5F 0x335F > +#define OV2650_ISP_CTL_60 0x3360 > +#define OV2650_ISP_CTL_61 0x3361 > +#define OV2650_ISP_CTL_62 0x3362 > +#define OV2650_ISP_CTL_63 0x3363 > +#define OV2650_ISP_CTL_64 0x3364 > +#define OV2650_ISP_CTL_65 0x3365 > +#define OV2650_ISP_CTL_6A 0x336A > +#define OV2650_ISP_CTL_6B 0x336B > +#define OV2650_ISP_CTL_6C 0x336C > +#define OV2650_ISP_CTL_6E 0x336E > +#define OV2650_ISP_CTL_71 0x3371 > +#define OV2650_ISP_CTL_72 0x3372 > +#define OV2650_ISP_CTL_73 0x3373 > +#define OV2650_ISP_CTL_74 0x3374 > +#define OV2650_ISP_CTL_75 0x3375 > +#define OV2650_ISP_CTL_76 0x3376 > +#define OV2650_ISP_CTL_77 0x3377 > +#define OV2650_ISP_CTL_78 0x3378 > +#define OV2650_ISP_CTL_79 0x3379 > +#define OV2650_ISP_CTL_7A 0x337A > +#define OV2650_ISP_CTL_7B 0x337B > +#define OV2650_ISP_CTL_7C 0x337C > +#define OV2650_ISP_CTL_80 0x3380 > +#define OV2650_ISP_CTL_81 0x3381 > +#define OV2650_ISP_CTL_82 0x3382 > +#define OV2650_ISP_CTL_83 0x3383 > +#define OV2650_ISP_CTL_84 0x3384 > +#define OV2650_ISP_CTL_85 0x3385 > +#define OV2650_ISP_CTL_86 0x3386 > +#define OV2650_ISP_CTL_87 0x3387 > +#define OV2650_ISP_CTL_88 0x3388 > +#define OV2650_ISP_CTL_89 0x3389 > +#define OV2650_ISP_CTL_8A 0x338A > +#define OV2650_ISP_CTL_8B 0x338B > +#define OV2650_ISP_CTL_8C 0x338C > +#define OV2650_ISP_CTL_8D 0x338D > +#define OV2650_ISP_CTL_8E 0x338E > +#define OV2650_ISP_CTL_90 0x3390 > +#define OV2650_ISP_CTL_91 0x3391 > +#define OV2650_ISP_CTL_92 0x3392 > +#define OV2650_ISP_CTL_93 0x3393 > +#define OV2650_ISP_CTL_94 0x3394 > +#define OV2650_ISP_CTL_95 0x3395 > +#define OV2650_ISP_CTL_96 0x3396 > +#define OV2650_ISP_CTL_97 0x3397 > +#define OV2650_ISP_CTL_98 0x3398 > +#define OV2650_ISP_CTL_99 0x3399 > +#define OV2650_ISP_CTL_9A 0x339A > +#define OV2650_ISP_CTL_A0 0x33A0 > +#define OV2650_ISP_CTL_A1 0x33A1 > +#define OV2650_ISP_CTL_A2 0x33A2 > +#define OV2650_ISP_CTL_A3 0x33A3 > +#define OV2650_ISP_CTL_A4 0x33A4 > +#define OV2650_ISP_CTL_A5 0x33A5 > +#define OV2650_ISP_CTL_A6 0x33A6 > +#define OV2650_ISP_CTL_A7 0x33A7 > +#define OV2650_ISP_CTL_A8 0x33A8 > +#define OV2650_ISP_CTL_AA 0x33AA > +#define OV2650_ISP_CTL_AB 0x33AB > +#define OV2650_ISP_CTL_AC 0x33AC > +#define OV2650_ISP_CTL_AD 0x33AD > +#define OV2650_ISP_CTL_AE 0x33AE > +#define OV2650_ISP_CTL_AF 0x33AF > +#define OV2650_ISP_CTL_B0 0x33B0 > +#define OV2650_ISP_CTL_B1 0x33B1 > +#define OV2650_ISP_CTL_B2 0x33B2 > +#define OV2650_ISP_CTL_B3 0x33B3 > +#define OV2650_ISP_CTL_B4 0x33B4 > +#define OV2650_ISP_CTL_B5 0x33B5 > +#define OV2650_ISP_CTL_B6 0x33B6 > +#define OV2650_ISP_CTL_B7 0x33B7 > +#define OV2650_ISP_CTL_B8 0x33B8 > +#define OV2650_ISP_CTL_B9 0x33B9 > + > +/* Format register */ > +#define OV2650_FMT_CTL_0 0x3400 > +#define OV2650_FMT_CTL_1 0x3401 > +#define OV2650_FMT_CTL_2 0x3402 > +#define OV2650_FMT_CTL_3 0x3403 > +#define OV2650_FMT_CTL_4 0x3404 > +#define OV2650_FMT_CTL_5 0x3405 > +#define OV2650_FMT_CTL_6 0x3406 > +#define OV2650_FMT_CTL_7 0x3407 > +#define OV2650_FMT_CTL_8 0x3408 > +#define OV2650_DITHER_CTL 0x3409 > +#define OV2650_DVP_CTL_0 0x3600 > +#define OV2650_DVP_CTL_1 0x3601 > +#define OV2650_DVP_CTL_6 0x3606 > +#define OV2650_DVP_CTL_7 0x3607 > +#define OV2650_DVP_CTL_9 0x3609 > +#define OV2650_DVP_CTL_B 0x360B > + > +/* General definition for ov2650 */ > +#define OV2650_OUTWND_MAX_H UXGA_SIZE_H > +#define OV2650_OUTWND_MAX_V UXGA_SIZE_V > + > +struct regval_list { > + u16 reg_num; > + u8 value; > +}; > + > +/* > + * Default register value > + * 1600x1200 YUV > + */ > +static struct regval_list ov2650_def_reg[] = { static const. Ditto for the similar arrays below. > + {0x3012, 0x80}, > + {0x308c, 0x80}, > + {0x308d, 0x0e}, > + {0x360b, 0x00}, > + {0x30b0, 0xff}, > + {0x30b1, 0xff}, > + {0x30b2, 0x27}, > + > + {0x300e, 0x34}, > + {0x300f, 0xa6}, > + {0x3010, 0x81}, > + {0x3082, 0x01}, > + {0x30f4, 0x01}, > + {0x3090, 0x33}, > + {0x3091, 0xc0}, > + {0x30ac, 0x42}, > + > + {0x30d1, 0x08}, > + {0x30a8, 0x56}, > + {0x3015, 0x03}, > + {0x3093, 0x00}, > + {0x307e, 0xe5}, > + {0x3079, 0x00}, > + {0x30aa, 0x42}, > + {0x3017, 0x40}, > + {0x30f3, 0x82}, > + {0x306a, 0x0c}, > + {0x306d, 0x00}, > + {0x336a, 0x3c}, > + {0x3076, 0x6a}, > + {0x30d9, 0x8c}, > + {0x3016, 0x82}, > + {0x3601, 0x30}, > + {0x304e, 0x88}, > + {0x30f1, 0x82}, > + {0x3011, 0x02}, > + > + {0x3013, 0xf7}, > + {0x301c, 0x13}, > + {0x301d, 0x17}, > + {0x3070, 0x3e}, > + {0x3072, 0x34}, > + > + {0x30af, 0x00}, > + {0x3048, 0x1f}, > + {0x3049, 0x4e}, > + {0x304a, 0x20}, > + {0x304f, 0x20}, > + {0x304b, 0x02}, > + {0x304c, 0x00}, > + {0x304d, 0x02}, > + {0x304f, 0x20}, > + {0x30a3, 0x10}, > + {0x3013, 0xf7}, > + {0x3014, 0x44}, > + {0x3071, 0x00}, > + {0x3070, 0x3e}, > + {0x3073, 0x00}, > + {0x3072, 0x34}, > + {0x301c, 0x12}, > + {0x301d, 0x16}, > + {0x304d, 0x42}, > + {0x304a, 0x40}, > + {0x304f, 0x40}, > + {0x3095, 0x07}, > + {0x3096, 0x16}, > + {0x3097, 0x1d}, > + > + {0x3020, 0x01}, > + {0x3021, 0x18}, > + {0x3022, 0x00}, > + {0x3023, 0x0a}, > + {0x3024, 0x06}, > + {0x3025, 0x58}, > + {0x3026, 0x04}, > + {0x3027, 0xbc}, > + {0x3088, 0x06}, > + {0x3089, 0x40}, > + {0x308a, 0x04}, > + {0x308b, 0xb0}, > + {0x3316, 0x64}, > + {0x3317, 0x4b}, > + {0x3318, 0x00}, > + {0x331a, 0x64}, > + {0x331b, 0x4b}, > + {0x331c, 0x00}, > + {0x3100, 0x00}, > + > + {0x3320, 0xfa}, > + {0x3321, 0x11}, > + {0x3322, 0x92}, > + {0x3323, 0x01}, > + {0x3324, 0x97}, > + {0x3325, 0x02}, > + {0x3326, 0xff}, > + {0x3327, 0x0c}, > + {0x3328, 0x10}, > + {0x3329, 0x10}, > + {0x332a, 0x58}, > + {0x332b, 0x50}, > + {0x332c, 0xbe}, > + {0x332d, 0xe1}, > + {0x332e, 0x43}, > + {0x332f, 0x36}, > + {0x3330, 0x4d}, > + {0x3331, 0x44}, > + {0x3332, 0xf8}, > + {0x3333, 0x0a}, > + {0x3334, 0xf0}, > + {0x3335, 0xf0}, > + {0x3336, 0xf0}, > + {0x3337, 0x40}, > + {0x3338, 0x40}, > + {0x3339, 0x40}, > + {0x333a, 0x00}, > + {0x333b, 0x00}, > + > + {0x3380, 0x28}, > + {0x3381, 0x48}, > + {0x3382, 0x10}, > + {0x3383, 0x23}, > + {0x3384, 0xc0}, > + {0x3385, 0xe5}, > + {0x3386, 0xc2}, > + {0x3387, 0xb3}, > + {0x3388, 0x0e}, > + {0x3389, 0x98}, > + {0x338a, 0x01}, > + > + {0x3340, 0x0e}, > + {0x3341, 0x1a}, > + {0x3342, 0x31}, > + {0x3343, 0x45}, > + {0x3344, 0x5a}, > + {0x3345, 0x69}, > + {0x3346, 0x75}, > + {0x3347, 0x7e}, > + {0x3348, 0x88}, > + {0x3349, 0x96}, > + {0x334a, 0xa3}, > + {0x334b, 0xaf}, > + {0x334c, 0xc4}, > + {0x334d, 0xd7}, > + {0x334e, 0xe8}, > + {0x334f, 0x20}, > + > + {0x3350, 0x32}, > + {0x3351, 0x25}, > + {0x3352, 0x80}, > + {0x3353, 0x1e}, > + {0x3354, 0x00}, > + {0x3355, 0x85}, > + {0x3356, 0x32}, > + {0x3357, 0x25}, > + {0x3358, 0x80}, > + {0x3359, 0x1b}, > + {0x335a, 0x00}, > + {0x335b, 0x85}, > + {0x335c, 0x32}, > + {0x335d, 0x25}, > + {0x335e, 0x80}, > + {0x335f, 0x1b}, > + {0x3360, 0x00}, > + {0x3361, 0x85}, > + {0x3363, 0x70}, > + {0x3364, 0x7f}, > + {0x3365, 0x00}, > + {0x3366, 0x00}, > + > + {0x3301, 0xff}, > + {0x338B, 0x11}, > + {0x338c, 0x10}, > + {0x338d, 0x40}, > + > + {0x3370, 0xd0}, > + {0x3371, 0x00}, > + {0x3372, 0x00}, > + {0x3373, 0x40}, > + {0x3374, 0x10}, > + {0x3375, 0x10}, > + {0x3376, 0x04}, > + {0x3377, 0x00}, > + {0x3378, 0x04}, > + {0x3379, 0x80}, > + > + {0x3069, 0x84}, > + {0x307c, 0x10}, > + {0x3087, 0x02}, > + > + {0x3300, 0xfc}, > + {0x3302, 0x01}, > + {0x3400, 0x00}, > + {0x3606, 0x20}, > + {0x3601, 0x30}, > + {0x30f3, 0x83}, > + {0x304e, 0x88}, > + > + {0x3086, 0x0f}, > + {0x3086, 0x00}, > + > + {0xffff, 0xff}, > +}; > + > +/* 800x600 */ > +static struct regval_list ov2650_res_svga[] = { > + > + {0x306f, 0x14}, > + {0x302a, 0x02}, > + {0x302b, 0x84}, > + {0x3012, 0x10}, > + {0x3011, 0x01}, > + > + {0x3070, 0x5d}, > + {0x3072, 0x4d}, > + > + {0x3014, 0x84}, > + {0x301c, 0x07}, > + {0x301d, 0x09}, > + {0x3070, 0x50}, > + {0x3071, 0x00}, > + {0x3072, 0x42}, > + {0x3073, 0x00}, > + > + {0x3020, 0x01}, > + {0x3021, 0x18}, > + {0x3022, 0x00}, > + {0x3023, 0x06}, > + {0x3024, 0x06}, > + {0x3025, 0x58}, > + {0x3026, 0x02}, > + {0x3027, 0x5e}, > + {0x3088, 0x03}, > + {0x3089, 0x20}, > + {0x308a, 0x02}, > + {0x308b, 0x58}, > + {0x3316, 0x64}, > + {0x3317, 0x25}, > + {0x3318, 0x80}, > + {0x3319, 0x08}, > + {0x331a, 0x64}, > + {0x331b, 0x4b}, > + {0x331c, 0x00}, > + {0x331d, 0x38}, > + {0x3100, 0x00}, > + > + {0x3302, 0x11}, > + > + {0x3011, 0x01}, > + {0x300f, 0xa6}, > + {0x300e, 0x36}, > + {0x3010, 0x81}, > + {0x302e, 0x00}, > + {0x302d, 0x00}, > + {0x302c, 0x00}, > + {0x302b, 0x84}, > + {0x3014, 0x84}, > + {0x301c, 0x07}, > + {0x301d, 0x09}, > + {0x3070, 0x50}, > + {0x3071, 0x00}, > + {0x3072, 0x42}, > + {0x3073, 0x00}, > + > + {0x3086, 0x0f}, > + {0x3086, 0x00}, > + {0xffff, 0xff}, > +}; > + > +/* 640x480 */ > +static struct regval_list ov2650_res_vga_vario[] = { > + {0x306f, 0x14}, > + {0x302a, 0x02}, > + {0x302b, 0x6a}, > + {0x3012, 0x10}, > + {0x3011, 0x01}, > + > + {0x3070, 0x5d}, > + {0x3072, 0x4d}, > + > + {0x301c, 0x05}, > + {0x301d, 0x06}, > + > + {0x3020, 0x01}, > + {0x3021, 0x18}, > + {0x3022, 0x00}, > + {0x3023, 0x06}, > + {0x3024, 0x06}, > + {0x3025, 0x58}, > + {0x3026, 0x02}, > + {0x3027, 0x61}, > + {0x3088, 0x02}, > + {0x3089, 0x80}, > + {0x308a, 0x01}, > + {0x308b, 0xe0}, > + {0x3316, 0x64}, > + {0x3317, 0x25}, > + {0x3318, 0x80}, > + {0x3319, 0x08}, > + {0x331a, 0x28}, > + {0x331b, 0x1e}, > + {0x331c, 0x00}, > + {0x331d, 0x38}, > + {0x3100, 0x00}, > + > + {0x3302, 0x11}, > + {0x3011, 0x00}, > + > + {0x3014, 0x84}, > + {0x3086, 0x0f}, > + {0x3086, 0x00}, > + {0xffff, 0xff}, > +}; > + > +/* 320x240 */ > +static struct regval_list ov2650_res_qvga[] = { > + {0x306f, 0x14}, > + {0x302a, 0x02}, > + {0x302b, 0x6a}, > + > + {0x3012, 0x10}, > + {0x3011, 0x01}, > + > + {0x3070, 0x5d}, > + {0x3072, 0x4d}, > + {0x301c, 0x05}, > + {0x301d, 0x06}, > + > + {0x3023, 0x06}, > + {0x3026, 0x02}, > + {0x3027, 0x61}, > + {0x3088, 0x01}, > + {0x3089, 0x40}, > + {0x308a, 0x00}, > + {0x308b, 0xf0}, > + {0x3316, 0x64}, > + {0x3317, 0x25}, > + {0x3318, 0x80}, > + {0x3319, 0x08}, > + {0x331a, 0x14}, > + {0x331b, 0x0f}, > + {0x331c, 0x00}, > + {0x331d, 0x38}, > + {0x3100, 0x00}, > + > + {0x3015, 0x02}, > + {0x3014, 0x84}, > + {0x3302, 0x11}, > + {0x3086, 0x0f}, > + {0x3086, 0x00}, > + {0xffff, 0xff}, > +}; > + > +static struct regval_list ov2650_res_uxga[] = { > + {0x3014, 0x84}, > + {0x301c, 0x13}, > + {0x301d, 0x17}, > + {0x3070, 0x40}, > + {0x3071, 0x00}, > + {0x3072, 0x36}, > + {0x3073, 0x00}, > + > + {0xffff, 0xff}, > +}; > + > +static struct regval_list ov2650_res_sxga[] = { > + {0x3011, 0x02}, > + > + {0x3020, 0x01}, > + {0x3021, 0x18}, > + {0x3022, 0x00}, > + {0x3023, 0x0a}, > + {0x3024, 0x06}, > + {0x3025, 0x58}, > + {0x3026, 0x04}, > + {0x3027, 0xbc}, > + {0x3088, 0x05}, > + {0x3089, 0x00}, > + {0x308a, 0x04}, > + {0x308b, 0x00}, > + {0x3316, 0x64}, > + {0x3317, 0x4b}, > + {0x3318, 0x00}, > + {0x331a, 0x50}, > + {0x331b, 0x40}, > + {0x331c, 0x00}, > + > + {0x3302, 0x11}, > + > + {0x3014, 0x84}, > + {0x301c, 0x13}, > + {0x301d, 0x17}, > + {0x3070, 0x40}, > + {0x3071, 0x00}, > + {0x3072, 0x36}, > + {0x3073, 0x00}, > + > + {0x3086, 0x0f}, > + {0x3086, 0x00}, > + {0xffff, 0xff}, > +}; > -- > 1.6.3.2 Regards, Hans -- Hans Verkuil - video4linux developer - sponsored by TANDBERG -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html