diff mbox

[5/6] TVP7002 driver for DM365

Message ID 1251418657-16240-1-git-send-email-santiago.nunez@ridgerun.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

santiago.nunez@ridgerun.com Aug. 28, 2009, 12:17 a.m. UTC
From: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>

This patch provides the implementation of the TVP7002 decoder
driver for DM365. g_fmt needs to be revised.

Signed-off-by: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
---
 drivers/media/video/tvp7002.c | 3067 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 3067 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tvp7002.c

Comments

Vaibhav Hiremath Aug. 28, 2009, 5:17 a.m. UTC | #1
> -----Original Message-----
> From: davinci-linux-open-source-bounces@linux.davincidsp.com
> [mailto:davinci-linux-open-source-bounces@linux.davincidsp.com] On
> Behalf Of santiago.nunez@ridgerun.com
> Sent: Friday, August 28, 2009 5:48 AM
> To: Karicheri, Muralidharan
> Cc: davinci-linux-open-source@linux.davincidsp.com;
> clark.becker@ridgerun.com; Santiago Nunez-Corrales;
> todd.fischer@ridgerun.com
> Subject: [PATCH 5/6] TVP7002 driver for DM365
>
> From: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
>
> This patch provides the implementation of the TVP7002 decoder
> driver for DM365. g_fmt needs to be revised.
>
> Signed-off-by: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
> ---
>  drivers/media/video/tvp7002.c | 3067
> +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 3067 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tvp7002.c
>
> diff --git a/drivers/media/video/tvp7002.c
> b/drivers/media/video/tvp7002.c
> new file mode 100644
> index 0000000..cc27aab
> --- /dev/null
> +++ b/drivers/media/video/tvp7002.c
> @@ -0,0 +1,3067 @@
> +/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and
> Graphics
> + * Digitizer with Horizontal PLL registers
> + *
> + * Copyright (C) 2009 Texas Instruments Inc
> + * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
> + *
> + * This code is partially based upon the TVP5150 driver
> + * written by Mauro Carvalho Chehab (mchehab@infradead.org)
> + * and the TVP514x driver written by Vaibhav Hiremath
> <hvaibhav@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as
> published by
> + * the Free Software Foundation; either version 2 of the License,
> or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/videodev2.h>
> +#include <linux/delay.h>
> +#include <media/v4l2-device.h>
> +#include <media/tvp7002.h>
> +#include <media/v4l2-i2c-drv.h>
> +#include <media/v4l2-chip-ident.h>
> +#include "tvp7002_reg.h"
> +
> +MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer
> driver");
> +MODULE_AUTHOR("Santiago Nunez-Corrales
> (santiago.nunez@ridgerun.com)");
> +MODULE_LICENSE("GPL");
> +
> +/* I2C retry attempts */
> +#define I2C_RETRY_COUNT                 (5)
> +
> +/* Debugging information */
> +
> +static int debug;
> +module_param(debug, int, 0);
> +MODULE_PARM_DESC(debug, "Debug level (0-2)");
> +
> +/* Register default values (according to tvp7002 datasheet) */
> +static const struct i2c_reg_value tvp7002_init_default[] = {
> +     /* 0x00: read only */
> +     {
> +             TVP7002_HPLL_FDBK_DIV_MSBS, 0x67
> +     },
> +     {
> +             TVP7002_HPLL_FDBK_DIV_LSBS, 0x20
> +     },
> +     {
> +             TVP7002_HPLL_CRTL, 0xa8
> +     },
> +     {
> +             TVP7002_HPLL_PHASE_SEL, 0x80
> +     },
> +     {
> +             TVP7002_CLAMP_START, 0x32
> +     },
> +     {
> +             TVP7002_CLAMP_W, 0x20
> +     },
> +     {
> +             TVP7002_HSYNC_OUT_W, 0x20
> +     },
> +     {
> +             TVP7002_B_FINE_GAIN, 0x00
> +     },
> +     {
> +             TVP7002_G_FINE_GAIN, 0x00
> +     },
> +     {
> +             TVP7002_R_FINE_GAIN, 0x00
> +     },
> +     {
> +             TVP7002_B_FINE_OFF_MSBS, 0x80
> +     },
> +     {
> +             TVP7002_G_FINE_OFF_MSBS, 0x80
> +     },
> +     {
> +             TVP7002_R_FINE_OFF_MSBS, 0x80
> +     },
> +     {
> +             TVP7002_SYNC_CTL_1, 0x5b
> +     },
> +     {
> +             TVP7002_HPLL_AND_CLAMP_CTL, 0x2e
> +     },
> +     {
> +             TVP7002_SYNC_ON_G_THRS, 0x5d
> +     },
> +     {
> +             TVP7002_SYNC_SEPARATOR_THRS, 0x20
> +     },
> +     {
> +             TVP7002_HPLL_PRE_COAST, 0x00
> +     },
> +     {
> +             TVP7002_HPLL_POST_COAST, 0x00
> +     },
> +     /* 0x14: read only */
> +     {
> +             TVP7002_OUT_FORMATTER, 0x00
> +     },
> +     {
> +             TVP7002_MISC_CTL_1, 0x11
> +     },
> +     {
> +             TVP7002_MISC_CTL_2, 0x03
> +     },
> +     {
> +             TVP7002_MISC_CTL_3, 0x00
> +     },
> +     {
> +             TVP7002_IN_MUX_SEL_1, 0x00
> +     },
> +     {
> +             TVP7002_IN_MUX_SEL_2, 0xc2
> +     },
> +     {
> +             TVP7002_B_AND_G_COARSE_GAIN, 0x77
> +     },
> +     {
> +             TVP7002_R_COARSE_GAIN, 0x07
> +     },
> +     {
> +             TVP7002_COARSE_CLAMP_CTL, 0x00
> +     },
> +     {
> +             TVP7002_FINE_OFF_LSBS, 0x00
> +     },
> +     {
> +             TVP7002_B_COARSE_OFF, 0x10
> +     },
> +     {
> +             TVP7002_G_COARSE_OFF, 0x10
> +     },
> +     {
> +             TVP7002_R_COARSE_OFF, 0x10
> +     },
> +     {
> +             TVP7002_HSOUT_OUT_START, 0x0d
> +     },
> +     {
> +             TVP7002_MISC_CTL_4, 0x0d
> +     },
> +     /* 0x23: read only */
> +     /* 0x24: read only */
> +     /* 0x25: read only */
> +     {
> +             TVP7002_AUTO_LVL_CTL_ENABLE, 0x80
> +     },
> +     /* 0x27: read only */
> +     {
> +             TVP7002_AUTO_LVL_CTL_FILTER, 0x53
> +     },
> +     {       /* Reserved */
> +             0x29, 0x08
> +     },
[Hiremath, Vaibhav] Why do you want to mention reserved register here, and again in tvp7002_write_inittab function you are writing to these registers. I would suggest you not to mention reserved registers at all.
> +     {
> +             TVP7002_FINE_CLAMP_CTL, 0x07
> +     },
> +     {
> +             TVP7002_PWR_CTL, 0x00
> +     },
> +     {
> +             TVP7002_ADC_SETUP, 0x50
> +     },
> +     {
> +             TVP7002_COARSE_CLAMP_CTL, 0x00
> +     },
> +     {
> +             TVP7002_SOG_CLAMP, 0x80
> +     },
> +     {
> +             TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c
> +     },
> +     {
> +             TVP7002_SOG_COARSE_CLAMP_CTL, 0x04
> +     },
> +     {
> +             TVP7002_ALC_PLACEMENT, 0x5a
> +     },
> +     {       /* Reserved */
> +             0x32, 0x18
> +     },
> +     {       /* Reserved */
> +             0x33, 0x60
> +     },
[Hiremath, Vaibhav] same here.
> +     {
> +             TVP7002_MVIS_STRIPPER_W, 0x03
> +     },
> +     {
> +             TVP7002_VSYNC_ALGN, 0x10
> +     },
> +     {
> +             TVP7002_SYNC_BYPASS, 0x00
> +     },
> +     /* 0x37: read only */
> +     /* 0x38: read only */
> +     /* 0x39: read only */
> +     /* 0x3a: read only */
> +     /* 0x3b: read only */
> +     /* 0x3c: read only */
> +     {
> +             TVP7002_L_LENGTH_TOL, 0x03
> +     },
> +     {       /* Reserved */
> +             0x3e, 0x04
> +     },
[Hiremath, Vaibhav] same.
> +     {
> +             TVP7002_VIDEO_BWTH_CTL, 0x00
> +     },
> +     {
> +             TVP7002_AVID_START_PIXEL_LSBS, 0x01
> +     },
> +     {
> +             TVP7002_AVID_START_PIXEL_MSBS, 0x2c
> +     },
> +     {
> +             TVP7002_AVID_STOP_PIXEL_LSBS, 0x06
> +     },
> +     {
> +             TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c
> +     },
> +     {
> +             TVP7002_VBLK_F_0_START_L_OFF, 0x05
> +     },
> +     {
> +             TVP7002_VBLK_F_1_START_L_OFF, 0x05
> +     },
> +     {
> +             TVP7002_VBLK_F_0_DURATION, 0x1e
> +     },
> +     {
> +             TVP7002_VBLK_F_1_DURATION, 0x1e
> +     },
> +     {
> +             TVP7002_FBIT_F_0_START_L_OFF, 0x00
> +     },
> +     {
> +             TVP7002_FBIT_F_1_START_L_OFF, 0x00
> +     },
> +     {
> +             TVP7002_YUV_Y_G_COEF_LSBS, 0xe3
> +     },
> +     {
> +             TVP7002_YUV_Y_G_COEF_MSBS, 0x16
> +     },
> +     {
> +             TVP7002_YUV_Y_B_COEF_LSBS, 0x4f
> +     },
> +     {
> +             TVP7002_YUV_Y_B_COEF_MSBS, 0x02
> +     },
> +     {
> +             TVP7002_YUV_Y_R_COEF_LSBS, 0xce
> +     },
> +     {
> +             TVP7002_YUV_Y_R_COEF_MSBS, 0x06
> +     },
> +     {
> +             TVP7002_YUV_U_G_COEF_LSBS, 0xab
> +     },
> +     {
> +             TVP7002_YUV_U_G_COEF_MSBS, 0xf3
> +     },
> +     {
> +             TVP7002_YUV_U_B_COEF_LSBS, 0x00
> +     },
> +     {
> +             TVP7002_YUV_U_B_COEF_MSBS, 0x10
> +     },
> +     {
> +             TVP7002_YUV_U_R_COEF_LSBS, 0x55
> +     },
> +     {
> +             TVP7002_YUV_U_R_COEF_MSBS, 0xfc
> +     },
> +     {
> +             TVP7002_YUV_V_G_COEF_LSBS, 0x78
> +     },
> +     {
> +             TVP7002_YUV_V_G_COEF_MSBS, 0xf1
> +     },
> +     {
> +             TVP7002_YUV_V_B_COEF_LSBS, 0x88
> +     },
> +     {
> +             TVP7002_YUV_V_B_COEF_MSBS, 0xfe
> +     },
> +     {
> +             TVP7002_YUV_V_R_COEF_LSBS, 0x00
> +     },
> +     {
> +             TVP7002_YUV_V_R_COEF_MSBS, 0x10
> +     },
> +     { /* End of registers */
> +             0x5c, 0x00
> +     }
> +};
> +
> +/* Available resolutions */
> +static struct tvp7002_resol tvp7002_resolutions[] = {
> +     {
> +             .id = V4L2_STD_480I_60,
> +             .hres = 720,
> +             .vres = 480,
> +             .frate = 30,
> +             .lrate = 15,
> +             .prate = 14,
> +             .reg01 = 0x35,
> +             .reg02 = 0xa0,
> +             .reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_576I_50,
> +             .hres = 720,
> +             .vres = 576,
> +             .frate = 25,
> +             .lrate = 16,
> +             .prate = 14,
> +             .reg01 = 0x36,
> +             .reg02 = 0x00,
> +             .reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_480P_60,
> +             .hres = 720,
> +             .vres = 480,
> +             .frate = 60,
> +             .lrate = 31,
> +             .prate = 27,
> +             .reg01 = 0x35,
> +             .reg02 = 0xa0,
> +             .reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_576P_50,
> +             .hres = 720,
> +             .vres = 576,
> +             .frate = 50,
> +             .lrate = 31,
> +             .prate = 27,
> +             .reg01 = 0x36,
> +             .reg02 = 0x00,
> +             .reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_720P_60,
> +             .hres = 1280,
> +             .vres = 720,
> +             .frate = 60,
> +             .lrate = 45,
> +             .prate = 74,
> +             .reg01 = 0x67,
> +             .reg02 = 0x20,
> +             .reg03 = TVP7002_VCO_RANGE_MED | 0x20,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_720P_50,
> +             .hres = 1280,
> +             .vres = 720,
> +             .frate = 50,
> +             .lrate = 38,
> +             .prate = 74,
> +             .reg01 = 0x7b,
> +             .reg02 = 0xc0,
> +             .reg03 = TVP7002_VCO_RANGE_MED | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_1080I_60,
> +             .hres = 1920,
> +             .vres = 1080,
> +             .frate = 60,
> +             .lrate = 34,
> +             .prate = 74,
> +             .reg01 = 0x89,
> +             .reg02 = 0x80,
> +             .reg03 = TVP7002_VCO_RANGE_MED | 0x18,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_1080I_50,
> +             .hres = 1920,
> +             .vres = 1080,
> +             .frate = 50,
> +             .lrate = 28,
> +             .prate = 74,
> +             .reg01 = 0xa5,
> +             .reg02 = 0x00,
> +             .reg03 = TVP7002_VCO_RANGE_MED | 0x10,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_1080P_60,
> +             .hres = 1920,
> +             .vres = 1080,
> +             .frate = 60,
> +             .lrate = 68,
> +             .prate = 149,
> +             .reg01 = 0x89,
> +             .reg02 = 0x80,
> +             .reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
> +             .reg04 = 0x80,
> +     }, {
> +             .id = V4L2_STD_1080P_50,
> +             .hres = 1920,
> +             .vres = 1080,
> +             .frate = 50,
> +             .lrate = 56,
> +             .prate = 149,
> +             .reg01 = 0xa5,
> +             .reg02 = 0x00,
> +             .reg03 = TVP7002_VCO_RANGE_HIGH | 0x18,
> +             .reg04 = 0x80,
> +     },
> +};
> +
> +/*
> + * tvp7002_from_std - Map video standard to register information
> + * @std: v4l2_std_id (u64) integer
> + *
> + * Returns index of std or -1 in case of error.
> + */
> +int tvp7002_from_std(v4l2_std_id std)
> +{
> +     int res;
> +
> +     switch(std){
> +     case V4L2_STD_480P_60:
> +             res = TVP7002_STD_480P;
> +             break;
> +     case V4L2_STD_480I_60:
> +             res = TVP7002_STD_480I;
> +             break;
> +     case V4L2_STD_576P_50:
> +             res = V4L2_STD_576P_50;
> +             break;
> +     case V4L2_STD_576I_50:
> +             res = V4L2_STD_576I_50;
> +             break;
> +     case V4L2_STD_720P_50:
> +             res = V4L2_STD_720P_50;
> +             break;
> +     case V4L2_STD_720P_60:
> +             res = V4L2_STD_720P_60;
> +             break;
> +     case V4L2_STD_1080I_50:
> +             res = V4L2_STD_1080I_50;
> +             break;
> +     case V4L2_STD_1080I_60:
> +             res = V4L2_STD_1080I_60;
> +             break;
> +     case V4L2_STD_1080P_50:
> +             res = V4L2_STD_1080P_50;
> +             break;
> +     case V4L2_STD_1080P_60:
> +             res = V4L2_STD_1080P_60;
> +             break;
> +     default:
> +             res = -1;
> +             break;
> +     }
> +
> +     return res;
> +}
> +
> +/* Device definition */
> +struct tvp7002 {
> +     struct v4l2_subdev sd;
> +     v4l2_std_id video_mode;
> +     int streaming;
> +};
> +
> +/* Supported controls */
> +static struct v4l2_queryctrl tvp7002_qctrl[] = {
> +     {
> +             .id = V4L2_CID_TVP7002_COARSE_GAIN_R,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Coarse gain for R channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_COARSE_GAIN_G,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Coarse gain for G channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_COARSE_GAIN_B,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Coarse gain for B channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_FINE_GAIN_R,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Fine gain for R channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_FINE_GAIN_G,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Fine gain for G channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_FINE_GAIN_B,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Fine gain for B channel",
> +             .minimum = 0,
> +             .maximum = 15,
> +             .step = 1,
> +             .default_value = 7,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_B_CLAMP,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Toggle Blue clamp",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 0,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_G_CLAMP,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Toggle Green clamp",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 0,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_R_CLAMP,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Toggle Red clamp",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 0,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_CLAMP_OFF_EN,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Enable clamp offset",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 0,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_FCTCA,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Fine clamp time cnst adj",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 0,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_F_CLAMP_GB,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Fine clamp for G and B",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 1,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_F_CLAMP_R,
> +             .type = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name = "Fine clamp for Red",
> +             .minimum = 0,
> +             .maximum = 1,
> +             .step = 1,
> +             .default_value = 1,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_CLAMP_START,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Clamp start",
> +             .minimum = 0,
> +             .maximum = 255,
> +             .step = 1,
> +             .default_value = 0x32,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_CLAMP_W,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Clamp width",
> +             .minimum = 0,
> +             .maximum = 255,
> +             .step = 1,
> +             .default_value = 0x20,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_B_COARSE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Blue coarse offset",
> +             .minimum = 0,
> +             .maximum = 32,
> +             .step = 1,
> +             .default_value = 0x10,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_G_COARSE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Green coarse offset",
> +             .minimum = 0,
> +             .maximum = 32,
> +             .step = 1,
> +             .default_value = 0x10,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_R_COARSE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Red coarse offset",
> +             .minimum = 0,
> +             .maximum = 32,
> +             .step = 1,
> +             .default_value = 0x10,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_B_FINE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Blue fine offset",
> +             .minimum = 0,
> +             .maximum = 1024,
> +             .step = 1,
> +             .default_value = 512,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_G_FINE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Green fine offset",
> +             .minimum = 0,
> +             .maximum = 1024,
> +             .step = 1,
> +             .default_value = 512,
> +             .flags = 0,
> +     },
> +     {
> +             .id = V4L2_CID_TVP7002_R_FINE_OFF,
> +             .type = V4L2_CTRL_TYPE_INTEGER,
> +             .name = "Red fine offset",
> +             .minimum = 0,
> +             .maximum = 1024,
> +             .step = 1,
> +             .default_value = 512,
> +             .flags = 0,
> +     },
> +};
> +
> +/*
> + * to_tvp7002 - Obtain device handler TVP7002
> + * @sd: ptr to v4l2_subdev struct
> + *
> + * Returns device handler tvp7002.
> + */
> +static struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd)
> +{
> +     return container_of(sd, struct tvp7002, sd);
> +}
> +
> +/*
> + * tvp7002_read - Read a value from a register in an TVP7002
> + * @sd: ptr to v4l2_subdev struct
> + * @reg: TVP7002 register address
> + *
> + * Returns value read if successful, or non-zero (-1) otherwise.
> + */
> +static int tvp7002_read(struct v4l2_subdev *sd, unsigned char addr)
> +{
> +     int error;
> +     int retry = 0;
> +     struct i2c_client *c = v4l2_get_subdevdata(sd);
> +
> +try_read:
> +     error = i2c_smbus_read_byte_data(c, addr);
> +     if (error == -1){
> +             if (retry <= I2C_RETRY_COUNT){
> +                     v4l2_warn(sd, "TVP7002 Read: retry ... %d\n",
> retry);
> +                     retry++;
> +                     msleep_interruptible(10);
> +                     goto try_read;
> +             }
> +     }
> +
> +     return error;
> +}
> +
> +/*
> + * tvp7002_write() - Write a value to a register in TVP5146/47
> + * @sd: ptr to v4l2_subdev struct
> + * @addr: TVP5146/47 register address

[Hiremath, Vaibhav] Copy-Paste error, you may want to change this to tvp7002.

> + * @value: value to be written to the register
> + *
> + * Write a value to a register in an TVP7002 decoder device.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value)
> +{
> +     int error;
> +     int retry = 0;
> +     struct i2c_client *c = v4l2_get_subdevdata(sd);
> +
> +write_again:
> +     error = i2c_smbus_write_byte_data(c, addr, value);
> +     if (error) {
> +             if (retry <= I2C_RETRY_COUNT) {
> +                     v4l2_warn(sd, "TVP7002 Write: retry ... %d\n",
> retry);
> +                     retry++;
> +                     msleep_interruptible(10);
> +                     goto write_again;
> +             }
> +     }
> +
> +     return error;
> +}
> +
> +/*
> + * dump_reg_range() - Dump information from TVP7002 registers
> + * @sd: ptr to v4l2_subdev struct
> + * @init: TVP7002 start address
> + * @init: TVP7002 end address
[Hiremath, Vaibhav] Should be "end" here.
> + * @nline: register values per line
> + *
[Hiremath, Vaibhav] Do we have this argument coming in?

> + * Dump values at a specified register range
> + * Returns nothing.
> + */
> +static void dump_reg_range(struct v4l2_subdev *sd, u8 init, const
> u8 end)
> +{
> +     int i = 0;
> +     int result;
> +
> +     while (init != (u8)(end + 1)) {
> +
> +             result = tvp7002_read(sd, init);
> +
> +             if (result == -1)
> +                     v4l2_err(sd, "tvp7002: reg 0x%02x unreadable\n",
> i);
> +             else
> +                     v4l2_info(sd, "tvp7002: @0x%02x = %02x\n", i,
> result);
> +
> +             init++;
> +             i++;
> +     }
> +     printk("\n");
> +}
> +
> +/*
> + * tvp7002_log_status() - Print information about register settings
> + * @sd: ptr to v4l2_subdev struct
> + *
> + * Log regsiter values of a TVP7002 decoder device.
> + * Returns zero or -EINVAL if read operation fails.
> + */
> +static int tvp7002_log_status(struct v4l2_subdev *sd)
> +{
> +     int error, rres;
> +
> +     rres = tvp7002_read(sd, TVP7002_CHIP_REV);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> TVP7002_CHIP_REV);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Chip revision number =
> 0x%02x\n",
> +                                                         TVP7002_CHIP_REV);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HPLL_FDBK_DIV_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: H-PLL feedback div LSB =
> 0x%02x\n",
> +                                             TVP7002_HPLL_FDBK_DIV_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HPLL_FDBK_DIV_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: H-PLL feedback div MSB =
> 0x%02x\n",
> +                                             TVP7002_HPLL_FDBK_DIV_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_CRTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> TVP7002_HPLL_CRTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VCO frequency range selector =
> 0x%02x\n",
> +                                                         TVP7002_HPLL_CRTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_PHASE_SEL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_HPLL_PHASE_SEL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: ADC sampling clk phase select =
> 0x%02x\n",
> +                                                     TVP7002_HPLL_PHASE_SEL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_CLAMP_START);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_CLAMP_START);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Clamp start = 0x%02x\n",
> +                                                     TVP7002_CLAMP_START);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_CLAMP_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> TVP7002_CLAMP_W);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Clamp width = 0x%02x\n",
> TVP7002_CLAMP_W);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HSYNC_OUT_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_HSYNC_OUT_W);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: HSYNC output width = 0x%02x\n",
> +                                                     TVP7002_HSYNC_OUT_W);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_B_FINE_GAIN);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_B_FINE_GAIN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain for B ch =
> 0x%02x\n",
> +                                                     TVP7002_B_FINE_GAIN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_G_FINE_GAIN);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_G_FINE_GAIN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain for G ch =
> 0x%02x\n",
> +                                                     TVP7002_G_FINE_GAIN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_FINE_GAIN);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_R_FINE_GAIN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain for R ch =
> 0x%02x\n",
> +                                                     TVP7002_R_FINE_GAIN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_B_FINE_OFF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain off B ch =
> 0x%02x\n",
> +                                             TVP7002_B_FINE_OFF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_G_FINE_OFF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain off G ch =
> 0x%02x\n",
> +                                             TVP7002_G_FINE_OFF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_R_FINE_OFF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Digital fine grain off R ch =
> 0x%02x\n",
> +                                             TVP7002_R_FINE_OFF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_FINE_OFF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Dig fine grain off R ch LSBs =
> 0x%02x\n",
> +                                             TVP7002_FINE_OFF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SYNC_CTL_1);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SYNC_CTL_1);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: SYNC control 1 = 0x%02x\n",
> +                                             TVP7002_SYNC_CTL_1);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_AND_CLAMP_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HPLL_AND_CLAMP_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: H-PLL and clamp control =
> 0x%02x\n",
> +                                             TVP7002_HPLL_AND_CLAMP_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SYNC_ON_G_THRS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Sync-On-Green threshold =
> 0x%02x\n",
> +                                             TVP7002_SYNC_ON_G_THRS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SYNC_SEPARATOR_THRS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SYNC_SEPARATOR_THRS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Sync separator threshold =
> 0x%02x\n",
> +                                             TVP7002_SYNC_SEPARATOR_THRS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_PRE_COAST);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HPLL_PRE_COAST);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: H-PLL pre-coast = 0x%02x\n",
> +                                             TVP7002_HPLL_PRE_COAST);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HPLL_POST_COAST);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HPLL_POST_COAST);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: H-PLL post-coast = 0x%02x\n",
> +                                             TVP7002_HPLL_POST_COAST);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SYNC_DETECT_STAT);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SYNC_DETECT_STAT);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Sync detect status = 0x%02x\n",
> +                                             TVP7002_SYNC_DETECT_STAT);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_OUT_FORMATTER);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_OUT_FORMATTER);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Output formatter = 0x%02x\n",
> +                                             TVP7002_OUT_FORMATTER);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MISC_CTL_1);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MISC_CTL_1);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Miscelaneous control 1 =
> 0x%02x\n",
> +                                             TVP7002_MISC_CTL_1);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MISC_CTL_2);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MISC_CTL_2);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Miscelaneous control 2 =
> 0x%02x\n",
> +                                             TVP7002_MISC_CTL_2);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MISC_CTL_3);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MISC_CTL_3);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Miscelaneous control 3 =
> 0x%02x\n",
> +                                             TVP7002_MISC_CTL_3);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MISC_CTL_3);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MISC_CTL_3);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Miscelaneous control 3 =
> 0x%02x\n",
> +                                             TVP7002_MISC_CTL_3);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_IN_MUX_SEL_1);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_IN_MUX_SEL_1);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Input Mux Selector 1 =
> 0x%02x\n",
> +                                             TVP7002_IN_MUX_SEL_1);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_IN_MUX_SEL_2);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_IN_MUX_SEL_2);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Input Mux Selector 1 =
> 0x%02x\n",
> +                                             TVP7002_IN_MUX_SEL_2);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_B_AND_G_COARSE_GAIN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: B and G coarse gain = 0x%02x\n",
> +                                             TVP7002_B_AND_G_COARSE_GAIN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_COARSE_GAIN);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_R_COARSE_GAIN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: R coarse gain = 0x%02x\n",
> +                                             TVP7002_R_COARSE_GAIN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_B_COARSE_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_B_COARSE_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Coarse offset for B ch =
> 0x%02x\n",
> +                                             TVP7002_B_COARSE_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_G_COARSE_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_G_COARSE_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Coarse offset for G ch =
> 0x%02x\n",
> +                                             TVP7002_G_COARSE_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_R_COARSE_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Coarse offset for R ch =
> 0x%02x\n",
> +                                             TVP7002_R_COARSE_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_R_COARSE_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Coarse offset for R ch =
> 0x%02x\n",
> +                                             TVP7002_R_COARSE_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HSOUT_OUT_START);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_HSOUT_OUT_START);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: HSYNC lead edge out start =
> 0x%02x\n",
> +                                             TVP7002_HSOUT_OUT_START);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MISC_CTL_4);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MISC_CTL_4);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Miscelaneous control 4 =
> 0x%02x\n",
> +                                             TVP7002_MISC_CTL_4);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_B_DGTL_ALC_OUT_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_B_DGTL_ALC_OUT_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Filt ALC out for B ch LSBs =
> 0x%02x\n",
> +                                             TVP7002_B_DGTL_ALC_OUT_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_G_DGTL_ALC_OUT_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_G_DGTL_ALC_OUT_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Filt ALC out for G ch LSBs =
> 0x%02x\n",
> +                                             TVP7002_G_DGTL_ALC_OUT_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_R_DGTL_ALC_OUT_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_R_DGTL_ALC_OUT_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Filt ALC out for R ch LSBs =
> 0x%02x\n",
> +                                             TVP7002_R_DGTL_ALC_OUT_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_ENABLE);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AUTO_LVL_CTL_ENABLE);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Auto level control enable =
> 0x%02x\n",
> +                                             TVP7002_AUTO_LVL_CTL_ENABLE);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_DGTL_ALC_OUT_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_DGTL_ALC_OUT_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Filt ALC out RGB chs MSB =
> 0x%02x\n",
> +                                             TVP7002_DGTL_ALC_OUT_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_FILTER);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AUTO_LVL_CTL_FILTER);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Auto level control filter =
> 0x%02x\n",
> +                                             TVP7002_AUTO_LVL_CTL_FILTER);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_FINE_CLAMP_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Fine clamp control = 0x%02x\n",
> +                                             TVP7002_FINE_CLAMP_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_PWR_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_PWR_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Power control = 0x%02x\n",
> +                                                     TVP7002_PWR_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_ADC_SETUP);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_ADC_SETUP);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: ADC setup = 0x%02x\n",
> +                                                     TVP7002_ADC_SETUP);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_COARSE_CLAMP_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_COARSE_CLAMP_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Coarse clamp control =
> 0x%02x\n",
> +                                             TVP7002_COARSE_CLAMP_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SOG_CLAMP);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SOG_CLAMP);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Sync-On-Green clamp = 0x%02x\n",
> +                                             TVP7002_SOG_CLAMP);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_RGB_COARSE_CLAMP_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_RGB_COARSE_CLAMP_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: RGB coarse clamp control =
> 0x%02x\n",
> +                                             TVP7002_RGB_COARSE_CLAMP_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SOG_COARSE_CLAMP_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_SOG_COARSE_CLAMP_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: SOG coarse clamp control =
> 0x%02x\n",
> +                                             TVP7002_SOG_COARSE_CLAMP_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_ALC_PLACEMENT);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_ALC_PLACEMENT);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: ALC placement = 0x%02x\n",
> +                                             TVP7002_ALC_PLACEMENT);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MVIS_STRIPPER_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_MVIS_STRIPPER_W);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Macrovision stripper width =
> 0x%02x\n",
> +                                                     TVP7002_VSYNC_ALGN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_MVIS_STRIPPER_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_VSYNC_ALGN);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VSYNC alignment = 0x%02x\n",
> +                                                     TVP7002_VSYNC_ALGN);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_SYNC_BYPASS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_SYNC_BYPASS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Sync bypass = 0x%02x\n",
> +                                                     TVP7002_SYNC_BYPASS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_L_FRAME_STAT_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_L_FRAME_STAT_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Lines p Frame status LSBs =
> 0x%02x\n",
> +                                             TVP7002_L_FRAME_STAT_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_L_FRAME_STAT_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_L_FRAME_STAT_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Lines p Frame status MSBs =
> 0x%02x\n",
> +                                             TVP7002_L_FRAME_STAT_MSBS);
> +     }
> +
> +
> +     rres = tvp7002_read(sd, TVP7002_CLK_L_STAT_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_CLK_L_STAT_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Clks p line status LSBs =
> 0x%02x\n",
> +                                             TVP7002_CLK_L_STAT_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_CLK_L_STAT_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_CLK_L_STAT_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Clks p line status MSBs =
> 0x%02x\n",
> +                                             TVP7002_CLK_L_STAT_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_HSYNC_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_HSYNC_W);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: HSYNC width = 0x%02x\n",
> +                                                     TVP7002_HSYNC_W);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VSYNC_W);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_VSYNC_W);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VSYNC width = 0x%02x\n",
> +                                                     TVP7002_VSYNC_W);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_L_LENGTH_TOL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                                     TVP7002_L_LENGTH_TOL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Line length tolerance =
> 0x%02x\n",
> +                                                     TVP7002_L_LENGTH_TOL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VIDEO_BWTH_CTL);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_VIDEO_BWTH_CTL);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: Video bandwidth control =
> 0x%02x\n",
> +                                             TVP7002_VIDEO_BWTH_CTL);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AVID_START_PIXEL_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AVID_START_PIXEL_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: AVID start pixel LSBs =
> 0x%02x\n",
> +                                             TVP7002_AVID_START_PIXEL_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AVID_START_PIXEL_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AVID_START_PIXEL_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: AVID start pixel MSBs =
> 0x%02x\n",
> +                                             TVP7002_AVID_START_PIXEL_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AVID_STOP_PIXEL_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: AVID stop pixel LSBs =
> 0x%02x\n",
> +                                             TVP7002_AVID_STOP_PIXEL_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_AVID_STOP_PIXEL_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: AVID stop pixel MSBs =
> 0x%02x\n",
> +                                             TVP7002_AVID_STOP_PIXEL_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VBLK_F_0_START_L_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_VBLK_F_0_START_L_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VBLK start line offset 0 =
> 0x%02x\n",
> +                                             TVP7002_VBLK_F_0_START_L_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VBLK_F_1_START_L_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_VBLK_F_1_START_L_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VBLK start line offset 1 =
> 0x%02x\n",
> +                                             TVP7002_VBLK_F_1_START_L_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VBLK_F_0_DURATION);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_VBLK_F_0_DURATION);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VBLK duration 0 = 0x%02x\n",
> +                                             TVP7002_VBLK_F_0_DURATION);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_VBLK_F_1_DURATION);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_VBLK_F_1_DURATION);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: VBLK duration 1 = 0x%02x\n",
> +                                             TVP7002_VBLK_F_1_DURATION);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_FBIT_F_0_START_L_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_FBIT_F_0_START_L_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: F-bit start line offset 0 =
> 0x%02x\n",
> +                                             TVP7002_FBIT_F_0_START_L_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_FBIT_F_1_START_L_OFF);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_FBIT_F_1_START_L_OFF);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: F-bit start line offset 1 =
> 0x%02x\n",
> +                                             TVP7002_FBIT_F_1_START_L_OFF);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_G_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y G LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_G_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_G_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y G MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_G_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_B_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y B LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_B_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_B_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y B MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_B_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_R_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y R LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_R_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_Y_R_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV Y R MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_Y_R_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_G_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_G_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U G LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_G_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_G_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_G_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U G MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_G_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_B_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_B_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U B LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_B_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_B_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_B_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U B MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_B_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_R_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_R_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U R LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_R_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_U_R_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_U_R_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV U R MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_U_R_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_G_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_G_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V G LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_G_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_G_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_G_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V G MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_G_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_B_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_B_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V B LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_B_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_B_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_B_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V B MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_B_COEF_MSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_R_COEF_LSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_R_COEF_LSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V R LSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_R_COEF_LSBS);
> +     }
> +
> +     rres = tvp7002_read(sd, TVP7002_YUV_V_R_COEF_MSBS);
> +     if (rres == -1){
> +             v4l2_err(sd, "tvp7002: error reading 0x%02x\n",
> +                                             TVP7002_YUV_V_R_COEF_MSBS);
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     else {
> +             v4l2_info(sd, "tvp7002: YUV V R MSBs = 0x%02x\n",
> +                                             TVP7002_YUV_V_R_COEF_MSBS);
> +     }
> +
[Hiremath, Vaibhav] Can we have some macro/inline function based implementation here?

> +     error = 0;
> +
> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_g_chip_ident() - Get chip identification number
> + * @sd: ptr to v4l2_subdev struct
> + * @chip: ptr to v4l2_dbg_chip_ident struct
> + *
> + * Obtains the chip's identification number.
> + * Returns zero or -EINVAL if read operation fails.
> + */
> +static int tvp7002_g_chip_ident(struct v4l2_subdev *sd,
> +                                     struct v4l2_dbg_chip_ident *chip)
> +{
> +     int rev;
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +
> +     rev = tvp7002_read(sd, TVP7002_CHIP_REV);
> +
> +     if (rev == -1)
> +             return -EINVAL;
> +     else
> +             return v4l2_chip_ident_i2c_client(client, chip,
> +                                             V4L2_IDENT_TVP7002, rev);
> +}
> +
> +/*
> + * tvp7002_write_inittab() - Write initialization values
> + * @sd: ptr to v4l2_subdev struct
> + * @regs: ptr to i2c_reg_value struct
> + *
> + * Write initialization values.
> + * Returns zero or -EINVAL if read operation fails.
> + */
> +static int tvp7002_write_inittab(struct v4l2_subdev *sd,
> +                                     const struct i2c_reg_value *regs)
> +{
> +     int i;
> +     int error;
> +     /* Initialize the first (defined) registers */
> +     while (regs->reg != 0x5c) {
> +             error = tvp7002_write(sd, regs->reg, regs->value);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
[Hiremath, Vaibhav] No need for goto, you can directly return from here.
> +             }
> +             else {
> +                     regs++;
> +             }
> +     }
> +     /* Initialize the last (undefined) registers */
> +     for (i = 0x5c; i <= 0xff; i++){
> +             error = tvp7002_write(sd, i, 0x00);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     regs++;
> +             }
> +     }
[Hiremath, Vaibhav] I am not sure whether this is really required here, since they are undefined.

> +
> +     error = 0;
> +
> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_set_video_mode()
> + * @sd: pointer to standard V4L2 sub-device structure
> + * @sdf: index to structure describing format
> + *
> + * Set video standard according to index
> + *
> + * Returns 0 if operation is successful or -EINVAL otherwise
> + */
> +static int tvp7002_set_video_mode(struct v4l2_subdev *sd, int sdf)
> +{
> +     int error;
> +
> +     if (sdf < TVP7002_STD_480I || sdf > TVP7002_STD_1080P_50){
> +             v4l2_err(sd, "tvp7002: sf out of range\n");
> +             error = -ERANGE;
> +             goto found_error;
> +     }
> +
> +     /* Print specific information about current format */
> +     v4l2_info(sd, "tvp7002: Setting standard display
> format...\n");
> +     v4l2_info(sd, "tvp7002: hres = %d vres=%d fr=%d lr=%d
> prate=%d\n",
> +                     tvp7002_resolutions[sdf].hres,
> +                     tvp7002_resolutions[sdf].vres,
> +                     tvp7002_resolutions[sdf].frate,
> +                     tvp7002_resolutions[sdf].lrate,
> +                     tvp7002_resolutions[sdf].prate);
> +     /* Set registers accordingly */
> +     error = tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_MSBS,
> +                                     tvp7002_resolutions[sdf].reg01);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     error = tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_LSBS,
> +                                     tvp7002_resolutions[sdf].reg02);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     error = tvp7002_write(sd, TVP7002_HPLL_CRTL,
> tvp7002_resolutions[sdf].reg03);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     error =  tvp7002_write(sd, TVP7002_HPLL_PHASE_SEL,
> +                                     tvp7002_resolutions[sdf].reg04);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     /* Set SD/HD mode registers */
> +
> +     if (sdf < TVP7002_STD_720P_60){
> +             error = tvp7002_write(sd, TVP7002_CLAMP_START, 0x06);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_CLAMP_W, 0x10);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x03);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_HPLL_POST_COAST,
> 0x03);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0x17);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             if (sdf < TVP7002_STD_480P){
> +                     error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START,
> 0x0c);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +                     error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W,
> 0x24);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +             else {
> +                     error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START,
> 0x0a);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +                     error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W,
> 0x12);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +             error = tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x08);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x18);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +     }
> +     else {
> +             error = tvp7002_write(sd, TVP7002_CLAMP_START, 0x32);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_CLAMP_W, 0x20);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x01);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_HPLL_POST_COAST,
> 0x00);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0xc7);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             if(sdf < TVP7002_STD_1080I_60){
> +                     error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START,
> 0x35);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +             else {
> +                     error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START,
> 0x39);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +             error = tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x00);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x5a);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             if(sdf < TVP7002_STD_1080P_60){
> +                     error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W,
> 0x07);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +             else {
> +                     error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W,
> 0x03);
> +                     if (error == -1){
> +                             error = -EINVAL;
> +                             goto found_error;
> +                     }
> +             }
> +     }
> +     if (sdf < TVP7002_STD_1080P_60){
> +             error = tvp7002_write(sd, TVP7002_ADC_SETUP, 0x50);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x0f);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +     }
> +     else {
> +             error = tvp7002_write(sd, TVP7002_ADC_SETUP, 0x80);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +             error = tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x00);
> +             if (error == -1){
> +                     error = -EINVAL;
> +                     goto found_error;
> +             }
> +     }
> +     /* Set up registers that hold the same value regardless of the
> +      * SD mode
> +      */
> +     error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 0x5d);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     error = tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     error = 0;
> +
[Hiremath, Vaibhav] I think there is no need for goto here, since we are not cleaning up anything on failure. So we can return directly.
Applies to all the places of I2C read/write.

> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_get_video_mode() - V4L2 decoder interface handler for
> querystd
> + * @sd: pointer to standard V4L2 sub-device structure
> + *
> + * Returns the current standard detected by TVP7002. If no active
> input is
> + * detected, returns -1
> + */
> +static v4l2_std_id tvp7002_get_video_mode(struct v4l2_subdev *sd){
> +     int error;
> +     int reg01, reg02, reg03;
> +     reg01 = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_MSBS);
> +     reg02 = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_LSBS);
> +     reg03 = tvp7002_read(sd, TVP7002_HPLL_CRTL);
> +
> +     if (reg01 == -1 || reg02 == -1 || reg03 == -1){
> +             error = -1;
> +             goto found_error;
> +     }
> +
> +     switch(reg01){
> +     case 0x35:
> +             if (reg02 == 0xa0)
> +                     error = V4L2_STD_480I_60;
> +             else
> +                     error = V4L2_STD_576I_50;
> +     case 0x36:
> +             if (reg02 == 0xa0)
> +                     error = V4L2_STD_480P_60;
> +             else
> +                     error = V4L2_STD_576P_50;
> +     case 0x67:
> +             error = V4L2_STD_720P_60;
> +     case 0x7b:
> +             error = V4L2_STD_720P_50;
> +     case 0x89:
> +             if (reg03 == 0x98)
> +                     error = V4L2_STD_1080I_60;
> +             else
> +                     error = V4L2_STD_1080P_60;
> +     case 0xa5:
> +             if (reg03 == 0x90)
> +                     error = V4L2_STD_1080I_50;
> +             else
> +                     error = V4L2_STD_1080P_50;
> +     default:
> +             error = -1;
> +     }
> +
> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_querystd() - V4L2 decoder interface handler for querystd
> + * @sd: pointer to standard V4L2 sub-device structure
> + * @std_id: standard V4L2 std_id ioctl enum
> + *
> + * Returns the current standard detected by TVP7002. If no active
> input is
> + * detected, returns -EINVAL
> + */
> +static int tvp7002_querystd(struct v4l2_subdev *sd, v4l2_std_id
> *std_id)
> +{
> +     struct tvp7002 *decoder = to_tvp7002(sd);
> +     v4l2_std_id current_std;
> +     u8 sync_lock_status, lock_mask;
> +
> +     if (std_id == NULL)
> +             return -EINVAL;
> +
> +     /* get the current standard */
> +     current_std = tvp7002_get_video_mode(sd);
> +     if (current_std == -1)
> +             return -EINVAL;
> +
> +     /* check whether signal is locked */
> +     sync_lock_status = tvp7002_read(sd, TVP7002_SYNC_DETECT_STAT);
> +
> +     if (0x02 != (sync_lock_status & 0xff))
> +             return -EINVAL; /* No input detected */
> +
> +     decoder->video_mode = current_std;
> +     *std_id = current_std;
> +
> +     v4l2_info(sd, "Current STD: %s", decoder->video_mode);
> +     return 0;
> +}
> +
> +/**
> + * tvp7002_g_fmt() - V4L2 decoder interface handler for
> tvp7002_g_fmt
> + * @sd: pointer to standard V4L2 sub-device structure
> + * @f: pointer to standard V4L2 v4l2_format structure
> + *
> + * Returns the decoder's current pixel format in the v4l2_format
> + * parameter.
> + */
> +static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format
> *f)
> +{
> +     struct tvp7002 *decoder = to_tvp7002(sd);
> +
> +     if (f == NULL)
> +             return -EINVAL;
> +
> +     if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +             /* only capture is supported */
> +             return -EINVAL;
> +
> +/*   f->fmt.pix = decoder->pix;
> +
> +     v4l2_info(sd, "Current FMT: bytesperline - %d"
> +                     "Width - %d, Height - %d",
> +                     decoder->pix.bytesperline,
> +                     decoder->pix.width, decoder->pix.height);*/
[Hiremath, Vaibhav] This is commented, is this intentional or mistake?

> +     return 0;
> +}
> +
> +/*
> + * tvp7002_s_ctrl() - Set a control
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to v4l2_control struct
> + *
> + * Set a control for a TVP7002 decoder device.
> + * Returns zero when successful or -EINVAL if register access
> fails.
> + */
> +static int tvp7002_s_std(struct v4l2_subdev *sd, v4l2_std_id std){
> +     struct tvp7002 *decoder = to_tvp7002(sd);
> +     int vmd = 0;
> +
> +     decoder->video_mode = std;
> +     vmd = tvp7002_from_std(std);
> +
> +     v4l2_info(sd, "Set video std mode to %d.\n", (int)std);
> +
> +     return tvp7002_set_video_mode(sd, vmd);
> +}
> +
> +/*
> + * tvp7002_g_ctrl() - Get a control
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to v4l2_control struct
> + *
> + * Get a control for a TVP7002 decoder device.
> + * Returns zero when successful or -EINVAL if register access
> fails.
> + */
> +static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct
> v4l2_control *ctrl){
> +     int res;
> +     int tmp;
> +
> +     v4l2_info(sd, "tvp7002: g_ctrl called\n");
> +
> +     switch (ctrl->id) {
> +     case V4L2_CID_TVP7002_COARSE_GAIN_R:
> +             res = tvp7002_read(sd, TVP7002_R_COARSE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x0F;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_COARSE_GAIN_G:
> +             res = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res & 0xF0) >> 4;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_COARSE_GAIN_B:
> +             res = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x0F;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_R:
> +             res = tvp7002_read(sd, TVP7002_R_FINE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0xFF;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_G:
> +             res = tvp7002_read(sd, TVP7002_G_FINE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0xFF;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_B:
> +             res = tvp7002_read(sd, TVP7002_B_FINE_GAIN);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0xFF;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_B_CLAMP:
> +             res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res >> 2) & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_G_CLAMP:
> +             res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res >> 1) & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_R_CLAMP:
> +             res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_OFF_EN:
> +             res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res >> 7) & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_FCTCA:
> +             res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (((res >> 3) & 0x03) == 0x03) ? 1 :
> 0;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_F_CLAMP_GB:
> +             res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res >> 1) & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_F_CLAMP_R:
> +             res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x01;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_START:
> +             res = tvp7002_read(sd, TVP7002_CLAMP_START);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0xff;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_W:
> +             res = tvp7002_read(sd, TVP7002_CLAMP_W);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0xff;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_B_COARSE_OFF:
> +             res = tvp7002_read(sd, TVP7002_B_COARSE_OFF);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x3f;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_G_COARSE_OFF:
> +             res = tvp7002_read(sd, TVP7002_G_COARSE_OFF);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x3f;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_R_COARSE_OFF:
> +             res = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
> +             if (res == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = res & 0x3f;
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_B_FINE_OFF:
> +             res = tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS);
> +             tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
> +             if (res == -1 || tmp == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res << 2) | (tmp & 0x03);
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_G_FINE_OFF:
> +             res = tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS);
> +             tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
> +             if (res == -1 || tmp == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res << 2) | ((tmp >> 2) & 0x03);
> +                     res = ctrl->value;
> +             }
> +             break;
> +     case V4L2_CID_TVP7002_R_FINE_OFF:
> +             res = tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS);
> +             tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
> +             if (res == -1 || tmp == -1){
> +                     res = -EINVAL;
> +                     goto found_error;
> +             }
> +             else {
> +                     ctrl->value = (res << 2) | ((tmp >> 4) & 0x03);
> +                     res = ctrl->value;
> +             }
[Hiremath, Vaibhav] All the above cases we can implement something -

case V4L2_CID_TVP7002_R_FINE_OFF:
        res = tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS);
        if (res != -1){
                ctrl->value = (res << 2) | ((tmp >> 4) & 0x03);
                res = ctrl->value;
        }
        Break;

This will directly return the error value returned by I2C read in res.

> +             break;
> +     default:
> +             res = -EINVAL;
> +             break;
> +     }
> +
> +found_error:
> +     return res;
> +}
> +
> +/*
> + * tvp7002_s_ctrl() - Set a control
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to v4l2_control struct
> + *
> + * Set a control in TVP7002 decoder device.
> + * Returns zero when successful or -EINVAL if register access
> fails.
> + */
> +static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct
> v4l2_control *ctrl)
> +{
> +     int error;
> +     u8 i, n;
> +     n = ARRAY_SIZE(tvp7002_qctrl);
> +
> +     for (i = 0; i < n; i++) {
> +             if (ctrl->id != tvp7002_qctrl[i].id)
> +                     continue;
> +
> +             if (ctrl->value < tvp7002_qctrl[i].minimum ||
> +                 ctrl->value > tvp7002_qctrl[i].maximum)
> +                     return -ERANGE;
> +             v4l2_err(sd, "s_ctrl: id=%d, value=%d\n", ctrl->id,
> +                                                             ctrl->value);
> +             break;
> +     }
> +
> +     switch (ctrl->id) {
> +     case V4L2_CID_TVP7002_COARSE_GAIN_R:
> +             error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN,
> +                                                     ctrl->value & 0xff);
> +             break;
> +     case V4L2_CID_TVP7002_COARSE_GAIN_G:
> +             error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN,
> +                                             (ctrl->value << 4) & 0xf0);
> +             break;
> +     case V4L2_CID_TVP7002_COARSE_GAIN_B:
> +             error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN,
> +                                             ctrl->value& 0x0f);
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_R:
> +             error = tvp7002_write(sd, TVP7002_R_FINE_GAIN,
> +                                                     ctrl->value & 0xff);
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_G:
> +             error = tvp7002_write(sd, TVP7002_G_FINE_GAIN,
> +                                             (ctrl->value << 4) & 0xf0);
> +             break;
> +     case V4L2_CID_TVP7002_FINE_GAIN_B:
> +             error = tvp7002_write(sd, TVP7002_B_FINE_GAIN,
> +                                                     ctrl->value& 0x0f);
> +             break;
> +     case V4L2_CID_TVP7002_B_CLAMP:
> +             error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS,
> +                                             (ctrl->value << 2) & 0x04);
> +             break;
> +     case V4L2_CID_TVP7002_G_CLAMP:
> +             error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS,
> +                                             (ctrl->value << 1) & 0x02);
> +             break;
> +     case V4L2_CID_TVP7002_R_CLAMP:
> +             error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS,
> +                                                     ctrl->value & 0x01);
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_OFF_EN:
> +             error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL,
> +                                             (ctrl->value << 7) & 0x80);
> +             break;
> +     case V4L2_CID_TVP7002_FCTCA:
> +             error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL,
> +                         ((ctrl->value == 0 ? 0x00 : 0x03) << 3) &
> 0x0c);
> +             break;
> +     case V4L2_CID_TVP7002_F_CLAMP_GB:
> +             error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL,
> +                                             (ctrl->value << 1) & 0x02);
> +             break;
> +     case V4L2_CID_TVP7002_F_CLAMP_R:
> +             error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL,
> +                                                     ctrl->value & 0x01);
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_START:
> +             error = tvp7002_write(sd, TVP7002_CLAMP_START,
> +                                                     ctrl->value & 0xff);
> +             break;
> +     case V4L2_CID_TVP7002_CLAMP_W:
> +             error = tvp7002_write(sd, TVP7002_CLAMP_W, ctrl->value &
> 0xff);
> +             break;
> +     case V4L2_CID_TVP7002_B_COARSE_OFF:
> +             error = tvp7002_write(sd, TVP7002_B_COARSE_OFF,
> +                                                     ctrl->value & 0x3f);
> +             break;
> +     case V4L2_CID_TVP7002_G_COARSE_OFF:
> +             error = tvp7002_write(sd, TVP7002_G_COARSE_OFF,
> +                                                     ctrl->value & 0x3f);
> +             break;
> +     case V4L2_CID_TVP7002_R_COARSE_OFF:
> +             error = tvp7002_write(sd, TVP7002_R_COARSE_OFF,
> +                                                     ctrl->value & 0x3f);
> +             break;
> +     case V4L2_CID_TVP7002_B_FINE_OFF:
> +             error = tvp7002_write(sd, TVP7002_B_FINE_OFF_MSBS,
> +                                             (ctrl->value & 0xff) >> 2) |
> +                     tvp7002_write(sd, TVP7002_FINE_OFF_LSBS,
> +                                             ctrl->value & 0x03);
> +             break;
> +     case V4L2_CID_TVP7002_G_FINE_OFF:
> +             error = tvp7002_write(sd, TVP7002_G_FINE_OFF_MSBS,
> +                                             (ctrl->value & 0xff) >> 2) |
> +                     tvp7002_write(sd, TVP7002_FINE_OFF_LSBS,
> +                                             (ctrl->value & 0x03) << 2);
> +             break;
> +     case V4L2_CID_TVP7002_R_FINE_OFF:
> +             error = tvp7002_write(sd, TVP7002_R_FINE_OFF_MSBS,
> +                                             (ctrl->value & 0xff) >> 2) |
> +                     tvp7002_write(sd, TVP7002_FINE_OFF_LSBS,
> +                                             (ctrl->value & 0x03) << 4);
> +             break;
> +     default:
> +             error = -1;
> +             break;
> +     }
> +
> +     if (error == -1)
> +             return -EINVAL;
> +     else
> +             return 0;
> +}
> +
> +/*
> + * tvp7002_g_register() - Get the value of a register
> + * @sd: ptr to v4l2_subdev struct
> + * @vreg: ptr to v4l2_dbg_register struct
> + *
> + * Get the value of a TVP7002 decoder device register.
> + * Returns zero when successful, -EINVAL if register read fails or
> + * access to I2C client fails, -EPERM if the call is not allowed
> + * by diabled CAP_SYS_ADMIN.
> + */
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +static int tvp7002_g_register(struct v4l2_subdev *sd,
> +                                             struct v4l2_dbg_register *reg)
> +{
> +     int error;
> +
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +
> +     if (!v4l2_chip_match_i2c_client(client, &reg->match)){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     if (!capable(CAP_SYS_ADMIN)){
> +             error = -EPERM;
> +             goto found_error;
> +     }
> +
> +     reg->val = tvp7002_read(sd, reg->reg & 0xff);
> +     reg->size = 1;
> +
> +     if (reg->val == -1)
> +             error = -EINVAL;
> +     else
> +             error = 0;
> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_s_register() - set a control
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to v4l2_control struct
> + *
> + * Get the value of a TVP7002 decoder device register.
> + * Returns zero when successful or -EINVAL if register read fails.
> + */
> +static int tvp7002_s_register(struct v4l2_subdev *sd,
> +                                             struct v4l2_dbg_register *reg)
> +{
> +     int error, wres;
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +
> +     if (!v4l2_chip_match_i2c_client(client, &reg->match)){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +     if (!capable(CAP_SYS_ADMIN)){
> +             error = -EPERM;
> +             goto found_error;
> +     }
> +
> +     wres = tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff);
> +
> +     if (wres == -1)
> +             error = -EINVAL;
> +     else
> +             error = 0;
> +
> +found_error:
> +     return error;
> +}
> +#endif
> +
> +/*
> + * tvp7002_queryctrl() - Query a control
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to v4l2_queryctrl struct
> + *
> + * Query a control of a TVP7002 decoder device.
> + * Returns zero when successful or -EINVAL if register read fails.
> + */
> +static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct
> v4l2_queryctrl *qc)
> +{
> +     int i, error;
> +
> +     v4l2_info(sd, "tvp7002: queryctrl called\n");
> +
> +     for (i = 0; i < ARRAY_SIZE(tvp7002_qctrl); i++)
> +             if (qc->id && qc->id == tvp7002_qctrl[i].id) {
> +                     memcpy(qc, &(tvp7002_qctrl[i]), sizeof(*qc));
> +                     error = 0;
> +             }
> +
> +     error = -EINVAL;
> +
> +     return error;
[Hiremath, Vaibhav] I am confused here, what are you trying to do here. Queryctrl will always be return -EINVAL.

Thanks,
Vaibhav
> +}
> +
> +/**
> + * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream
> + * @sd: pointer to standard V4L2 sub-device structure
> + * @enable: streaming enable or disable
> + *
> + * Sets streaming to enable or disable, if possible.
> + */
> +static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable)
> +{
> +     int err = 0;
> +     struct tvp7002 *decoder = to_tvp7002(sd);
> +
> +     if (decoder->streaming == enable)
> +             return 0;
> +
> +     switch (enable) {
> +     case 0:
> +             {
> +                     /* Power Down Sequence */
> +                     err = tvp7002_write(sd, TVP7002_PWR_CTL, 0x40);
> +                     if (err) {
> +                             v4l2_err(sd, "Unable to turn off
> decoder\n");
> +                             return err;
> +                     }
> +                     decoder->streaming = enable;
> +                     break;
> +             }
> +     case 1:
> +             {
> +                     /* Power Up Sequence */
> +                     err = tvp7002_write(sd, TVP7002_PWR_CTL, 0x00);
> +                     if (err) {
> +                             v4l2_err(sd, "Unable to turn on decoder\n");
> +                             err = -EINVAL;
> +                     }
> +                     err = tvp7002_write_inittab(sd,
> tvp7002_init_default);
> +                     if (err == -1) {
> +                             v4l2_err(sd, "Unable to initialize\n");
> +                             err = -EINVAL;
> +                     }
> +                     /* Detect if not already detected */
> +                     err = tvp7002_read(sd, TVP7002_CHIP_REV);
> +                     if (err == -1) {
> +                             v4l2_err(sd, "Unable to detect decoder\n");
> +                             err = -EINVAL;
> +                     }
> +                     decoder->streaming = enable;
> +                     break;
> +             }
> +     default:
> +             {
> +                     err = -ENODEV;
> +                     break;
> +             }
> +     }
> +
> +     return err;
> +}
> +
> +/* Specific video subsystem operation handlers */
> +static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
> +     .querystd = tvp7002_querystd,
> +     .s_stream = tvp7002_s_stream,
> +     .g_fmt = tvp7002_g_fmt,
> +};
> +
> +/* V4L2 Operations handlers */
> +static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
> +     .g_chip_ident = tvp7002_g_chip_ident,
> +     .log_status = tvp7002_log_status,
> +     .g_ctrl = tvp7002_g_ctrl,
> +     .s_ctrl = tvp7002_s_ctrl,
> +     .queryctrl = tvp7002_queryctrl,
> +     .s_std = tvp7002_s_std,
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +     .g_register = tvp7002_g_register,
> +     .s_register = tvp7002_s_register,
> +#endif
> +};
> +
> +static const struct v4l2_subdev_ops tvp7002_ops = {
> +     .core = &tvp7002_core_ops,
> +     .video = &tvp7002_video_ops,
> +};
> +
> +/*
> + * tvp7002_reset - Reset a TVP7002 device
> + * @sd: ptr to v4l2_subdev struct
> + * @val: unsigned integer (not used)
> + *
> + * Reset the TVP7002 device
> + * Returns zero when successful or -EINVAL if register read fails.
> + */
> +static int tvp7002_reset(struct v4l2_subdev *sd, u32 val)
> +{
> +     int error;
> +     int polarity;
> +
> +     error = tvp7002_read(sd, TVP7002_CHIP_REV);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     if (error == 0x02)
> +             v4l2_info(sd, "tvp7002: rev. %02x detected.\n", error);
> +
> +     else {
> +             v4l2_info(sd, "tvp7002: unknown revision detected.\n");
> +             v4l2_info(sd, "tvp7002: revision number is %02x\n",
> error);
> +     }
> +
> +     /* Set polarity information */
> +     polarity = tvp7002_pdata.clk_polarity &
> tvp7002_pdata.hs_polarity &
> +                tvp7002_pdata.vs_polarity &
> tvp7002_pdata.fid_polarity;
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_2, polarity);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     /* Initializes TVP7002 to its default values */
> +     error = tvp7002_write_inittab(sd, tvp7002_init_default);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +found_error:
> +     return error;
> +};
> +
> +/*
> + * tvp7002_probe - Reset a TVP7002 device
> + * @sd: ptr to v4l2_subdev struct
> + * @ctrl: ptr to i2c_device_id struct
> + *
> + * Reset the TVP7002 device
> + * Returns zero when successful or -EINVAL if register read fails.
> + */
> +static int tvp7002_probe(struct i2c_client *c, const struct
> i2c_device_id *id)
> +{
> +     int error;
> +     int polarity;
> +     struct tvp7002 *core;
> +     struct v4l2_subdev *sd;
> +
> +     /* Check if the adapter supports the needed features */
> +     if (!i2c_check_functionality(c->adapter,
> +          I2C_FUNC_SMBUS_READ_BYTE |
> I2C_FUNC_SMBUS_WRITE_BYTE_DATA)){
> +             error = -EIO;
> +     }
> +
> +     core = kzalloc(sizeof(struct tvp7002), GFP_KERNEL);
> +
> +     if (!core) {
> +             error = -ENOMEM;
> +     }
> +     sd = &core->sd;
> +     v4l2_i2c_subdev_init(sd, c, &tvp7002_ops);
> +     v4l_info(c, "tvp7002 found @ 0x%02x (%s)\n",
> +              c->addr << 1, c->adapter->name);
> +
> +     /* Set polarity information */
> +     polarity = tvp7002_pdata.clk_polarity &
> tvp7002_pdata.hs_polarity &
> +                tvp7002_pdata.vs_polarity &
> tvp7002_pdata.fid_polarity;
> +     error = tvp7002_write(sd, TVP7002_MISC_CTL_2, polarity);
> +     if (error == -1){
> +             error = -EINVAL;
> +             goto found_error;
> +     }
> +
> +     /* Set video mode */
> +     core->video_mode = V4L2_STD_480P_60;
> +
> +     if (debug > 1)
> +             error = tvp7002_log_status(sd);
> +     else
> +             error = 0;
> +
> +found_error:
> +     return error;
> +}
> +
> +/*
> + * tvp7002_remove - Remove TVP7002 device support
> + * @c: ptr to i2c_client struct
> + *
> + * Reset the TVP7002 device
> + * Returns zero when successful or -EINVAL if register read fails.
> + */
> +static int tvp7002_remove(struct i2c_client *c)
> +{
> +     struct v4l2_subdev *sd = i2c_get_clientdata(c);
> +
> +     v4l2_dbg(1, debug, sd, "tvp7002.c: removing tvp7002 adapter"
> +                             "on address 0x%x\n", c->addr << 1);
> +
> +     v4l2_device_unregister_subdev(sd);
> +     kfree(to_tvp7002(sd));
> +     return 0;
> +}
> +
> +/* I2C Device ID table */
> +static const struct i2c_device_id tvp7002_id[] = {
> +     { "tvp7002", 0 },
> +     { }
> +};
> +MODULE_DEVICE_TABLE(i2c, tvp7002_id);
> +
> +/* I2C driver data */
> +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
> +     .name = "tvp7002",
> +     .probe = tvp7002_probe,
> +     .remove = tvp7002_remove,
> +     .id_table = tvp7002_id,
> +};
> --
> 1.6.0.4
>
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> Davinci-linux-open-source@linux.davincidsp.com
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-
> source
diff mbox

Patch

diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
new file mode 100644
index 0000000..cc27aab
--- /dev/null
+++ b/drivers/media/video/tvp7002.c
@@ -0,0 +1,3067 @@ 
+/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics
+ * Digitizer with Horizontal PLL registers
+ * 
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
+ *
+ * This code is partially based upon the TVP5150 driver
+ * written by Mauro Carvalho Chehab (mchehab@infradead.org)
+ * and the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <media/v4l2-device.h>
+#include <media/tvp7002.h>
+#include <media/v4l2-i2c-drv.h>
+#include <media/v4l2-chip-ident.h>
+#include "tvp7002_reg.h"
+
+MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
+MODULE_AUTHOR("Santiago Nunez-Corrales (santiago.nunez@ridgerun.com)");
+MODULE_LICENSE("GPL");
+
+/* I2C retry attempts */
+#define I2C_RETRY_COUNT                 (5)
+
+/* Debugging information */
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+/* Register default values (according to tvp7002 datasheet) */
+static const struct i2c_reg_value tvp7002_init_default[] = {
+	/* 0x00: read only */
+	{
+		TVP7002_HPLL_FDBK_DIV_MSBS, 0x67
+	},
+	{ 
+		TVP7002_HPLL_FDBK_DIV_LSBS, 0x20
+	},
+	{ 
+		TVP7002_HPLL_CRTL, 0xa8
+	},
+	{
+		TVP7002_HPLL_PHASE_SEL, 0x80
+	},
+	{
+		TVP7002_CLAMP_START, 0x32
+	},
+	{
+		TVP7002_CLAMP_W, 0x20
+	},
+	{
+		TVP7002_HSYNC_OUT_W, 0x20
+	},
+	{
+		TVP7002_B_FINE_GAIN, 0x00
+	},
+	{
+		TVP7002_G_FINE_GAIN, 0x00
+	},
+	{
+		TVP7002_R_FINE_GAIN, 0x00
+	},
+	{
+		TVP7002_B_FINE_OFF_MSBS, 0x80
+	},
+	{
+		TVP7002_G_FINE_OFF_MSBS, 0x80
+	},
+	{
+		TVP7002_R_FINE_OFF_MSBS, 0x80
+	},
+	{
+		TVP7002_SYNC_CTL_1, 0x5b
+	},
+	{
+		TVP7002_HPLL_AND_CLAMP_CTL, 0x2e
+	},
+	{
+		TVP7002_SYNC_ON_G_THRS, 0x5d
+	},
+	{
+		TVP7002_SYNC_SEPARATOR_THRS, 0x20
+	},
+	{
+		TVP7002_HPLL_PRE_COAST, 0x00
+	},
+	{
+		TVP7002_HPLL_POST_COAST, 0x00
+	},
+	/* 0x14: read only */
+	{
+		TVP7002_OUT_FORMATTER, 0x00
+	},
+	{
+		TVP7002_MISC_CTL_1, 0x11
+	},
+	{
+		TVP7002_MISC_CTL_2, 0x03
+	},
+	{
+		TVP7002_MISC_CTL_3, 0x00
+	},
+	{
+		TVP7002_IN_MUX_SEL_1, 0x00
+	},
+	{
+		TVP7002_IN_MUX_SEL_2, 0xc2
+	},
+	{
+		TVP7002_B_AND_G_COARSE_GAIN, 0x77
+	},
+	{
+		TVP7002_R_COARSE_GAIN, 0x07
+	},
+	{
+		TVP7002_COARSE_CLAMP_CTL, 0x00
+	},
+	{
+		TVP7002_FINE_OFF_LSBS, 0x00
+	},
+	{
+		TVP7002_B_COARSE_OFF, 0x10
+	},
+	{
+		TVP7002_G_COARSE_OFF, 0x10
+	},
+	{
+		TVP7002_R_COARSE_OFF, 0x10
+	},
+	{
+		TVP7002_HSOUT_OUT_START, 0x0d
+	},
+	{
+		TVP7002_MISC_CTL_4, 0x0d
+	},
+	/* 0x23: read only */
+	/* 0x24: read only */
+	/* 0x25: read only */
+	{
+		TVP7002_AUTO_LVL_CTL_ENABLE, 0x80
+	},
+	/* 0x27: read only */
+	{
+		TVP7002_AUTO_LVL_CTL_FILTER, 0x53
+	},
+	{	/* Reserved */
+		0x29, 0x08
+	},
+	{
+		TVP7002_FINE_CLAMP_CTL, 0x07
+	},
+	{
+		TVP7002_PWR_CTL, 0x00
+	},
+	{
+		TVP7002_ADC_SETUP, 0x50
+	},
+	{
+		TVP7002_COARSE_CLAMP_CTL, 0x00
+	},
+	{
+		TVP7002_SOG_CLAMP, 0x80
+	},
+	{
+		TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c
+	},
+	{
+		TVP7002_SOG_COARSE_CLAMP_CTL, 0x04
+	},
+	{
+		TVP7002_ALC_PLACEMENT, 0x5a
+	},
+	{       /* Reserved */
+		0x32, 0x18
+	},
+	{       /* Reserved */
+		0x33, 0x60
+	},
+	{
+		TVP7002_MVIS_STRIPPER_W, 0x03
+	},
+	{
+		TVP7002_VSYNC_ALGN, 0x10
+	},
+	{
+		TVP7002_SYNC_BYPASS, 0x00
+	},
+	/* 0x37: read only */
+	/* 0x38: read only */
+	/* 0x39: read only */
+	/* 0x3a: read only */
+	/* 0x3b: read only */
+	/* 0x3c: read only */
+	{
+		TVP7002_L_LENGTH_TOL, 0x03
+	},
+	{       /* Reserved */
+		0x3e, 0x04
+	},
+	{
+		TVP7002_VIDEO_BWTH_CTL, 0x00
+	},
+	{
+		TVP7002_AVID_START_PIXEL_LSBS, 0x01
+	},
+	{
+		TVP7002_AVID_START_PIXEL_MSBS, 0x2c
+	},
+	{
+		TVP7002_AVID_STOP_PIXEL_LSBS, 0x06
+	},
+	{
+		TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c
+	},
+	{
+		TVP7002_VBLK_F_0_START_L_OFF, 0x05
+	},
+	{
+		TVP7002_VBLK_F_1_START_L_OFF, 0x05
+	},
+	{
+		TVP7002_VBLK_F_0_DURATION, 0x1e
+	},
+	{
+		TVP7002_VBLK_F_1_DURATION, 0x1e
+	},
+	{
+		TVP7002_FBIT_F_0_START_L_OFF, 0x00
+	},
+	{
+		TVP7002_FBIT_F_1_START_L_OFF, 0x00
+	},
+	{
+		TVP7002_YUV_Y_G_COEF_LSBS, 0xe3
+	},
+	{
+		TVP7002_YUV_Y_G_COEF_MSBS, 0x16
+	},
+	{
+		TVP7002_YUV_Y_B_COEF_LSBS, 0x4f
+	},
+	{
+		TVP7002_YUV_Y_B_COEF_MSBS, 0x02
+	},
+	{
+		TVP7002_YUV_Y_R_COEF_LSBS, 0xce
+	},
+	{
+		TVP7002_YUV_Y_R_COEF_MSBS, 0x06
+	},
+	{
+		TVP7002_YUV_U_G_COEF_LSBS, 0xab
+	},
+	{
+		TVP7002_YUV_U_G_COEF_MSBS, 0xf3
+	},
+	{
+		TVP7002_YUV_U_B_COEF_LSBS, 0x00
+	},
+	{
+		TVP7002_YUV_U_B_COEF_MSBS, 0x10
+	},
+	{
+		TVP7002_YUV_U_R_COEF_LSBS, 0x55
+	},
+	{
+		TVP7002_YUV_U_R_COEF_MSBS, 0xfc
+	},
+	{
+		TVP7002_YUV_V_G_COEF_LSBS, 0x78
+	},
+	{
+		TVP7002_YUV_V_G_COEF_MSBS, 0xf1
+	},
+	{
+		TVP7002_YUV_V_B_COEF_LSBS, 0x88
+	},
+	{
+		TVP7002_YUV_V_B_COEF_MSBS, 0xfe
+	},
+	{
+		TVP7002_YUV_V_R_COEF_LSBS, 0x00
+	},
+	{
+		TVP7002_YUV_V_R_COEF_MSBS, 0x10
+	},
+	{ /* End of registers */
+		0x5c, 0x00
+	}
+};
+
+/* Available resolutions */
+static struct tvp7002_resol tvp7002_resolutions[] = {
+	{
+		.id = V4L2_STD_480I_60,
+		.hres = 720,
+		.vres = 480,
+		.frate = 30,
+		.lrate = 15,
+		.prate = 14,
+		.reg01 = 0x35,
+		.reg02 = 0xa0,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_576I_50,
+		.hres = 720,
+		.vres = 576,
+		.frate = 25,
+		.lrate = 16,
+		.prate = 14,
+		.reg01 = 0x36,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_480P_60,
+		.hres = 720,
+		.vres = 480,
+		.frate = 60,
+		.lrate = 31,
+		.prate = 27,
+		.reg01 = 0x35,
+		.reg02 = 0xa0,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_576P_50,
+		.hres = 720,
+		.vres = 576,
+		.frate = 50,
+		.lrate = 31,
+		.prate = 27,
+		.reg01 = 0x36,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_720P_60,
+		.hres = 1280,
+		.vres = 720,
+		.frate = 60,
+		.lrate = 45,
+		.prate = 74,
+		.reg01 = 0x67,
+		.reg02 = 0x20,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_720P_50,
+		.hres = 1280,
+		.vres = 720,
+		.frate = 50,
+		.lrate = 38,
+		.prate = 74,
+		.reg01 = 0x7b,
+		.reg02 = 0xc0,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_1080I_60,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 60,
+		.lrate = 34,
+		.prate = 74,
+		.reg01 = 0x89,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_1080I_50,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 50,
+		.lrate = 28,
+		.prate = 74,
+		.reg01 = 0xa5,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x10,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_1080P_60,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 60,
+		.lrate = 68,
+		.prate = 149,
+		.reg01 = 0x89,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x80,
+	}, {
+		.id = V4L2_STD_1080P_50,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 50,
+		.lrate = 56,
+		.prate = 149,
+		.reg01 = 0xa5,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x18,
+		.reg04 = 0x80,
+	},
+};
+
+/*
+ * tvp7002_from_std - Map video standard to register information
+ * @std: v4l2_std_id (u64) integer
+ *
+ * Returns index of std or -1 in case of error.
+ */
+int tvp7002_from_std(v4l2_std_id std)
+{
+	int res;
+	
+	switch(std){
+	case V4L2_STD_480P_60:
+		res = TVP7002_STD_480P;
+		break;
+	case V4L2_STD_480I_60:
+		res = TVP7002_STD_480I;
+		break;
+	case V4L2_STD_576P_50:
+		res = V4L2_STD_576P_50;
+		break;
+	case V4L2_STD_576I_50:
+		res = V4L2_STD_576I_50;
+		break;
+	case V4L2_STD_720P_50:
+		res = V4L2_STD_720P_50;
+		break;
+	case V4L2_STD_720P_60:
+		res = V4L2_STD_720P_60;
+		break;
+	case V4L2_STD_1080I_50:
+		res = V4L2_STD_1080I_50;
+		break;
+	case V4L2_STD_1080I_60:
+		res = V4L2_STD_1080I_60;
+		break;
+	case V4L2_STD_1080P_50:
+		res = V4L2_STD_1080P_50;
+		break;
+	case V4L2_STD_1080P_60:
+		res = V4L2_STD_1080P_60;
+		break;
+	default:
+		res = -1;
+		break;
+	}
+	
+	return res;
+}
+
+/* Device definition */
+struct tvp7002 {
+	struct v4l2_subdev sd;
+	v4l2_std_id video_mode;
+	int streaming;
+};
+
+/* Supported controls */
+static struct v4l2_queryctrl tvp7002_qctrl[] = {
+	{
+		.id = V4L2_CID_TVP7002_COARSE_GAIN_R,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for R channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    	},
+	{
+		.id = V4L2_CID_TVP7002_COARSE_GAIN_G,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for G channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_COARSE_GAIN_B,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for B channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_FINE_GAIN_R,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for R channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_FINE_GAIN_G,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for G channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    	},
+	{
+		.id = V4L2_CID_TVP7002_FINE_GAIN_B,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for B channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_B_CLAMP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Toggle Blue clamp",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    	},
+    	{
+		.id = V4L2_CID_TVP7002_G_CLAMP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Toggle Green clamp",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    	},
+    	{
+		.id = V4L2_CID_TVP7002_R_CLAMP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Toggle Red clamp",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_CLAMP_OFF_EN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Enable clamp offset",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_FCTCA,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Fine clamp time cnst adj",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_F_CLAMP_GB,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Fine clamp for G and B",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_F_CLAMP_R,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Fine clamp for Red",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_CLAMP_START,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Clamp start",
+		.minimum = 0,
+		.maximum = 255,
+		.step = 1,
+		.default_value = 0x32,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_CLAMP_W,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Clamp width",
+		.minimum = 0,
+		.maximum = 255,
+		.step = 1,
+		.default_value = 0x20,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_B_COARSE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue coarse offset",
+		.minimum = 0,
+		.maximum = 32,
+		.step = 1,
+		.default_value = 0x10,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_G_COARSE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Green coarse offset",
+		.minimum = 0,
+		.maximum = 32,
+		.step = 1,
+		.default_value = 0x10,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_R_COARSE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red coarse offset",
+		.minimum = 0,
+		.maximum = 32,
+		.step = 1,
+		.default_value = 0x10,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_B_FINE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue fine offset",
+		.minimum = 0,
+		.maximum = 1024,
+		.step = 1,
+		.default_value = 512,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_G_FINE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Green fine offset",
+		.minimum = 0,
+		.maximum = 1024,
+		.step = 1,
+		.default_value = 512,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_TVP7002_R_FINE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red fine offset",
+		.minimum = 0,
+		.maximum = 1024,
+		.step = 1,
+		.default_value = 512,
+		.flags = 0,
+	},
+};
+
+/*
+ * to_tvp7002 - Obtain device handler TVP7002
+ * @sd: ptr to v4l2_subdev struct
+ *
+ * Returns device handler tvp7002.
+ */
+static struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tvp7002, sd);
+}
+
+/*
+ * tvp7002_read - Read a value from a register in an TVP7002
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: TVP7002 register address
+ *
+ * Returns value read if successful, or non-zero (-1) otherwise.
+ */
+static int tvp7002_read(struct v4l2_subdev *sd, unsigned char addr)
+{
+	int error;
+	int retry = 0;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	
+try_read:
+	error = i2c_smbus_read_byte_data(c, addr);
+	if (error == -1){
+		if (retry <= I2C_RETRY_COUNT){
+			v4l2_warn(sd, "TVP7002 Read: retry ... %d\n", retry);
+			retry++;
+			msleep_interruptible(10);
+			goto try_read;
+		}
+	}
+	
+	return error;
+}
+
+/*
+ * tvp7002_write() - Write a value to a register in TVP5146/47
+ * @sd: ptr to v4l2_subdev struct
+ * @addr: TVP5146/47 register address
+ * @value: value to be written to the register
+ *
+ * Write a value to a register in an TVP7002 decoder device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value)
+{
+	int error;
+	int retry = 0;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+
+write_again:
+	error = i2c_smbus_write_byte_data(c, addr, value);
+	if (error) {
+		if (retry <= I2C_RETRY_COUNT) {
+			v4l2_warn(sd, "TVP7002 Write: retry ... %d\n", retry);
+			retry++;
+			msleep_interruptible(10);
+			goto write_again;
+		}
+	}
+
+	return error;
+}
+
+/*
+ * dump_reg_range() - Dump information from TVP7002 registers
+ * @sd: ptr to v4l2_subdev struct
+ * @init: TVP7002 start address
+ * @init: TVP7002 end address
+ * @nline: register values per line
+ *
+ * Dump values at a specified register range
+ * Returns nothing.
+ */
+static void dump_reg_range(struct v4l2_subdev *sd, u8 init, const u8 end)
+{
+	int i = 0;
+	int result;
+	
+	while (init != (u8)(end + 1)) {
+		
+		result = tvp7002_read(sd, init);
+		
+		if (result == -1)
+			v4l2_err(sd, "tvp7002: reg 0x%02x unreadable\n", i);
+		else 
+			v4l2_info(sd, "tvp7002: @0x%02x = %02x\n", i, result);
+
+		init++;
+		i++;
+	}
+	printk("\n");
+}
+
+/*
+ * tvp7002_log_status() - Print information about register settings
+ * @sd: ptr to v4l2_subdev struct
+ *
+ * Log regsiter values of a TVP7002 decoder device.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_log_status(struct v4l2_subdev *sd)
+{
+	int error, rres;
+	
+	rres = tvp7002_read(sd, TVP7002_CHIP_REV);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", TVP7002_CHIP_REV);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Chip revision number = 0x%02x\n",
+							    TVP7002_CHIP_REV);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HPLL_FDBK_DIV_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: H-PLL feedback div LSB = 0x%02x\n",
+						TVP7002_HPLL_FDBK_DIV_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HPLL_FDBK_DIV_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: H-PLL feedback div MSB = 0x%02x\n",
+						TVP7002_HPLL_FDBK_DIV_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_CRTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", TVP7002_HPLL_CRTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VCO frequency range selector = 0x%02x\n",
+							    TVP7002_HPLL_CRTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_PHASE_SEL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_HPLL_PHASE_SEL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: ADC sampling clk phase select = 0x%02x\n",
+							TVP7002_HPLL_PHASE_SEL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_CLAMP_START);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_CLAMP_START);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Clamp start = 0x%02x\n",
+							TVP7002_CLAMP_START);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_CLAMP_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", TVP7002_CLAMP_W);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Clamp width = 0x%02x\n", TVP7002_CLAMP_W);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_HSYNC_OUT_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_HSYNC_OUT_W);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: HSYNC output width = 0x%02x\n", 
+							TVP7002_HSYNC_OUT_W);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_B_FINE_GAIN);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_B_FINE_GAIN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain for B ch = 0x%02x\n", 
+							TVP7002_B_FINE_GAIN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_G_FINE_GAIN);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_G_FINE_GAIN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain for G ch = 0x%02x\n", 
+							TVP7002_G_FINE_GAIN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_R_FINE_GAIN);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_R_FINE_GAIN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain for R ch = 0x%02x\n", 
+							TVP7002_R_FINE_GAIN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_B_FINE_OFF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain off B ch = 0x%02x\n", 
+						TVP7002_B_FINE_OFF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_G_FINE_OFF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain off G ch = 0x%02x\n", 
+						TVP7002_G_FINE_OFF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_R_FINE_OFF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Digital fine grain off R ch = 0x%02x\n", 
+						TVP7002_R_FINE_OFF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_FINE_OFF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Dig fine grain off R ch LSBs = 0x%02x\n", 
+						TVP7002_FINE_OFF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SYNC_CTL_1);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SYNC_CTL_1);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: SYNC control 1 = 0x%02x\n", 
+						TVP7002_SYNC_CTL_1);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_AND_CLAMP_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HPLL_AND_CLAMP_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: H-PLL and clamp control = 0x%02x\n", 
+						TVP7002_HPLL_AND_CLAMP_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SYNC_ON_G_THRS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Sync-On-Green threshold = 0x%02x\n", 
+						TVP7002_SYNC_ON_G_THRS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_SYNC_SEPARATOR_THRS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SYNC_SEPARATOR_THRS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Sync separator threshold = 0x%02x\n", 
+						TVP7002_SYNC_SEPARATOR_THRS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_HPLL_PRE_COAST);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HPLL_PRE_COAST);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: H-PLL pre-coast = 0x%02x\n", 
+						TVP7002_HPLL_PRE_COAST);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HPLL_POST_COAST);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HPLL_POST_COAST);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: H-PLL post-coast = 0x%02x\n", 
+						TVP7002_HPLL_POST_COAST);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SYNC_DETECT_STAT);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SYNC_DETECT_STAT);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Sync detect status = 0x%02x\n", 
+						TVP7002_SYNC_DETECT_STAT);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_OUT_FORMATTER);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_OUT_FORMATTER);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Output formatter = 0x%02x\n", 
+						TVP7002_OUT_FORMATTER);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MISC_CTL_1);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MISC_CTL_1);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Miscelaneous control 1 = 0x%02x\n",
+						TVP7002_MISC_CTL_1);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MISC_CTL_2);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MISC_CTL_2);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Miscelaneous control 2 = 0x%02x\n",
+						TVP7002_MISC_CTL_2);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MISC_CTL_3);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MISC_CTL_3);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Miscelaneous control 3 = 0x%02x\n",
+						TVP7002_MISC_CTL_3);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MISC_CTL_3);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MISC_CTL_3);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Miscelaneous control 3 = 0x%02x\n",
+						TVP7002_MISC_CTL_3);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_IN_MUX_SEL_1);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_IN_MUX_SEL_1);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Input Mux Selector 1 = 0x%02x\n",
+						TVP7002_IN_MUX_SEL_1);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_IN_MUX_SEL_2);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_IN_MUX_SEL_2);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Input Mux Selector 1 = 0x%02x\n",
+						TVP7002_IN_MUX_SEL_2);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_B_AND_G_COARSE_GAIN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: B and G coarse gain = 0x%02x\n",
+						TVP7002_B_AND_G_COARSE_GAIN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_R_COARSE_GAIN);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_R_COARSE_GAIN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: R coarse gain = 0x%02x\n",
+						TVP7002_R_COARSE_GAIN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_B_COARSE_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_B_COARSE_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Coarse offset for B ch = 0x%02x\n",
+						TVP7002_B_COARSE_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_G_COARSE_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_G_COARSE_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Coarse offset for G ch = 0x%02x\n",
+						TVP7002_G_COARSE_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_R_COARSE_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Coarse offset for R ch = 0x%02x\n",
+						TVP7002_R_COARSE_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_R_COARSE_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Coarse offset for R ch = 0x%02x\n",
+						TVP7002_R_COARSE_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HSOUT_OUT_START);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_HSOUT_OUT_START);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: HSYNC lead edge out start = 0x%02x\n",
+						TVP7002_HSOUT_OUT_START);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_MISC_CTL_4);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MISC_CTL_4);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Miscelaneous control 4 = 0x%02x\n",
+						TVP7002_MISC_CTL_4);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_B_DGTL_ALC_OUT_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_B_DGTL_ALC_OUT_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Filt ALC out for B ch LSBs = 0x%02x\n",
+						TVP7002_B_DGTL_ALC_OUT_LSBS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_G_DGTL_ALC_OUT_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_G_DGTL_ALC_OUT_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Filt ALC out for G ch LSBs = 0x%02x\n",
+						TVP7002_G_DGTL_ALC_OUT_LSBS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_R_DGTL_ALC_OUT_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_R_DGTL_ALC_OUT_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Filt ALC out for R ch LSBs = 0x%02x\n",
+						TVP7002_R_DGTL_ALC_OUT_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_ENABLE);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AUTO_LVL_CTL_ENABLE);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Auto level control enable = 0x%02x\n",
+						TVP7002_AUTO_LVL_CTL_ENABLE);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_DGTL_ALC_OUT_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_DGTL_ALC_OUT_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Filt ALC out RGB chs MSB = 0x%02x\n",
+						TVP7002_DGTL_ALC_OUT_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_FILTER);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AUTO_LVL_CTL_FILTER);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Auto level control filter = 0x%02x\n",
+						TVP7002_AUTO_LVL_CTL_FILTER);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_FINE_CLAMP_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Fine clamp control = 0x%02x\n",
+						TVP7002_FINE_CLAMP_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_PWR_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_PWR_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Power control = 0x%02x\n",
+							TVP7002_PWR_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_ADC_SETUP);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_ADC_SETUP);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: ADC setup = 0x%02x\n",
+							TVP7002_ADC_SETUP);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_COARSE_CLAMP_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_COARSE_CLAMP_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Coarse clamp control = 0x%02x\n",
+						TVP7002_COARSE_CLAMP_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SOG_CLAMP);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SOG_CLAMP);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Sync-On-Green clamp = 0x%02x\n",
+						TVP7002_SOG_CLAMP);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_RGB_COARSE_CLAMP_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_RGB_COARSE_CLAMP_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: RGB coarse clamp control = 0x%02x\n",
+						TVP7002_RGB_COARSE_CLAMP_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SOG_COARSE_CLAMP_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_SOG_COARSE_CLAMP_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: SOG coarse clamp control = 0x%02x\n",
+						TVP7002_SOG_COARSE_CLAMP_CTL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_ALC_PLACEMENT);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_ALC_PLACEMENT);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: ALC placement = 0x%02x\n",
+						TVP7002_ALC_PLACEMENT);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MVIS_STRIPPER_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_MVIS_STRIPPER_W);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Macrovision stripper width = 0x%02x\n",
+							TVP7002_VSYNC_ALGN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_MVIS_STRIPPER_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_VSYNC_ALGN);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VSYNC alignment = 0x%02x\n",
+							TVP7002_VSYNC_ALGN);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_SYNC_BYPASS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_SYNC_BYPASS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Sync bypass = 0x%02x\n",
+							TVP7002_SYNC_BYPASS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_L_FRAME_STAT_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_L_FRAME_STAT_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Lines p Frame status LSBs = 0x%02x\n",
+						TVP7002_L_FRAME_STAT_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_L_FRAME_STAT_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_L_FRAME_STAT_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Lines p Frame status MSBs = 0x%02x\n",
+						TVP7002_L_FRAME_STAT_MSBS);
+	}
+	
+
+	rres = tvp7002_read(sd, TVP7002_CLK_L_STAT_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_CLK_L_STAT_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Clks p line status LSBs = 0x%02x\n",
+						TVP7002_CLK_L_STAT_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_CLK_L_STAT_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_CLK_L_STAT_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Clks p line status MSBs = 0x%02x\n",
+						TVP7002_CLK_L_STAT_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_HSYNC_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_HSYNC_W);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: HSYNC width = 0x%02x\n",
+							TVP7002_HSYNC_W);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_VSYNC_W);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_VSYNC_W);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VSYNC width = 0x%02x\n",
+							TVP7002_VSYNC_W);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_L_LENGTH_TOL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+							TVP7002_L_LENGTH_TOL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Line length tolerance = 0x%02x\n",
+							TVP7002_L_LENGTH_TOL);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_VIDEO_BWTH_CTL);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_VIDEO_BWTH_CTL);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: Video bandwidth control = 0x%02x\n",
+						TVP7002_VIDEO_BWTH_CTL);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_AVID_START_PIXEL_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AVID_START_PIXEL_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: AVID start pixel LSBs = 0x%02x\n",
+						TVP7002_AVID_START_PIXEL_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_AVID_START_PIXEL_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AVID_START_PIXEL_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: AVID start pixel MSBs = 0x%02x\n",
+						TVP7002_AVID_START_PIXEL_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AVID_STOP_PIXEL_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: AVID stop pixel LSBs = 0x%02x\n",
+						TVP7002_AVID_STOP_PIXEL_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_AVID_STOP_PIXEL_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: AVID stop pixel MSBs = 0x%02x\n",
+						TVP7002_AVID_STOP_PIXEL_MSBS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_VBLK_F_0_START_L_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_VBLK_F_0_START_L_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VBLK start line offset 0 = 0x%02x\n",
+						TVP7002_VBLK_F_0_START_L_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_VBLK_F_1_START_L_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_VBLK_F_1_START_L_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VBLK start line offset 1 = 0x%02x\n",
+						TVP7002_VBLK_F_1_START_L_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_VBLK_F_0_DURATION);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_VBLK_F_0_DURATION);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VBLK duration 0 = 0x%02x\n",
+						TVP7002_VBLK_F_0_DURATION);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_VBLK_F_1_DURATION);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_VBLK_F_1_DURATION);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: VBLK duration 1 = 0x%02x\n",
+						TVP7002_VBLK_F_1_DURATION);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_FBIT_F_0_START_L_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_FBIT_F_0_START_L_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: F-bit start line offset 0 = 0x%02x\n",
+						TVP7002_FBIT_F_0_START_L_OFF);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_FBIT_F_1_START_L_OFF);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_FBIT_F_1_START_L_OFF);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: F-bit start line offset 1 = 0x%02x\n",
+						TVP7002_FBIT_F_1_START_L_OFF);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_G_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y G LSBs = 0x%02x\n",
+						TVP7002_YUV_Y_G_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_G_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y G MSBs = 0x%02x\n",
+						TVP7002_YUV_Y_G_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_B_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y B LSBs = 0x%02x\n",
+						TVP7002_YUV_Y_B_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_B_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y B MSBs = 0x%02x\n",
+						TVP7002_YUV_Y_B_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_R_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y R LSBs = 0x%02x\n",
+						TVP7002_YUV_Y_R_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_Y_R_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV Y R MSBs = 0x%02x\n",
+						TVP7002_YUV_Y_R_COEF_MSBS);
+	}
+
+	rres = tvp7002_read(sd, TVP7002_YUV_U_G_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_G_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U G LSBs = 0x%02x\n",
+						TVP7002_YUV_U_G_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_U_G_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_G_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U G MSBs = 0x%02x\n",
+						TVP7002_YUV_U_G_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_U_B_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_B_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U B LSBs = 0x%02x\n",
+						TVP7002_YUV_U_B_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_U_B_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_B_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U B MSBs = 0x%02x\n",
+						TVP7002_YUV_U_B_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_U_R_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_R_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U R LSBs = 0x%02x\n",
+						TVP7002_YUV_U_R_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_U_R_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_U_R_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV U R MSBs = 0x%02x\n",
+						TVP7002_YUV_U_R_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_G_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_G_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V G LSBs = 0x%02x\n",
+						TVP7002_YUV_V_G_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_G_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_G_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V G MSBs = 0x%02x\n",
+						TVP7002_YUV_V_G_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_B_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_B_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V B LSBs = 0x%02x\n",
+						TVP7002_YUV_V_B_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_B_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_B_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V B MSBs = 0x%02x\n",
+						TVP7002_YUV_V_B_COEF_MSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_R_COEF_LSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_R_COEF_LSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V R LSBs = 0x%02x\n",
+						TVP7002_YUV_V_R_COEF_LSBS);
+	}
+	
+	rres = tvp7002_read(sd, TVP7002_YUV_V_R_COEF_MSBS);
+	if (rres == -1){
+		v4l2_err(sd, "tvp7002: error reading 0x%02x\n", 
+						TVP7002_YUV_V_R_COEF_MSBS);
+		error = -EINVAL;
+		goto found_error;
+	}
+	else {
+		v4l2_info(sd, "tvp7002: YUV V R MSBs = 0x%02x\n",
+						TVP7002_YUV_V_R_COEF_MSBS);
+	}
+	
+	error = 0;
+	
+found_error:
+	return error;
+}
+
+/*
+ * tvp7002_g_chip_ident() - Get chip identification number
+ * @sd: ptr to v4l2_subdev struct
+ * @chip: ptr to v4l2_dbg_chip_ident struct
+ *
+ * Obtains the chip's identification number.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_g_chip_ident(struct v4l2_subdev *sd, 
+					struct v4l2_dbg_chip_ident *chip)
+{
+	int rev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	
+	rev = tvp7002_read(sd, TVP7002_CHIP_REV);
+	
+	if (rev == -1)
+		return -EINVAL;
+	else
+		return v4l2_chip_ident_i2c_client(client, chip, 
+						V4L2_IDENT_TVP7002, rev);
+}
+
+/*
+ * tvp7002_write_inittab() - Write initialization values
+ * @sd: ptr to v4l2_subdev struct
+ * @regs: ptr to i2c_reg_value struct
+ *
+ * Write initialization values.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_write_inittab(struct v4l2_subdev *sd, 
+					const struct i2c_reg_value *regs)
+{
+	int i;
+	int error;
+	/* Initialize the first (defined) registers */
+	while (regs->reg != 0x5c) {
+		error = tvp7002_write(sd, regs->reg, regs->value);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		else {
+			regs++;
+		}
+	}
+	/* Initialize the last (undefined) registers */
+	for (i = 0x5c; i <= 0xff; i++){
+		error = tvp7002_write(sd, i, 0x00);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		else {
+			regs++;
+		}
+	}
+	
+	error = 0;
+
+found_error:	
+	return error;
+}
+
+/*
+ * tvp7002_set_video_mode()
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @sdf: index to structure describing format
+ *
+ * Set video standard according to index
+ * 
+ * Returns 0 if operation is successful or -EINVAL otherwise 
+ */
+static int tvp7002_set_video_mode(struct v4l2_subdev *sd, int sdf)
+{
+	int error;
+	
+	if (sdf < TVP7002_STD_480I || sdf > TVP7002_STD_1080P_50){
+		v4l2_err(sd, "tvp7002: sf out of range\n");
+		error = -ERANGE;
+		goto found_error;
+	}
+
+	/* Print specific information about current format */
+	v4l2_info(sd, "tvp7002: Setting standard display format...\n");
+	v4l2_info(sd, "tvp7002: hres = %d vres=%d fr=%d lr=%d prate=%d\n", 
+			tvp7002_resolutions[sdf].hres,
+			tvp7002_resolutions[sdf].vres,
+			tvp7002_resolutions[sdf].frate,
+			tvp7002_resolutions[sdf].lrate,
+			tvp7002_resolutions[sdf].prate);
+	/* Set registers accordingly */
+	error = tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_MSBS, 
+					tvp7002_resolutions[sdf].reg01);	
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+					
+	error = tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_LSBS, 
+					tvp7002_resolutions[sdf].reg02);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	
+	error = tvp7002_write(sd, TVP7002_HPLL_CRTL, tvp7002_resolutions[sdf].reg03);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	
+	error =  tvp7002_write(sd, TVP7002_HPLL_PHASE_SEL, 
+					tvp7002_resolutions[sdf].reg04);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	
+	/* Set SD/HD mode registers */
+
+	if (sdf < TVP7002_STD_720P_60){
+		error = tvp7002_write(sd, TVP7002_CLAMP_START, 0x06);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_CLAMP_W, 0x10);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x03);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_HPLL_POST_COAST, 0x03);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0x17);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		if (sdf < TVP7002_STD_480P){
+			error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x0c);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+			error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x24);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+		else {
+			error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x0a);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+			error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x12);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+		error = tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x08);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x18);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+	}
+	else {
+		error = tvp7002_write(sd, TVP7002_CLAMP_START, 0x32);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_CLAMP_W, 0x20);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x01);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_HPLL_POST_COAST, 0x00);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0xc7);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		if(sdf < TVP7002_STD_1080I_60){
+			error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x35);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+		else {
+			error = tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x39);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+		error = tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x00);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x5a);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		if(sdf < TVP7002_STD_1080P_60){
+			error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x07);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+		else {
+			error = tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x03);
+			if (error == -1){
+				error = -EINVAL;
+				goto found_error;
+			}
+		}
+	}
+	if (sdf < TVP7002_STD_1080P_60){
+		error = tvp7002_write(sd, TVP7002_ADC_SETUP, 0x50);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x0f);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+	}
+	else {
+		error = tvp7002_write(sd, TVP7002_ADC_SETUP, 0x80);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+		error = tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x00);
+		if (error == -1){
+			error = -EINVAL;
+			goto found_error;
+		}
+	}
+	/* Set up registers that hold the same value regardless of the 
+	 * SD mode
+	 */ 
+	error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 0x5d);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	error = tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	
+	error = 0;
+	
+found_error:
+	return error;
+}
+
+/*
+ * tvp7002_get_video_mode() - V4L2 decoder interface handler for querystd
+ * @sd: pointer to standard V4L2 sub-device structure
+ *
+ * Returns the current standard detected by TVP7002. If no active input is
+ * detected, returns -1
+ */
+static v4l2_std_id tvp7002_get_video_mode(struct v4l2_subdev *sd){
+	int error;
+	int reg01, reg02, reg03;
+	reg01 = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_MSBS);
+	reg02 = tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_LSBS);
+	reg03 = tvp7002_read(sd, TVP7002_HPLL_CRTL);
+	
+	if (reg01 == -1 || reg02 == -1 || reg03 == -1){
+		error = -1;
+		goto found_error;
+	}
+	
+	switch(reg01){
+	case 0x35:
+		if (reg02 == 0xa0)
+			error = V4L2_STD_480I_60;
+		else
+			error = V4L2_STD_576I_50;
+	case 0x36:
+		if (reg02 == 0xa0)
+			error = V4L2_STD_480P_60;
+		else
+			error = V4L2_STD_576P_50;
+	case 0x67:
+		error = V4L2_STD_720P_60;
+	case 0x7b:
+		error = V4L2_STD_720P_50;
+	case 0x89:
+		if (reg03 == 0x98)
+			error = V4L2_STD_1080I_60;
+		else
+			error = V4L2_STD_1080P_60;
+	case 0xa5:
+		if (reg03 == 0x90)
+			error = V4L2_STD_1080I_50;
+		else
+			error = V4L2_STD_1080P_50;
+	default:
+		error = -1;
+	}
+	
+found_error:
+	return error;
+}
+
+/*
+ * tvp7002_querystd() - V4L2 decoder interface handler for querystd
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @std_id: standard V4L2 std_id ioctl enum
+ *
+ * Returns the current standard detected by TVP7002. If no active input is
+ * detected, returns -EINVAL
+ */
+static int tvp7002_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
+{
+	struct tvp7002 *decoder = to_tvp7002(sd);
+	v4l2_std_id current_std;
+	u8 sync_lock_status, lock_mask;
+
+	if (std_id == NULL)
+		return -EINVAL;
+
+	/* get the current standard */
+	current_std = tvp7002_get_video_mode(sd);
+	if (current_std == -1)
+		return -EINVAL;
+
+	/* check whether signal is locked */
+	sync_lock_status = tvp7002_read(sd, TVP7002_SYNC_DETECT_STAT);
+	
+	if (0x02 != (sync_lock_status & 0xff))
+		return -EINVAL;	/* No input detected */
+
+	decoder->video_mode = current_std;
+	*std_id = current_std;
+
+	v4l2_info(sd, "Current STD: %s", decoder->video_mode);
+	return 0;
+}
+
+/**
+ * tvp7002_g_fmt() - V4L2 decoder interface handler for tvp7002_g_fmt
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the decoder's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+	struct tvp7002 *decoder = to_tvp7002(sd);
+
+	if (f == NULL)
+		return -EINVAL;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		/* only capture is supported */
+		return -EINVAL;
+
+/*	f->fmt.pix = decoder->pix;
+
+	v4l2_info(sd, "Current FMT: bytesperline - %d"
+			"Width - %d, Height - %d",
+			decoder->pix.bytesperline,
+			decoder->pix.width, decoder->pix.height);*/
+	return 0;
+}
+
+/*
+ * tvp7002_s_ctrl() - Set a control
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to v4l2_control struct
+ *
+ * Set a control for a TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register access fails.
+ */
+static int tvp7002_s_std(struct v4l2_subdev *sd, v4l2_std_id std){
+	struct tvp7002 *decoder = to_tvp7002(sd);
+	int vmd = 0;
+
+	decoder->video_mode = std;
+	vmd = tvp7002_from_std(std);
+
+	v4l2_info(sd, "Set video std mode to %d.\n", (int)std);
+	
+	return tvp7002_set_video_mode(sd, vmd);
+}
+
+/*
+ * tvp7002_g_ctrl() - Get a control
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to v4l2_control struct
+ *
+ * Get a control for a TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register access fails.
+ */
+static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl){
+	int res;
+	int tmp;
+	
+	v4l2_info(sd, "tvp7002: g_ctrl called\n");
+	
+	switch (ctrl->id) {
+	case V4L2_CID_TVP7002_COARSE_GAIN_R:
+		res = tvp7002_read(sd, TVP7002_R_COARSE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x0F; 
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_COARSE_GAIN_G:
+		res = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res & 0xF0) >> 4;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_COARSE_GAIN_B:
+		res = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x0F;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_R:
+		res = tvp7002_read(sd, TVP7002_R_FINE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0xFF;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_G:
+		res = tvp7002_read(sd, TVP7002_G_FINE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0xFF;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_B:
+		res = tvp7002_read(sd, TVP7002_B_FINE_GAIN);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0xFF;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_B_CLAMP:
+		res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res >> 2) & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_G_CLAMP:
+		res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res >> 1) & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_R_CLAMP:
+		res = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_CLAMP_OFF_EN:
+		res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res >> 7) & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_FCTCA:
+		res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (((res >> 3) & 0x03) == 0x03) ? 1 : 0;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_F_CLAMP_GB:
+		res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res >> 1) & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_F_CLAMP_R:
+		res = tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x01;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_CLAMP_START:
+		res = tvp7002_read(sd, TVP7002_CLAMP_START);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0xff;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_CLAMP_W:
+		res = tvp7002_read(sd, TVP7002_CLAMP_W);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0xff;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_B_COARSE_OFF:
+		res = tvp7002_read(sd, TVP7002_B_COARSE_OFF);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x3f;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_G_COARSE_OFF:
+		res = tvp7002_read(sd, TVP7002_G_COARSE_OFF);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x3f;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_R_COARSE_OFF:
+		res = tvp7002_read(sd, TVP7002_R_COARSE_OFF);
+		if (res == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = res & 0x3f;
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_B_FINE_OFF:
+		res = tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS);
+		tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
+		if (res == -1 || tmp == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res << 2) | (tmp & 0x03);
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_G_FINE_OFF:
+		res = tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS);
+		tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
+		if (res == -1 || tmp == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res << 2) | ((tmp >> 2) & 0x03);
+			res = ctrl->value;
+		}
+		break;
+	case V4L2_CID_TVP7002_R_FINE_OFF:
+		res = tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS);
+		tmp = tvp7002_read(sd, TVP7002_FINE_OFF_LSBS);
+		if (res == -1 || tmp == -1){
+			res = -EINVAL;
+			goto found_error;
+		}
+		else {
+			ctrl->value = (res << 2) | ((tmp >> 4) & 0x03);
+			res = ctrl->value;
+		}
+		break;
+	default:
+		res = -EINVAL;
+		break;
+	}
+
+found_error:	
+	return res;
+}
+
+/*
+ * tvp7002_s_ctrl() - Set a control
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to v4l2_control struct
+ *
+ * Set a control in TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register access fails.
+ */
+static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	int error;
+	u8 i, n;
+	n = ARRAY_SIZE(tvp7002_qctrl);
+
+	for (i = 0; i < n; i++) {
+		if (ctrl->id != tvp7002_qctrl[i].id)
+			continue;
+            
+		if (ctrl->value < tvp7002_qctrl[i].minimum || 
+		    ctrl->value > tvp7002_qctrl[i].maximum)
+			return -ERANGE;
+		v4l2_err(sd, "s_ctrl: id=%d, value=%d\n", ctrl->id, 
+								ctrl->value);
+		break;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_TVP7002_COARSE_GAIN_R:
+		error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, 
+							ctrl->value & 0xff);
+		break;
+	case V4L2_CID_TVP7002_COARSE_GAIN_G:
+		error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, 
+						(ctrl->value << 4) & 0xf0);
+		break;
+	case V4L2_CID_TVP7002_COARSE_GAIN_B:
+		error = tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, 
+						ctrl->value& 0x0f);
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_R:
+		error = tvp7002_write(sd, TVP7002_R_FINE_GAIN, 
+							ctrl->value & 0xff);
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_G:
+		error = tvp7002_write(sd, TVP7002_G_FINE_GAIN, 
+						(ctrl->value << 4) & 0xf0);
+		break;
+	case V4L2_CID_TVP7002_FINE_GAIN_B:
+		error = tvp7002_write(sd, TVP7002_B_FINE_GAIN, 
+							ctrl->value& 0x0f);
+		break;
+	case V4L2_CID_TVP7002_B_CLAMP:
+		error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 
+						(ctrl->value << 2) & 0x04);
+		break;
+	case V4L2_CID_TVP7002_G_CLAMP:
+		error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 
+						(ctrl->value << 1) & 0x02);
+		break;
+	case V4L2_CID_TVP7002_R_CLAMP:
+		error = tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 
+							ctrl->value & 0x01);
+		break;
+	case V4L2_CID_TVP7002_CLAMP_OFF_EN:
+		error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, 
+						(ctrl->value << 7) & 0x80);
+		break;
+	case V4L2_CID_TVP7002_FCTCA:
+		error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, 
+			    ((ctrl->value == 0 ? 0x00 : 0x03) << 3) & 0x0c);
+		break;
+	case V4L2_CID_TVP7002_F_CLAMP_GB:
+		error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, 
+						(ctrl->value << 1) & 0x02);
+		break;
+	case V4L2_CID_TVP7002_F_CLAMP_R:
+		error = tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, 
+							ctrl->value & 0x01);
+		break;
+	case V4L2_CID_TVP7002_CLAMP_START:
+		error = tvp7002_write(sd, TVP7002_CLAMP_START, 
+							ctrl->value & 0xff);
+		break;
+	case V4L2_CID_TVP7002_CLAMP_W:
+		error = tvp7002_write(sd, TVP7002_CLAMP_W, ctrl->value & 0xff);
+		break;
+	case V4L2_CID_TVP7002_B_COARSE_OFF:
+		error = tvp7002_write(sd, TVP7002_B_COARSE_OFF, 
+							ctrl->value & 0x3f);
+		break;
+	case V4L2_CID_TVP7002_G_COARSE_OFF:
+		error = tvp7002_write(sd, TVP7002_G_COARSE_OFF, 
+							ctrl->value & 0x3f);
+		break;
+	case V4L2_CID_TVP7002_R_COARSE_OFF:
+		error = tvp7002_write(sd, TVP7002_R_COARSE_OFF, 
+							ctrl->value & 0x3f);
+		break;
+	case V4L2_CID_TVP7002_B_FINE_OFF:
+		error =	tvp7002_write(sd, TVP7002_B_FINE_OFF_MSBS, 
+						(ctrl->value & 0xff) >> 2) | 
+			tvp7002_write(sd, TVP7002_FINE_OFF_LSBS, 
+						ctrl->value & 0x03);
+		break;
+	case V4L2_CID_TVP7002_G_FINE_OFF:
+		error =	tvp7002_write(sd, TVP7002_G_FINE_OFF_MSBS, 
+						(ctrl->value & 0xff) >> 2) | 
+			tvp7002_write(sd, TVP7002_FINE_OFF_LSBS, 
+						(ctrl->value & 0x03) << 2);
+		break;
+	case V4L2_CID_TVP7002_R_FINE_OFF:
+		error =	tvp7002_write(sd, TVP7002_R_FINE_OFF_MSBS, 
+						(ctrl->value & 0xff) >> 2) | 
+			tvp7002_write(sd, TVP7002_FINE_OFF_LSBS,
+						(ctrl->value & 0x03) << 4);
+		break;
+	default:
+		error = -1;
+		break;
+	}
+	
+	if (error == -1)
+		return -EINVAL;
+	else
+		return 0;
+}
+
+/*
+ * tvp7002_g_register() - Get the value of a register
+ * @sd: ptr to v4l2_subdev struct
+ * @vreg: ptr to v4l2_dbg_register struct
+ *
+ * Get the value of a TVP7002 decoder device register.
+ * Returns zero when successful, -EINVAL if register read fails or
+ * access to I2C client fails, -EPERM if the call is not allowed
+ * by diabled CAP_SYS_ADMIN.
+ */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int tvp7002_g_register(struct v4l2_subdev *sd, 
+						struct v4l2_dbg_register *reg)
+{
+	int error;
+	
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match)){
+		error = -EINVAL;
+		goto found_error;
+	}
+	if (!capable(CAP_SYS_ADMIN)){
+		error = -EPERM;
+		goto found_error;
+	}
+	
+	reg->val = tvp7002_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	
+	if (reg->val == -1)
+		error = -EINVAL;
+	else
+		error = 0;
+found_error:
+	return error;
+}
+
+/*
+ * tvp7002_s_register() - set a control
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to v4l2_control struct
+ *
+ * Get the value of a TVP7002 decoder device register.
+ * Returns zero when successful or -EINVAL if register read fails.
+ */
+static int tvp7002_s_register(struct v4l2_subdev *sd, 
+						struct v4l2_dbg_register *reg)
+{
+	int error, wres;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match)){
+		error = -EINVAL;
+		goto found_error;
+	}
+	if (!capable(CAP_SYS_ADMIN)){
+		error = -EPERM;
+		goto found_error;
+	}
+	
+	wres = tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	
+	if (wres == -1)
+		error = -EINVAL;
+	else
+		error = 0;
+	
+found_error:
+	return error;
+}
+#endif
+
+/*
+ * tvp7002_queryctrl() - Query a control
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to v4l2_queryctrl struct
+ *
+ * Query a control of a TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register read fails.
+ */
+static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	int i, error;
+
+	v4l2_info(sd, "tvp7002: queryctrl called\n");
+
+	for (i = 0; i < ARRAY_SIZE(tvp7002_qctrl); i++)
+		if (qc->id && qc->id == tvp7002_qctrl[i].id) {
+			memcpy(qc, &(tvp7002_qctrl[i]), sizeof(*qc));
+			error = 0;
+		}
+	
+	error = -EINVAL;
+
+	return error;
+}
+
+/**
+ * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @enable: streaming enable or disable
+ *
+ * Sets streaming to enable or disable, if possible.
+ */
+static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	int err = 0;
+	struct tvp7002 *decoder = to_tvp7002(sd);
+
+	if (decoder->streaming == enable)
+		return 0;
+
+	switch (enable) {
+	case 0:
+		{
+			/* Power Down Sequence */
+			err = tvp7002_write(sd, TVP7002_PWR_CTL, 0x40);
+			if (err) {
+				v4l2_err(sd, "Unable to turn off decoder\n");
+				return err;
+			}
+			decoder->streaming = enable;
+			break;
+		}
+	case 1:
+		{
+			/* Power Up Sequence */
+			err = tvp7002_write(sd, TVP7002_PWR_CTL, 0x00);
+			if (err) {
+				v4l2_err(sd, "Unable to turn on decoder\n");
+				err = -EINVAL;
+			}
+			err = tvp7002_write_inittab(sd, tvp7002_init_default);
+			if (err == -1) {
+				v4l2_err(sd, "Unable to initialize\n");
+				err = -EINVAL;
+			}
+			/* Detect if not already detected */
+			err = tvp7002_read(sd, TVP7002_CHIP_REV);
+			if (err == -1) {
+				v4l2_err(sd, "Unable to detect decoder\n");
+				err = -EINVAL;
+			}
+			decoder->streaming = enable;
+			break;
+		}
+	default:
+		{
+			err = -ENODEV;
+			break;
+		}
+	}
+
+	return err;
+}
+
+/* Specific video subsystem operation handlers */
+static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
+	.querystd = tvp7002_querystd,
+	.s_stream = tvp7002_s_stream,
+	.g_fmt = tvp7002_g_fmt,
+};
+
+/* V4L2 Operations handlers */
+static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
+	.g_chip_ident = tvp7002_g_chip_ident,
+	.log_status = tvp7002_log_status,
+	.g_ctrl = tvp7002_g_ctrl,
+	.s_ctrl = tvp7002_s_ctrl,
+	.queryctrl = tvp7002_queryctrl,
+	.s_std = tvp7002_s_std,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = tvp7002_g_register,
+	.s_register = tvp7002_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_ops tvp7002_ops = {
+	.core = &tvp7002_core_ops,
+	.video = &tvp7002_video_ops,
+};
+
+/*
+ * tvp7002_reset - Reset a TVP7002 device
+ * @sd: ptr to v4l2_subdev struct
+ * @val: unsigned integer (not used)
+ *
+ * Reset the TVP7002 device
+ * Returns zero when successful or -EINVAL if register read fails.
+ */
+static int tvp7002_reset(struct v4l2_subdev *sd, u32 val)
+{
+	int error;
+	int polarity;
+
+	error = tvp7002_read(sd, TVP7002_CHIP_REV);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+
+	if (error == 0x02)
+		v4l2_info(sd, "tvp7002: rev. %02x detected.\n", error);
+	
+	else {
+		v4l2_info(sd, "tvp7002: unknown revision detected.\n");
+		v4l2_info(sd, "tvp7002: revision number is %02x\n", error);
+	}
+
+	/* Set polarity information */
+	polarity = tvp7002_pdata.clk_polarity & tvp7002_pdata.hs_polarity &
+		   tvp7002_pdata.vs_polarity & tvp7002_pdata.fid_polarity; 
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_2, polarity);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+
+	/* Initializes TVP7002 to its default values */
+	error = tvp7002_write_inittab(sd, tvp7002_init_default);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+
+found_error:
+	return error;
+};
+
+/*
+ * tvp7002_probe - Reset a TVP7002 device
+ * @sd: ptr to v4l2_subdev struct
+ * @ctrl: ptr to i2c_device_id struct
+ *
+ * Reset the TVP7002 device
+ * Returns zero when successful or -EINVAL if register read fails.
+ */
+static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
+{
+	int error;
+	int polarity;
+	struct tvp7002 *core;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(c->adapter,
+	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)){
+	     	error = -EIO; 
+	}
+
+	core = kzalloc(sizeof(struct tvp7002), GFP_KERNEL);
+	
+	if (!core) {
+		error = -ENOMEM;
+	}
+	sd = &core->sd;
+	v4l2_i2c_subdev_init(sd, c, &tvp7002_ops);
+	v4l_info(c, "tvp7002 found @ 0x%02x (%s)\n",
+		 c->addr << 1, c->adapter->name);
+
+	/* Set polarity information */
+	polarity = tvp7002_pdata.clk_polarity & tvp7002_pdata.hs_polarity &
+		   tvp7002_pdata.vs_polarity & tvp7002_pdata.fid_polarity; 
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_2, polarity);
+	if (error == -1){
+		error = -EINVAL;
+		goto found_error;
+	}
+	
+	/* Set video mode */
+	core->video_mode = V4L2_STD_480P_60;
+
+	if (debug > 1)
+		error = tvp7002_log_status(sd);
+	else
+		error = 0;
+		
+found_error:
+	return error;
+}
+
+/*
+ * tvp7002_remove - Remove TVP7002 device support
+ * @c: ptr to i2c_client struct
+ *
+ * Reset the TVP7002 device
+ * Returns zero when successful or -EINVAL if register read fails.
+ */
+static int tvp7002_remove(struct i2c_client *c)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+	v4l2_dbg(1, debug, sd, "tvp7002.c: removing tvp7002 adapter" 
+				"on address 0x%x\n", c->addr << 1);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_tvp7002(sd));
+	return 0;
+}
+
+/* I2C Device ID table */
+static const struct i2c_device_id tvp7002_id[] = {
+	{ "tvp7002", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tvp7002_id);
+
+/* I2C driver data */
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "tvp7002",
+	.probe = tvp7002_probe,
+	.remove = tvp7002_remove,
+	.id_table = tvp7002_id,
+};