Re: [PATCH v2 4/10] V4L2 patches for Intel Moorestown Camera Imaging Drivers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
> +       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);
> +       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, &reg->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, &reg->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

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux