diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 362ac62..54d7eef 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -43,6 +43,7 @@
 #include <mach/nand.h>
 #include <linux/videodev2.h>
 #include <media/tvp514x.h>
+#include <media/tvp7002.h>
 
 
 static inline int have_imager(void)
@@ -53,14 +54,20 @@ static inline int have_imager(void)
 
 static inline int have_tvp7002(void)
 {
-	/* REVISIT when it's supported, trigger via Kconfig */
+#ifdef CONFIG_VIDEO_TVP7002
+	return 1;
+#else
 	return 0;
+#endif
 }
 
 
 #define DM365_ASYNC_EMIF_CONTROL_BASE	0x01d10000
 #define DM365_ASYNC_EMIF_DATA_CE0_BASE	0x02000000
 #define DM365_ASYNC_EMIF_DATA_CE1_BASE	0x04000000
+#define DM365_ASYNC_EMIF_DATA_CE1_REG3	0x18
+#define DM365_ASYNC_EMIF_VIDEO_MUX_MASK	(0x07070707)
+#define DM365_ASYNC_EMIF_TVP7002_SEL	(0x01010101)
 
 #define DM365_EVM_PHY_MASK		(0x2)
 #define DM365_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
@@ -109,6 +116,13 @@ static struct tvp514x_platform_data tvp5146_pdata = {
        .vs_polarity = 1
 };
 
+// According to TI's tvp7002 datasheet
+static struct tvp7002_platform_data tvp7002_pdata = {
+       .clk_polarity = 0,
+       .hs_polarity = 1,
+       .vs_polarity = 1
+};
+
 /* NOTE:  this is geared for the standard config, with a socketed
  * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors.  If you
  * swap chips, maybe with a different block size, partitioning may
@@ -243,6 +257,18 @@ static struct v4l2_input tvp5146_inputs[] = {
 	},
 };
 
+#define TVP7002_STD_ALL        (V4L2_STD_525_60 | V4L2_STD_625_50 |\
+								V4L2_STD_725_50 | V4L2_STD_825_60)
+/* Inputs available at the TVP7002 */
+static struct v4l2_input tvp7002_inputs[] = {
+	{
+		.index = 0,
+		.name = "Component",
+		.type = V4L2_INPUT_TYPE_CAMERA,
+		.std = TVP7002_STD_ALL,
+	},
+};
+
 /*
  * this is the route info for connecting each input to decoder
  * ouput that goes to vpfe. There is a one to one correspondence
@@ -259,8 +285,20 @@ static struct vpfe_route tvp5146_routes[] = {
 	},
 };
 
+/*
+ * this is the route info for connecting each input to decoder
+ * ouput that goes to vpfe. There is a one to one correspondence
+ * with tvp7002_inputs
+ */
+static struct vpfe_route tvp7002_routes[] = {
+	{
+		.input = TVP7002_RIN_1,
+		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+	},
+};
+
 static struct vpfe_subdev_info vpfe_sub_devs[] = {
-{
+        {
 		.module_name = "tvp5146",
 		.grp_id = 0,
 		.num_inputs = ARRAY_SIZE(tvp5146_inputs),
@@ -276,6 +314,23 @@ static struct vpfe_subdev_info vpfe_sub_devs[] = {
 			I2C_BOARD_INFO("tvp5146", 0x5d),
 			.platform_data = &tvp5146_pdata,
 		},
+	},
+        {
+		.module_name = "tvp7002",
+		.grp_id = 0,
+		.num_inputs = ARRAY_SIZE(tvp7002_inputs),
+		.inputs = tvp7002_inputs,
+		.routes = tvp7002_routes,
+		.can_route = 1,
+		.ccdc_if_params = {
+			.if_type = VPFE_BT1120,
+			.hdpol = VPFE_PINPOL_POSITIVE,
+			.vdpol = VPFE_PINPOL_POSITIVE,
+		},
+		.board_info = {
+			I2C_BOARD_INFO("tvp7002", 0x5c),
+			.platform_data = &tvp7002_pdata,
+		},
 	}
 };
 
@@ -286,6 +341,7 @@ static struct vpfe_config vpfe_cfg = {
        .ccdc = "DM365 ISIF",
        .num_clocks = 1,
        .clocks = {"vpss_master"},
+//       .setup_input = dm365evm_setup_video_input,
 };
 
 static struct davinci_mmc_config dm365evm_mmc_config = {
@@ -439,6 +495,16 @@ static int __init cpld_leds_init(void)
 /* run after subsys_initcall() for LEDs */
 fs_initcall(cpld_leds_init);
 
+/* Set the input mux for TVP7002 */
+int tvp7002_set_input_mux(unsigned char channel)
+{
+	u32 val;
+	val = __raw_readl(DM365_ASYNC_EMIF_DATA_CE1_REG3);
+	val &= ~DM365_ASYNC_EMIF_VIDEO_MUX_MASK;
+	val |= DM365_ASYNC_EMIF_TVP7002_SEL;
+	__raw_writel(val, DM365_ASYNC_EMIF_DATA_CE1_REG3);
+	return 0;
+}
 
 static void __init evm_init_cpld(void)
 {
@@ -519,6 +585,8 @@ fail:
 			mux |= 2;
 			resets &= ~BIT(2);
 			label = "tvp7002 HD";
+			// Call the input setter
+			tvp7002_set_input_mux(0);
 		} else {
 			/* default to tvp5146 */
 			mux |= 5;
@@ -526,8 +594,8 @@ fail:
 			label = "tvp5146 SD";
 		}
 	}
-	__raw_writeb(mux, cpld + CPLD_MUX);
-	__raw_writeb(resets, cpld + CPLD_RESETS);
+	__raw_writel(mux, cpld + CPLD_MUX);
+	__raw_writel(resets, cpld + CPLD_RESETS);
 	pr_info("EVM: %s video input\n", label);
 
 	/* REVISIT export switches: NTSC/PAL (SW5.6), EXTRA1 (SW5.2), etc */
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d3723a1..a35395e 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -383,6 +383,15 @@ config VIDEO_TVP5150
 	  To compile this driver as a module, choose M here: the
 	  module will be called tvp5150.
 
+config VIDEO_TVP7002
+	tristate "Texas Instruments TVP7002 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Texas Instruments TVP7002 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp7002.
+
 config VIDEO_VPX3220
 	tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 00fb23e..9a8090e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
 obj-$(CONFIG_VIDEO_VINO) += indycam.o
 obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
 obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
index ff8677c..5f18219 100644
--- a/drivers/media/video/davinci/vpfe_capture.c
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -142,6 +142,8 @@ static struct ccdc_config *ccdc_cfg;
 const struct vpfe_standard vpfe_standards[] = {
 	{V4L2_STD_525_60, 720, 480, {11, 10}, 1},
 	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
+	{V4L2_STD_725_50, 1280, 720, {12, 10}, 0},
+	{V4L2_STD_825_60, 1920, 1080, {12, 10}, 1},
 };
 
 /* Used when raw Bayer image from ccdc is directly captured to SDRAM */
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
new file mode 100644
index 0000000..60e401d
--- /dev/null
+++ b/drivers/media/video/tvp7002.c
@@ -0,0 +1,2309 @@
+/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics Digitizer
+ * with Horizontal PLL registers
+ * 
+ * Copyright (C) 2009 Santiago Nunez-Corrales (santiago.nunez@ridgerun.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#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"
+
+/* 
+ * Macro for identifying whether we are within a SD video mode. Required
+ * for identifying if extra registers have to be set up.
+ */
+
+#define STD_INDEX(mode)		( (mode) & ~V4L2_STD_TVP7002_BASE_STD )
+#define IS_SD_MODE(mode)	( (mode) <= STD_INDEX(TVP7002_VIDEOP_1920_1080_50) && (mode) >= STD_INDEX(TVP7002_VIDEOI_720_480_30) )
+#define IS_XGA60_MODE(mode)	( (mode) == STD_INDEX(TVP7002_XGA_1024_768_60) ) 
+
+MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
+MODULE_AUTHOR("Santiago Nunez-Corrales (santiago.nunez@ridgerun.com)");
+MODULE_LICENSE("GPL");
+
+/*** Debugging information ***/
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+/*** Data structures ***/
+
+/* Register default values (according to 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 = TVP7002_VGA_640_480_60,
+		.hres = 640,
+		.vres = 480,
+		.frate = 60,
+		.lrate = 31,
+		.prate = 25,
+		.reg01 = 0x32,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VGA_640_480_73,
+		.hres = 640,
+		.vres = 480,
+		.frate = 73,
+		.lrate = 38,
+		.prate = 32,
+		.reg01 = 0x34,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VGA_640_480_75,
+		.hres = 640,
+		.vres = 480,
+		.frate = 75,
+		.lrate = 38,
+		.prate = 32,
+		.reg01 = 0x34,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VGA_640_480_85,
+		.hres = 640,
+		.vres = 480,
+		.frate = 85,
+		.lrate = 43,
+		.prate = 36,
+		.reg01 = 0x34,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SVGA_800_600_56,
+		.hres = 800,
+		.vres = 600,
+		.frate = 56,
+		.lrate = 35,
+		.prate = 36,
+		.reg01 = 0x40,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SVGA_800_600_60,
+		.hres = 800,
+		.vres = 600,
+		.frate = 60,
+		.lrate = 38,
+		.prate = 40,
+		.reg01 = 0x42,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SVGA_800_600_72,
+		.hres = 800,
+		.vres = 600,
+		.frate = 72,
+		.lrate = 48,
+		.prate = 50,
+		.reg01 = 0x41,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SVGA_800_600_75,
+		.hres = 800,
+		.vres = 600,
+		.frate = 75,
+		.lrate = 47,
+		.prate = 50,
+		.reg01 = 0x42,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SVGA_800_600_85,
+		.hres = 800,
+		.vres = 600,
+		.frate = 85,
+		.lrate = 54,
+		.prate = 56,
+		.reg01 = 0x41,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_XGA_1024_768_60,
+		.hres = 1025,
+		.vres = 768,
+		.frate = 60,
+		.lrate = 48,
+		.prate = 65,
+		.reg01 = 0x54,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_XGA_1024_768_70,
+		.hres = 1025,
+		.vres = 768,
+		.frate = 70,
+		.lrate = 56,
+		.prate = 75,
+		.reg01 = 0x53,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x28,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_XGA_1024_768_75,
+		.hres = 1025,
+		.vres = 768,
+		.frate = 75,
+		.lrate = 60,
+		.prate = 79,
+		.reg01 = 0x52,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x28,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_XGA_1024_768_85,
+		.hres = 1025,
+		.vres = 768,
+		.frate = 85,
+		.lrate = 69,
+		.prate = 95,
+		.reg01 = 0x56,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA1_1280_768_60_L,
+		.hres = 1280,
+		.vres = 768,
+		.frate = 60,
+		.lrate = 47,
+		.prate = 68,
+		.reg01 = 0x5a,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_LOW | 0x10,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA1_1280_768_60_H,
+		.hres = 1280,
+		.vres = 768,
+		.frate = 60,
+		.lrate = 48,
+		.prate = 80,
+		.reg01 = 0x68,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA1_1280_768_75,
+		.hres = 1280,
+		.vres = 768,
+		.frate = 75,
+		.lrate = 60,
+		.prate = 102,
+		.reg01 = 0x6b,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA1_1280_768_85,
+		.hres = 1280,
+		.vres = 768,
+		.frate = 85,
+		.lrate = 69,
+		.prate = 118,
+		.reg01 = 0x6b,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGA_1280_1024_60,
+		.hres = 1280,
+		.vres = 1024,
+		.frate = 60,
+		.lrate = 64,
+		.prate = 108,
+		.reg01 = 0x69,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGA_1280_1024_75,
+		.hres = 1280,
+		.vres = 1024,
+		.frate = 75,
+		.lrate = 80,
+		.prate = 135,
+		.reg01 = 0x69,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x28,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGA_1280_1024_85,
+		.hres = 1280,
+		.vres = 1024,
+		.frate = 85,
+		.lrate = 91,
+		.prate = 158,
+		.reg01 = 0x6c,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x28,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGAPLUS_1400_1050_60_L,
+		.hres = 1400,
+		.vres = 1050,
+		.frate = 60,
+		.lrate = 65,
+		.prate = 101,
+		.reg01 = 0x61,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGAPLUS_1400_1050_60_H,
+		.hres = 1400,
+		.vres = 1050,
+		.frate = 60,
+		.lrate = 65,
+		.prate = 121,
+		.reg01 = 0x74,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_SXGAPLUS_1400_1050_75,
+		.hres = 1400,
+		.vres = 1050,
+		.frate = 75,
+		.lrate = 82,
+		.prate = 156,
+		.reg01 = 0x76,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA2_1440_900_60_L,
+		.hres = 1440,
+		.vres = 900,
+		.frate = 60,
+		.lrate = 55,
+		.prate = 89,
+		.reg01 = 0x64,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA2_1440_900_60_H,
+		.hres = 1440,
+		.vres = 900,
+		.frate = 60,
+		.lrate = 56,
+		.prate = 107,
+		.reg01 = 0x77,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA2_1440_900_75,
+		.hres = 1440,
+		.vres = 900,
+		.frate = 75,
+		.lrate = 71,
+		.prate = 137,
+		.reg01 = 0x79,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_WXGA2_1440_900_85,
+		.hres = 1440,
+		.vres = 900,
+		.frate = 85,
+		.lrate = 80,
+		.prate = 157,
+		.reg01 = 0x7a,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_UXGA_1600_1200_60,
+		.hres = 1600,
+		.vres = 1200,
+		.frate = 60,
+		.lrate = 75,
+		.prate = 162,
+		.reg01 = 0x87,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x00,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOI_720_480_30,
+		.hres = 720,
+		.vres = 480,
+		.frate = 30,
+		.lrate = 15,
+		.prate = 14,
+		.reg01 = 0x35,
+		.reg02 = 0xa0,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOI_720_576_25,
+		.hres = 720,
+		.vres = 576,
+		.frate = 25,
+		.lrate = 16,
+		.prate = 14,
+		.reg01 = 0x36,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_720_480_60,
+		.hres = 720,
+		.vres = 480,
+		.frate = 60,
+		.lrate = 31,
+		.prate = 27,
+		.reg01 = 0x35,
+		.reg02 = 0xa0,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_720_576_50,
+		.hres = 720,
+		.vres = 576,
+		.frate = 50,
+		.lrate = 31,
+		.prate = 27,
+		.reg01 = 0x36,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_ULOW | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_1280_720_60,
+		.hres = 1280,
+		.vres = 720,
+		.frate = 60,
+		.lrate = 45,
+		.prate = 74,
+		.reg01 = 0x67,
+		.reg02 = 0x20,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x20,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_1280_720_50,
+		.hres = 1280,
+		.vres = 720,
+		.frate = 50,
+		.lrate = 38,
+		.prate = 74,
+		.reg01 = 0x7b,
+		.reg02 = 0xc0,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOI_1920_1080_60,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 60,
+		.lrate = 34,
+		.prate = 74,
+		.reg01 = 0x89,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOI_1920_1080_50,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 50,
+		.lrate = 28,
+		.prate = 74,
+		.reg01 = 0xa5,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_MED | 0x10,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_1920_1080_60,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 60,
+		.lrate = 68,
+		.prate = 149,
+		.reg01 = 0x89,
+		.reg02 = 0x80,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x20,
+		.reg04 = 0x80,
+		.available = TRUE,
+	}, {
+		.id = TVP7002_VIDEOP_1920_1080_50,
+		.hres = 1920,
+		.vres = 1080,
+		.frate = 50,
+		.lrate = 56,
+		.prate = 149,
+		.reg01 = 0xa5,
+		.reg02 = 0x00,
+		.reg03 = TVP7002_VCO_RANGE_HIGH | 0x18,
+		.reg04 = 0x80,
+		.available = TRUE,
+	},
+};
+
+/* I2C Device ID table */
+static const struct i2c_device_id tvp7002_id[] = {
+	{ "tvp7002", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, tvp7002_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "tvp7002",
+	.probe = tvp7002_probe,
+	.remove = tvp7002_remove,
+	.id_table = tvp7002_id,
+};
+
+/* Device definition */
+
+struct tvp7002 {
+	struct v4l2_subdev sd;
+	v4l2_std_id video_mode;
+};
+
+/* Supported controls */
+
+static struct v4l2_queryctrl tvp7002_qctrl[] = {
+    {
+		.id = V4L2_CID_COARSE_GAIN_R,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for Red channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+	{
+		.id = V4L2_CID_COARSE_GAIN_G,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for Green channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+	{
+		.id = V4L2_CID_COARSE_GAIN_B,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Coarse gain for Blue channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_FINE_GAIN_R,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for Red channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+	{
+		.id = V4L2_CID_FINE_GAIN_G,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for Green channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+	{
+		.id = V4L2_CID_FINE_GAIN_B,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Fine gain for Blue channel",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 7,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SOG_IN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Sync-On-Green input",
+		.minimum = 0,
+		.maximum = 2,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_R_IN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red input",
+		.minimum = 0,
+		.maximum = 2,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_G_IN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Green input",
+		.minimum = 0,
+		.maximum = 3,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_R_IN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue input",
+		.minimum = 0,
+		.maximum = 2,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_SOG_LPF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Sync-On-Green low pass filter",
+		.minimum = 0,
+		.maximum = 2,
+		.step = 1,
+		.default_value = 3,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_CLAMP_LPF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Clamp low pass filter",
+		.minimum = 0,
+		.maximum = 2,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_CLK_IN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Clock input",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_VSYNC_IN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "VSYNC input",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PIXEL_CLK_IN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Pixel clock input",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_HSYNC_IN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "HSYNC input",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SOG_THRS,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Sync-On-Green threshold",
+		.minimum = 0,
+		.maximum = 31,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_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_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_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_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_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_F_CLAMP_GB,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Fine clamp for Green and Blue",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+	{
+		.id = V4L2_CID_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_CLAMP_START,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Clamp start",
+		.minimum = 0,
+		.maximum = 255,
+		.step = 1,
+		.default_value = 0x32,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_CLAMP_W,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Clamp width",
+		.minimum = 0,
+		.maximum = 255,
+		.step = 1,
+		.default_value = 0x20,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_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_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_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_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_G_FINE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Green coarse offset",
+		.minimum = 0,
+		.maximum = 1024,
+		.step = 1,
+		.default_value = 512,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_R_FINE_OFF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red coarse offset",
+		.minimum = 0,
+		.maximum = 1024,
+		.step = 1,
+		.default_value = 512,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_ALC_EN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Automatic level control (ALC)",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_ALC_PLACEMENT,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "ALC placement",
+		.minimum = 0,
+		.maximum = 255,
+		.step = 1,
+		.default_value = 0x5a,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_ALC_FILTER_VERT_CF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "ALC vertical coefficient",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 10,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_ALC_FILTER_HORZ_CF,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "ALC horizontal coefficient",
+		.minimum = 0,
+		.maximum = 7,
+		.step = 1,
+		.default_value = 3,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_CLAMP_ALC_PULSE_RF,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Clamp and ALC pulse reference",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_OUT_CODE_RANGE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Output code range",
+		.minimum = 0,
+		.maximum = 3,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_OUT_CBCR_ORDER,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "YUV CbCr output order",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_OUT_422_444,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "4:4:4/4:2:2 output format",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_OUT_EMB_SYNC_EN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Embedded SYNC enable",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	},
+	{
+		.id = V4L2_CID_SYNC_HSPO,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "HSYNC polarity override",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_HSIP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "HSYNC input polarity (caution)",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_HSOP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "HSYNC output polarity",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_AHSO,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Active HSYNC override",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_AHSS,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Active HSYNC select",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_VSOP,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "VSYNC output polarity",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_AVSO,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Active VSYNC override",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SYNC_AVSS,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Active VSYNC select",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_SEEK_MODE_OVRD,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "SYNC mode override",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_FCPD,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Full chip power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 1,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_SOG_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Sync-On-Green power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_SLICER_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Slicer power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_REF_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Reference power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_CURRENT_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Current power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_ADC_B_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "ADC Blue channel power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_ADC_G_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "ADC Green channel power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    },
+    {
+		.id = V4L2_CID_PWR_ADC_R_PWDN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "ADC Red channel power down",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+    }
+};
+
+/** 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
+};
+
+/* Specific video subsystem operation handlers */
+static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
+	.querystd = tvp7002_querystd,
+};
+
+static const struct v4l2_subdev_ops tvp7002_ops = {
+	.core = &tvp7002_core_ops,
+	.video = &tvp7002_video_ops,
+};
+
+/*** Functions ***/
+
+/** Register access functions **/
+
+/* Read the contents of a register */
+static int tvp7002_read(struct v4l2_subdev *sd, unsigned char addr){
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[1];
+	int rc;
+	
+	buffer[0] = addr;
+	if (1 != (rc = i2c_master_send(c, buffer, 1)))
+		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
+	
+	/* Sleep and try once more */
+	msleep(10);
+	
+	if (1 != (rc = i2c_master_recv(c, buffer, 1)))
+		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
+	
+	v4l2_dbg(2, debug, sd, "tvp7002: read 0x%02x = 0x%02x\n", addr, buffer[0]);
+	
+	return (buffer[0]);
+}
+
+/* Write data to a register */
+static int tvp7002_write(struct v4l2_subdev *sd, unsigned char addr, unsigned char value){
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[2];
+	int rc;
+
+	buffer[0] = addr;
+	buffer[1] = value;
+	v4l2_dbg(2, debug, sd, "tvp7002: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+	
+	if (2 != (rc = i2c_master_send(c, buffer, 2))){
+		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
+		return -1;
+	}
+	
+	return 0;
+        
+}
+
+/* Read data in registers withing a range given by [init..end] */
+static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init, const u8 end, int max_line){
+	int i = 0;
+	
+	while (init != (u8)(end + 1)) {
+		if ((i % max_line) == 0) {
+			if (i > 0)
+			printk("\n");
+			printk("tvp7002: %s reg 0x%02x = ", s, init);
+		}
+		
+		printk("%02x ", tvp7002_read(sd, init));
+		init++;
+		i++;
+	}
+	printk("\n");
+}
+
+/* Log function for register contents */
+static int tvp7002_log_status(struct v4l2_subdev *sd){
+	printk("tvp7002: Chip revision number = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_CHIP_REV));
+	printk("tvp7002: H-PLL feedback divider MSBs and LSBs = 0x%02x, 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_MSBS), 
+			tvp7002_read(sd, TVP7002_HPLL_FDBK_DIV_LSBS));
+	printk("tvp7002: VCO frequency range selector = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_CRTL));
+	printk("tvp7002: ADC sampling clock phase selector = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_PHASE_SEL));
+	printk("tvp7002: Clamp start = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_CLAMP_START));
+	printk("tvp7002: Clamp width = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_CLAMP_W));
+	printk("tvp7002: HSYNC output width = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HSYNC_OUT_W));
+	printk("tvp7002: Digital fine grain for Blue channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_B_FINE_GAIN));
+	printk("tvp7002: Digital fine grain for Green channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_G_FINE_GAIN));
+	printk("tvp7002: Digital fine grain for Red channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_R_FINE_GAIN));
+	printk("tvp7002: Digital fine grain offset for Blue channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS));
+	printk("tvp7002: Digital fine grain offset for Green channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS));
+	printk("tvp7002: Digital fine grain offset for Red channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_R_FINE_OFF_MSBS));
+	printk("tvp7002: Digital fine grain LSB offsets for RGB channels = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_FINE_OFF_LSBS));
+	printk("tvp7002: SYNC control 1  = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SYNC_CTL_1));
+	printk("tvp7002: H-PLL and clamp control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_AND_CLAMP_CTL));
+	printk("tvp7002: Sync-On-Green threshold = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS));
+	printk("tvp7002: Sync separator threshold = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SYNC_SEPARATOR_THRS));
+	printk("tvp7002: H-PLL pre-coast = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_PRE_COAST));
+	printk("tvp7002: H-PLL post-coast = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HPLL_POST_COAST));
+	printk("tvp7002: Sync detect status = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SYNC_DETECT_STAT));
+	printk("tvp7002: Output formatter = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_OUT_FORMATTER));
+	printk("tvp7002: Miscelaneous control 1 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_MISC_CTL_1));
+	printk("tvp7002: Miscelaneous control 2 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_MISC_CTL_2));
+	printk("tvp7002: Miscelaneous control 3 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_MISC_CTL_3));
+	printk("tvp7002: Input Mux Selector 1 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_IN_MUX_SEL_1));
+	printk("tvp7002: Input Mux Selector 2 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_IN_MUX_SEL_2));
+	printk("tvp7002: Blue and Green coarse gain = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN));
+	printk("tvp7002: Red coarse gain = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_R_COARSE_GAIN));
+	printk("tvp7002: Coarse offset for Blue channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_B_COARSE_OFF));
+	printk("tvp7002: Coarse offset for Green channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_G_COARSE_OFF));
+	printk("tvp7002: Coarse offset for Red channel = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_R_COARSE_OFF));
+	printk("tvp7002: HSYNC leading edge output start = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HSOUT_OUT_START));
+	printk("tvp7002: Miscelaneous control 4 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_MISC_CTL_4));
+	printk("tvp7002: Filtered digital ALC output for Blue channel LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_B_DGTL_ALC_OUT_LSBS));
+	printk("tvp7002: Filtered digital ALC output for Green channel LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_G_DGTL_ALC_OUT_LSBS));
+	printk("tvp7002: Filtered digital ALC output for Red channel LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_R_DGTL_ALC_OUT_LSBS));
+	printk("tvp7002: Automatic level control enable = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_ENABLE));
+	printk("tvp7002: Filtered digital ALC output for RGB channels MSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_DGTL_ALC_OUT_MSBS));
+	printk("tvp7002: Automatic level control filter = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_FILTER));
+	printk("tvp7002: Fine clamp control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL));
+	printk("tvp7002: Power control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_PWR_CTL));
+	printk("tvp7002: ADC setup = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_ADC_SETUP));
+	printk("tvp7002: Coarse clamp control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_COARSE_CLAMP_CTL));
+	printk("tvp7002: Sync-On-Green clamp = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SOG_CLAMP));
+	printk("tvp7002: RGB coarse clamp control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_RGB_COARSE_CLAMP_CTL));
+	printk("tvp7002: Sync-On-Green coarse clamp control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SOG_COARSE_CLAMP_CTL));
+	printk("tvp7002: ALC placement = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_ALC_PLACEMENT));
+	printk("tvp7002: Macrovision stripper width = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_MVIS_STRIPPER_W));
+	printk("tvp7002: VSYNC alignment = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VSYNC_ALGN));
+	printk("tvp7002: Sync bypass = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_SYNC_BYPASS));
+	printk("tvp7002: Lines per frame status MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_L_FRAME_STAT_MSBS),
+			tvp7002_read(sd, TVP7002_L_FRAME_STAT_LSBS));
+	printk("tvp7002: Clocks per line status MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_CLK_L_STAT_MSBS),
+			tvp7002_read(sd, TVP7002_CLK_L_STAT_LSBS));
+	printk("tvp7002: HSYNC width = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_HSYNC_W));
+	printk("tvp7002: VSYNC width = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VSYNC_W));
+	printk("tvp7002: Line length tolerance = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_L_LENGTH_TOL));
+	printk("tvp7002: Video bandwidth control = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VIDEO_BWTH_CTL));
+	printk("tvp7002: AVID start pixel MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_AVID_START_PIXEL_MSBS),
+			tvp7002_read(sd, TVP7002_AVID_START_PIXEL_LSBS));
+	printk("tvp7002: AVID stop pixel MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_MSBS),
+			tvp7002_read(sd, TVP7002_AVID_STOP_PIXEL_LSBS));
+	printk("tvp7002: VBLK start line offset 0 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VBLK_F_0_START_L_OFF));
+	printk("tvp7002: VBLK start line offset 1 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VBLK_F_1_START_L_OFF));
+	printk("tvp7002: VBLK duration 0 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VBLK_F_0_DURATION));
+	printk("tvp7002: VBLK duration 1 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_VBLK_F_1_DURATION));
+	printk("tvp7002: F-bit start line offset 0 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_FBIT_F_0_START_L_OFF));
+	printk("tvp7002: F-bit start line offset 1 = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_FBIT_F_1_START_L_OFF));
+	printk("tvp7002: YUV Y coefficient for Green MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_Y_G_COEF_LSBS));
+	printk("tvp7002: YUV Y coefficient for Blue MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_Y_B_COEF_LSBS));
+	printk("tvp7002: YUV Y coefficient for Red MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_Y_R_COEF_LSBS));
+	printk("tvp7002: YUV U coefficient for Green MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_U_G_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_U_G_COEF_LSBS));
+    printk("tvp7002: YUV U coefficient for Blue MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_U_B_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_U_B_COEF_LSBS));
+    printk("tvp7002: YUV U coefficient for Red MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_U_R_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_U_R_COEF_LSBS));
+	printk("tvp7002: YUV V coefficient for Green MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_V_G_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_V_G_COEF_LSBS));
+    printk("tvp7002: YUV V coefficient for Blue MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_V_B_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_V_B_COEF_LSBS));
+    printk("tvp7002: YUV V coefficient for Red MSBs and LSBs = 0x%02x LSBs = 0x%02x\n",
+			tvp7002_read(sd, TVP7002_YUV_V_R_COEF_MSBS),
+			tvp7002_read(sd, TVP7002_YUV_V_R_COEF_LSBS));
+
+	return 0;
+}
+
+/** Device access functions **/
+
+/* Obtain parent structure */
+static struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd){
+	return container_of(sd, struct tvp7002, sd);
+}
+
+/* Get chip identification information */
+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);
+	
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev);
+}
+
+/* Initialize for default values */
+static int tvp7002_write_inittab(struct v4l2_subdev *sd, const struct i2c_reg_value *regs){
+	int i;
+	/* Initialize the first (defined) registers */
+	while (regs->reg != 0x5c) {
+		tvp7002_write(sd, regs->reg, regs->value);
+		regs++;
+	}
+	/* Initialize the last (undefined) registers */
+	for (i = 0x5c; i <= 0xff; i++)
+		tvp7002_write(sd, i, 0x00);
+	
+	return 0;
+}
+
+/* Set video mode */
+static int tvp7002_set_video_mode(struct v4l2_subdev *sd, int sdf){
+	/* If this configuration exists but is not available, signal correspondingly */
+	if (!tvp7002_resolutions[sdf].available){
+		v4l2_err(sd, "tvp7002: Standard Display Format is not available in current implementation\n");
+		return -1;
+	}
+
+	/* Print specific information about current format */
+	printk("tvp7002: Setting standard display format...\n");
+	printk("tvp7002: hres = %d vres=%d frate=%d lrate=%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 */
+	tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_MSBS, tvp7002_resolutions[sdf].reg01);
+	tvp7002_write(sd, TVP7002_HPLL_FDBK_DIV_LSBS, tvp7002_resolutions[sdf].reg02);
+	tvp7002_write(sd, TVP7002_HPLL_CRTL, tvp7002_resolutions[sdf].reg03);
+	tvp7002_write(sd, TVP7002_HPLL_PHASE_SEL, tvp7002_resolutions[sdf].reg04);
+	
+	/* Now, the tricky part for SD modes */
+	if (IS_SD_MODE(sdf)){
+		// Set registers 05h, 06h, 12h, 13h, 1Ah, 22h, 31h
+		if (sdf < TVP7002_VIDEOP_720_480_60){
+			tvp7002_write(sd, TVP7002_CLAMP_START, 0x06);
+			tvp7002_write(sd, TVP7002_CLAMP_W, 0x10);
+			tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x03);
+			tvp7002_write(sd, TVP7002_HPLL_POST_COAST, 0x03);
+			tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0x17);
+			if (sdf < TVP7002_VIDEOP_720_480_60){
+				tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x0c);
+				tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x24);
+			}
+			else {
+				tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x0a);
+				tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x12);
+			}
+			tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x08);
+			tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x18);
+		}
+		else {
+			tvp7002_write(sd, TVP7002_CLAMP_START, 0x32);
+			tvp7002_write(sd, TVP7002_CLAMP_W, 0x20);
+			tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x01);
+			tvp7002_write(sd, TVP7002_HPLL_POST_COAST, 0x00);
+			tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0xc7);
+			if(sdf < TVP7002_VIDEOI_1920_1080_60)
+				tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x35);
+			else
+				tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x39);
+			tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x00);
+			tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x5a);
+			if(sdf < TVP7002_VIDEOP_1920_1080_60)
+				tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x07);
+			else
+				tvp7002_write(sd, TVP7002_MVIS_STRIPPER_W, 0x03);
+		}
+		// Set registers 2Ch and 3Fh
+		if (sdf < TVP7002_VIDEOP_1920_1080_60){
+			tvp7002_write(sd, TVP7002_ADC_SETUP, 0x50);
+			tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x0f);
+		}
+		else {
+			tvp7002_write(sd, TVP7002_ADC_SETUP, 0x80);
+			tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x00);
+		}
+		// Set up registers that hold the same value regardless
+		// of the SD mode 
+		tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 0x5d);
+		tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
+		tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+		tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
+		tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
+		tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
+		tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);;
+		tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
+		tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+		tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
+		tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
+		tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
+		tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
+	}
+	else if ( IS_XGA60_MODE(sdf) ){
+		tvp7002_write(sd, TVP7002_CLAMP_START, 0x06);
+		tvp7002_write(sd, TVP7002_CLAMP_W, 0x10);
+		tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, 0x58);
+		tvp7002_write(sd, TVP7002_SYNC_SEPARATOR_THRS, 0x40);
+		tvp7002_write(sd, TVP7002_HPLL_PRE_COAST, 0x01);
+		tvp7002_write(sd, TVP7002_HPLL_POST_COAST, 0x00);
+		tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+		tvp7002_write(sd, TVP7002_MISC_CTL_3, 0x01);
+		tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, 0x00);
+		tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, 0xc7);
+		tvp7002_write(sd, TVP7002_HSOUT_OUT_START, 0x0d);
+		tvp7002_write(sd, TVP7002_MISC_CTL_4, 0x00);
+		tvp7002_write(sd, TVP7002_ADC_SETUP, 0x50);
+		tvp7002_write(sd, TVP7002_ALC_PLACEMENT, 0x18);
+		// Macrovision strip width register is set to its default value
+		tvp7002_write(sd, TVP7002_VSYNC_ALGN, 0x00);
+		tvp7002_write(sd, TVP7002_L_LENGTH_TOL, 0x06);
+		tvp7002_write(sd, TVP7002_VIDEO_BWTH_CTL, 0x00);
+	}
+	
+	return 0;
+}
+
+/* Get video mode */
+static int tvp7002_get_video_mode(struct v4l2_subdev *sd){
+	int reg01, reg02, reg03;
+	// Read the  value in  the first register  (reg01)
+	// and  recognize  first  all  unique identifiers,
+	// then those differentiable by the value of their
+	// second register and finally  those by the value
+	// of the third  register. This is not elegant and
+	// needs to be changed in a more efficient way.
+	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);
+	
+	switch(reg01){
+		case 0x32:
+			return TVP7002_VGA_640_480_60;
+		case 0x34:
+			if (reg02 == 0x00)
+				return TVP7002_VGA_640_480_73;
+			else if (reg02 == 0x80)
+				return TVP7002_VGA_640_480_75;
+			else if (reg03 == 0x60)
+				return TVP7002_VGA_640_480_85;
+		case 0x40:
+			return TVP7002_SVGA_800_600_56;
+		case 0x41:
+			if (reg02 == 0x00)
+				return TVP7002_SVGA_800_600_72;
+			else
+				return TVP7002_SVGA_800_600_85;
+		// In the documentation, based on the value of registers 0x01, 0x02 and 0x03 there is
+		// no current way of identifying the appropriate mode (probably an error on the device's
+		// documentation). First listed, first served.
+		case 0x42:  
+			if (reg02 == 0x00)
+				return TVP7002_SVGA_800_600_60;
+			else
+				return TVP7002_SVGA_800_600_75;
+		case 0x54:
+			return TVP7002_XGA_1024_768_60;
+		case 0x53:
+			return TVP7002_XGA_1024_768_70;
+		case 0x52:
+			return TVP7002_XGA_1024_768_75;
+		case 0x56:
+			return TVP7002_XGA_1024_768_85;
+		case 0x5a:
+			return TVP7002_WXGA1_1280_768_60_L;
+		case 0x68:
+			return TVP7002_WXGA1_1280_768_60_H;
+		case 0x6a:
+			return TVP7002_WXGA1_1280_768_75;
+		case 0x6b:
+			return TVP7002_WXGA1_1280_768_85;
+		case 0x69:
+			if (reg03 == 0xa0)
+				return TVP7002_SXGA_1280_1024_60;
+			else
+				return TVP7002_SXGA_1280_1024_75;
+		case 0x6c: 
+			return TVP7002_SXGA_1280_1024_85;
+		case 0x61:
+			return TVP7002_SXGAPLUS_1400_1050_60_L;
+		case 0x74:
+			return TVP7002_SXGAPLUS_1400_1050_60_H;
+		case 0x76:
+			return TVP7002_SXGAPLUS_1400_1050_75;
+		case 0x64:
+			return TVP7002_WXGA2_1440_900_60_L;
+		case 0x77:
+			return TVP7002_WXGA2_1440_900_60_H;
+		case 0x79:
+			return TVP7002_WXGA2_1440_900_75;
+		case 0x7a:
+			return TVP7002_WXGA2_1440_900_85;
+		case 0x87:
+			return TVP7002_UXGA_1600_1200_60;
+		case 0x35:
+			if (reg02 == 0xa0)
+				return TVP7002_VIDEOI_720_480_30;
+			else
+				return TVP7002_VIDEOI_720_576_25;
+		case 0x36:
+			if (reg02 == 0xa0)
+				return TVP7002_VIDEOP_720_480_60;
+			else
+				return TVP7002_VIDEOP_720_576_50;
+		case 0x67:
+			return TVP7002_VIDEOP_1280_720_60;
+		case 0x7b:
+			return TVP7002_VIDEOP_1280_720_50;
+		case 0x89:
+			if (reg03 == 0x98)
+				return TVP7002_VIDEOI_1920_1080_60;
+			else
+				return TVP7002_VIDEOP_1920_1080_60;
+		case 0xa5:
+			if (reg03 == 0x90)
+				return TVP7002_VIDEOI_1920_1080_50;
+			else
+				return TVP7002_VIDEOP_1920_1080_50;
+	}
+}
+
+/* Set standard video definition 
+ * 
+ * This will be changed with the following
+ * iteration of v4l2 HD definitions */
+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 = (int)(std & ~V4L2_STD_TVP7002_BASE_STD);
+
+	v4l2_dbg(1, debug, sd, "Set video std mode to %d.\n", vmd);
+	tvp7002_set_video_mode(sd, vmd);
+	
+	return 0;
+}
+
+static int tvp7002_querystd(struct v4l2_subdev *sd, v4l2_std_id *std){
+	(*std) = tvp7002_get_video_mode(sd);
+	
+	return 0;
+};
+
+/* Get a control */
+static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl){
+	v4l2_dbg(1, debug, sd, "tvp7002: g_ctrl called\n");
+	
+	switch (ctrl->id) {
+	case V4L2_CID_COARSE_GAIN_R:
+		ctrl->value = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+		return 0;
+	case V4L2_CID_COARSE_GAIN_G:
+		ctrl->value = tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+		return 0;
+	case V4L2_CID_COARSE_GAIN_B:
+		ctrl->value =  tvp7002_read(sd, TVP7002_B_AND_G_COARSE_GAIN);
+		return 0;
+	case V4L2_CID_FINE_GAIN_R:
+		ctrl->value = tvp7002_read(sd, TVP7002_R_FINE_GAIN);
+		return 0;
+	case V4L2_CID_FINE_GAIN_G:
+		ctrl->value = (tvp7002_read(sd, TVP7002_G_FINE_GAIN) >> 4) & 0x0f;
+		return 0;
+	case V4L2_CID_FINE_GAIN_B:
+		ctrl->value = tvp7002_read(sd, TVP7002_B_FINE_GAIN) & 0x0f;
+		return 0;
+	case V4L2_CID_SOG_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_1) >> 6) & 0x03;
+		return 0;
+	case V4L2_CID_R_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_1) >> 4) & 0x03;
+		return 0;
+	case V4L2_CID_G_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_1) >> 2) & 0x03;
+		return 0;
+	case V4L2_CID_B_IN:
+		ctrl->value = tvp7002_read(sd, TVP7002_IN_MUX_SEL_1) & 0x03;
+		return 0;
+	case V4L2_CID_SOG_LPF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) >> 6) & 0x03;
+		return 0;
+	case V4L2_CID_CLAMP_LPF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) >> 4) & 0x03;
+		return 0;
+	case V4L2_CID_CLK_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) >> 3) & 0x01;
+		return 0;
+	case V4L2_CID_VSYNC_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_PIXEL_CLK_IN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_HSYNC_IN:
+		ctrl->value = tvp7002_read(sd, TVP7002_IN_MUX_SEL_2) & 0x01;
+		return 0;
+	case V4L2_CID_SOG_THRS:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS) >> 3) & 0x1f;
+		return 0;
+	case V4L2_CID_B_CLAMP:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_G_CLAMP:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_R_CLAMP:
+		ctrl->value = tvp7002_read(sd, TVP7002_SYNC_ON_G_THRS) & 0x01;
+		return 0;
+	case V4L2_CID_CLAMP_OFF_EN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL) >> 7) & 0x01;
+		return 0;
+	case V4L2_CID_FCTCA:
+		ctrl->value = ((tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL >> 3) & 0x03) == 0x03) ? 1 : 0; 
+		return 0;
+	case V4L2_CID_F_CLAMP_GB:
+		ctrl->value = (tvp7002_read(sd, TVP7002_FINE_CLAMP_CTL) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_F_CLAMP_R:
+		return tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, ctrl->value & 0x01);
+	case V4L2_CID_CLAMP_START:
+		ctrl->value = tvp7002_read(sd, TVP7002_CLAMP_START) & 0xff;
+		return 0;
+	case V4L2_CID_CLAMP_W:
+		ctrl->value = tvp7002_read(sd, TVP7002_CLAMP_W) & 0xff;
+		return 0;
+	case V4L2_CID_B_COARSE_OFF:
+		ctrl->value = tvp7002_read(sd, TVP7002_B_COARSE_OFF) & 0x3f;
+		return 0;
+	case V4L2_CID_G_COARSE_OFF:
+		ctrl->value = tvp7002_read(sd, TVP7002_G_COARSE_OFF) & 0x3f;
+		return 0;
+	case V4L2_CID_R_COARSE_OFF:
+		ctrl->value = tvp7002_read(sd, TVP7002_R_COARSE_OFF) & 0x3f;
+		return 0;
+	case V4L2_CID_B_FINE_OFF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_B_FINE_OFF_MSBS) << 2) |
+					  (tvp7002_read(sd, TVP7002_FINE_OFF_LSBS) & 0x03);	
+		return 0;		
+	case V4L2_CID_G_FINE_OFF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS) << 2) |
+					  ((tvp7002_read(sd, TVP7002_FINE_OFF_LSBS) >> 2) & 0x03);	
+		return 0;
+	case V4L2_CID_R_FINE_OFF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_G_FINE_OFF_MSBS) << 2) |
+					  ((tvp7002_read(sd, TVP7002_FINE_OFF_LSBS) >> 4) & 0x03);	
+		return 0;
+	case V4L2_CID_ALC_EN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_ENABLE) >> 7) & 0x01;
+		return 0;
+	case V4L2_CID_ALC_PLACEMENT:
+		ctrl->value = tvp7002_read(sd, TVP7002_ALC_PLACEMENT) & 0xff;
+		return 0;
+	case V4L2_CID_ALC_FILTER_VERT_CF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_ENABLE) >> 3) & 0x0f;
+		return 0;
+	case V4L2_CID_ALC_FILTER_HORZ_CF:
+		ctrl->value = tvp7002_read(sd, TVP7002_AUTO_LVL_CTL_FILTER) & 0x07;
+		return 0;
+	case V4L2_CID_CLAMP_ALC_PULSE_RF:
+		ctrl->value = (tvp7002_read(sd, TVP7002_OUT_FORMATTER) >> 3) & 0x01;
+		return 0;
+	case V4L2_CID_OUT_CODE_RANGE:
+		ctrl->value = (tvp7002_read(sd, TVP7002_OUT_FORMATTER) >> 5) & 0x03;
+		return 0;
+	case V4L2_CID_OUT_CBCR_ORDER:
+		ctrl->value = (tvp7002_read(sd, TVP7002_OUT_FORMATTER) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_OUT_422_444:
+		ctrl->value = (tvp7002_read(sd, TVP7002_OUT_FORMATTER) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_OUT_EMB_SYNC_EN:
+		ctrl->value = tvp7002_read(sd, TVP7002_OUT_FORMATTER) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_HSPO:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 7) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_HSIP:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 6) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_HSOP:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 5) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_AHSO:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 4) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_AHSS:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 3) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_VSOP:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_AVSO:
+		ctrl->value = (tvp7002_read(sd, TVP7002_SYNC_CTL_1) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_SYNC_AVSS:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, ctrl->value & 0x01);
+	case V4L2_CID_SEEK_MODE_OVRD:
+		ctrl->value = (tvp7002_read(sd, TVP7002_HPLL_AND_CLAMP_CTL) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_FCPD:
+		ctrl->value = (tvp7002_read(sd, TVP7002_HPLL_AND_CLAMP_CTL) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_SOG_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 6) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_SLICER_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 5) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_REF_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 4) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_CURRENT_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 3) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_ADC_B_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 2) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_ADC_G_PWDN:
+		ctrl->value = (tvp7002_read(sd, TVP7002_PWR_CTL) >> 1) & 0x01;
+		return 0;
+	case V4L2_CID_PWR_ADC_R_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, ctrl->value & 0x01);
+	}
+	
+	return -EINVAL;
+}
+
+/* Set a control */
+static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl){
+	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_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", ctrl->id, ctrl->value);
+		break;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_COARSE_GAIN_R:
+		return tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, ctrl->value & 0xff);
+	case V4L2_CID_COARSE_GAIN_G:
+		return tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, (ctrl->value << 4) & 0xf0);
+	case V4L2_CID_COARSE_GAIN_B:
+		return tvp7002_write(sd, TVP7002_B_AND_G_COARSE_GAIN, ctrl->value& 0x0f);
+	case V4L2_CID_FINE_GAIN_R:
+		return tvp7002_write(sd, TVP7002_R_FINE_GAIN, ctrl->value & 0xff);
+	case V4L2_CID_FINE_GAIN_G:
+		return tvp7002_write(sd, TVP7002_G_FINE_GAIN, (ctrl->value << 4) & 0xf0);
+	case V4L2_CID_FINE_GAIN_B:
+		return tvp7002_write(sd, TVP7002_B_FINE_GAIN, ctrl->value& 0x0f);
+	case V4L2_CID_SOG_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, (ctrl->value << 6)& 0xc0);
+	case V4L2_CID_R_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, (ctrl->value << 4)& 0x30);
+	case V4L2_CID_G_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, (ctrl->value << 2)& 0x0c);
+	case V4L2_CID_B_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_1, ctrl->value & 0x03);
+	case V4L2_CID_SOG_LPF:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, (ctrl->value << 6) & 0xc0);
+	case V4L2_CID_CLAMP_LPF:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, (ctrl->value << 4) & 0x30);
+	case V4L2_CID_CLK_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, (ctrl->value << 3) & 0x08);
+	case V4L2_CID_VSYNC_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_PIXEL_CLK_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_HSYNC_IN:
+		return tvp7002_write(sd, TVP7002_IN_MUX_SEL_2, ctrl->value & 0x01);
+	case V4L2_CID_SOG_THRS:
+		return tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, (ctrl->value << 3) & 0xf8);
+	case V4L2_CID_B_CLAMP:
+		return tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_G_CLAMP:
+		return tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_R_CLAMP:
+		return tvp7002_write(sd, TVP7002_SYNC_ON_G_THRS, ctrl->value & 0x01);
+	case V4L2_CID_CLAMP_OFF_EN:
+		return tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, (ctrl->value << 7) & 0x80);
+	case V4L2_CID_FCTCA:
+		return tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, ((ctrl->value == 0 ? 0x00 : 0x03) << 3) & 0x0c);
+	case V4L2_CID_F_CLAMP_GB:
+		return tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_F_CLAMP_R:
+		return tvp7002_write(sd, TVP7002_FINE_CLAMP_CTL, ctrl->value & 0x01);
+	case V4L2_CID_CLAMP_START:
+		return tvp7002_write(sd, TVP7002_CLAMP_START, ctrl->value & 0xff);
+	case V4L2_CID_CLAMP_W:
+		return tvp7002_write(sd, TVP7002_CLAMP_W, ctrl->value & 0xff);
+	case V4L2_CID_B_COARSE_OFF:
+		return tvp7002_write(sd, TVP7002_B_COARSE_OFF, ctrl->value & 0x3f);
+	case V4L2_CID_G_COARSE_OFF:
+		return tvp7002_write(sd, TVP7002_G_COARSE_OFF, ctrl->value & 0x3f);
+	case V4L2_CID_R_COARSE_OFF:
+		return tvp7002_write(sd, TVP7002_R_COARSE_OFF, ctrl->value & 0x3f);
+	case V4L2_CID_B_FINE_OFF:
+		return 	tvp7002_write(sd, TVP7002_B_FINE_OFF_MSBS, (ctrl->value & 0xff) >> 2) + 
+				tvp7002_write(sd, TVP7002_FINE_OFF_LSBS, ctrl->value & 0x03);
+	case V4L2_CID_G_FINE_OFF:
+		return 	tvp7002_write(sd, TVP7002_G_FINE_OFF_MSBS, (ctrl->value & 0xff) >> 2) + 
+				tvp7002_write(sd, TVP7002_FINE_OFF_LSBS, (ctrl->value & 0x03) << 2);
+	case V4L2_CID_R_FINE_OFF:
+		return 	tvp7002_write(sd, TVP7002_R_FINE_OFF_MSBS, (ctrl->value & 0xff) >> 2) + 
+				tvp7002_write(sd, TVP7002_FINE_OFF_LSBS, (ctrl->value & 0x03) << 4);
+	case V4L2_CID_ALC_EN:
+		return tvp7002_write(sd, TVP7002_AUTO_LVL_CTL_ENABLE, (ctrl->value << 7) & 0x80);
+	case V4L2_CID_ALC_PLACEMENT:
+		return tvp7002_write(sd, TVP7002_ALC_PLACEMENT, ctrl->value & 0xff);
+	case V4L2_CID_ALC_FILTER_VERT_CF:
+		return tvp7002_write(sd, TVP7002_AUTO_LVL_CTL_FILTER, (ctrl->value << 3) & 0x78);
+	case V4L2_CID_ALC_FILTER_HORZ_CF:
+		return tvp7002_write(sd, TVP7002_AUTO_LVL_CTL_FILTER, ctrl->value & 0x07);
+	case V4L2_CID_CLAMP_ALC_PULSE_RF:
+		return tvp7002_write(sd, TVP7002_OUT_FORMATTER, (ctrl->value << 3) & 0x08);
+	case V4L2_CID_OUT_CODE_RANGE:
+		return tvp7002_write(sd, TVP7002_OUT_FORMATTER, (ctrl->value << 5) & 0x60);
+	case V4L2_CID_OUT_CBCR_ORDER:
+		return tvp7002_write(sd, TVP7002_OUT_FORMATTER, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_OUT_422_444:
+		return tvp7002_write(sd, TVP7002_OUT_FORMATTER, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_OUT_EMB_SYNC_EN:
+		return tvp7002_write(sd, TVP7002_OUT_FORMATTER, ctrl->value & 0x01);
+	case V4L2_CID_SYNC_HSPO:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 7) & 0x80);
+	case V4L2_CID_SYNC_HSIP:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 6) & 0x40);
+	case V4L2_CID_SYNC_HSOP:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 5) & 0x20);
+	case V4L2_CID_SYNC_AHSO:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 4) & 0x08);
+	case V4L2_CID_SYNC_AHSS:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 3) & 0x06);
+	case V4L2_CID_SYNC_VSOP:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_SYNC_AVSO:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_SYNC_AVSS:
+		return tvp7002_write(sd, TVP7002_SYNC_CTL_1, ctrl->value & 0x01);
+	case V4L2_CID_SEEK_MODE_OVRD:
+		return tvp7002_write(sd, TVP7002_HPLL_AND_CLAMP_CTL, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_PWR_FCPD:
+		return tvp7002_write(sd, TVP7002_HPLL_AND_CLAMP_CTL, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_PWR_SOG_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 6) & 0x40);
+	case V4L2_CID_PWR_SLICER_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 5) & 0x20);
+	case V4L2_CID_PWR_REF_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 4) & 0x08);
+	case V4L2_CID_PWR_CURRENT_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 3) & 0x06);
+	case V4L2_CID_PWR_ADC_B_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 2) & 0x04);
+	case V4L2_CID_PWR_ADC_G_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, (ctrl->value << 1) & 0x02);
+	case V4L2_CID_PWR_ADC_R_PWDN:
+		return tvp7002_write(sd, TVP7002_PWR_CTL, ctrl->value & 0x01);
+	}
+	
+	return -EINVAL;
+}
+
+/* IOCTL-handled request: get the value of a register */
+static int tvp7002_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg){
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	reg->val = tvp7002_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+/* IOCTL-handled request: set the value of a register */
+static int tvp7002_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg){
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+
+/* Query for a control */
+static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc){
+	int i;
+
+	v4l2_dbg(1, debug, 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));
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+/* Reset tvp7002 chip */
+static int tvp7002_reset(struct v4l2_subdev *sd, u32 val){
+	u8 rev;
+
+	rev = tvp7002_read(sd, TVP7002_CHIP_REV);
+
+	if (rev == 0x02)
+		v4l2_info(sd, "tvp7002 rev. %02x detected.\n", rev);
+	
+	else {
+			v4l2_info(sd, "*** Unknown revision of tvp7002 chip detected.\n");
+			v4l2_info(sd, "*** Revision number is %02x\n", rev);
+	}
+
+	/* Initializes TVP7002 to its default values */
+	return tvp7002_write_inittab(sd, tvp7002_init_default);
+};
+
+/* Probe device */
+static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id){
+	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))
+		return -EIO;
+
+	core = kzalloc(sizeof(struct tvp7002), GFP_KERNEL);
+	if (!core) {
+		return -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);
+
+	core->video_mode = TVP7002_VGA_640_480_60;
+
+	if (debug > 1)
+		tvp7002_log_status(sd);
+		
+	return 0;
+}
+
+/* Remove device */
+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;
+}
+
diff --git a/drivers/media/video/tvp7002_reg.h b/drivers/media/video/tvp7002_reg.h
new file mode 100644
index 0000000..8db4104
--- /dev/null
+++ b/drivers/media/video/tvp7002_reg.h
@@ -0,0 +1,159 @@
+/*
+ * TVP7002 Triple 8-/10-BIT 165-/110-MSPS Video and Graphics Digitizer
+ * with Horizontal PLL registers
+ *
+ * Copyright (C) 2009 Santiago Nunez-Corrales (santiago.nunez@ridgerun.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+/* Naming conventions
+ * ------------------
+ *
+ * FDBK:  Feedback
+ * DIV:   Divider
+ * CTL:   Control
+ * SEL:   Select
+ * IN:    Input
+ * OUT:   Output
+ * R:     Red
+ * G:     Green
+ * B:     Blue
+ * OFF:   Offset
+ * THRS:  Threshold
+ * DGTL:  Digital
+ * LVL:   Level
+ * PWR:   Power
+ * MVIS:  Macrovision
+ * W:     Width
+ * H:     Height
+ * ALGN:  Alignment
+ * CLK:   Clocks
+ * TOL:   Tolerance
+ * BWTH:  Bandwidth
+ * COEF:  Coefficient
+ * STAT:  Status
+ * AUTO:  Automatic
+ * FLD:   Field
+ * L:	  Line
+ */
+
+
+#define TVP7002_CHIP_REV		0x00	// Chip revision number 
+#define TVP7002_HPLL_FDBK_DIV_MSBS	0x01  	// Controls the 12-bit horizontal PLL feedback divider value that determines 
+					   	// the number of pixels per line
+#define TVP7002_HPLL_FDBK_DIV_LSBS	0x02	// Controls the 12-bit horizontal PLL feedback divider value that determines 
+						// the number of pixels per line
+#define TVP7002_HPLL_CRTL		0x03	// Selects VCO frequency range
+#define TVP7002_HPLL_PHASE_SEL		0x04	// ADC sampling clock phase select
+#define TVP7002_CLAMP_START		0x05	// Positions the clamp signal an integer number of clock periods after the 
+						// HSYNC signal
+#define TVP7002_CLAMP_W			0x06	// Sets the width in pixels for the fine clamp
+#define TVP7002_HSYNC_OUT_W		0x07	// Sets the width in pixels for HSYNC output
+#define TVP7002_B_FINE_GAIN		0x08	// 8-bit fine digital gain (contrast) for Blue channel (applied after 
+						// the ADC)
+#define TVP7002_G_FINE_GAIN		0x09	// 8-bit fine digital gain (contrast) for Green channel (applied after 
+                                                // the ADC)
+#define TVP7002_R_FINE_GAIN            0x0a    // 8-bit fine digital gain (contrast) for Red channel (applied after 
+                                                // the ADC)
+#define TVP7002_B_FINE_OFF_MSBS		0x0b	// Eight MSBs of 10-bit fine digital offset (brightness) for Blue channel 
+						// (applied after ADC)
+#define TVP7002_G_FINE_OFF_MSBS         0x0c    // Eight MSBs of 10-bit fine digital offset (brightness) for Green channel 
+                                                // (applied after ADC)
+#define TVP7002_R_FINE_OFF_MSBS         0x0d    // Eight MSBs of 10-bit fine digital offset (brightness) for Red channel 
+                                                // (applied after ADC)
+#define TVP7002_SYNC_CTL_1		0x0e	// Sync control register 1
+#define TVP7002_HPLL_AND_CLAMP_CTL	0x0f	// H-PLL and Clamp functionality control register
+#define TVP7002_SYNC_ON_G_THRS		0x10	// Sets the voltage level of the SOG slicer comparator
+#define TVP7002_SYNC_SEPARATOR_THRS	0x11	// Sets how many internal clock reference periods the sync separator counts 
+						// to before toggling high or low
+#define TVP7002_HPLL_PRE_COAST		0x12	// Sets the number of HSYNC periods that coast becomes active prior to 
+						// VSYNC leading edge
+#define TVP7002_HPLL_POST_COAST		0x13	// Sets the number of HSYNC periods that coast stays active following VSYNC 
+						// trailing edge
+#define TVP7002_SYNC_DETECT_STAT	0x14	// Sync Detect Status
+#define TVP7002_OUT_FORMATTER		0x15	// Sets output decoding parameters
+#define TVP7002_MISC_CTL_1		0x16	// Miscelaneous functions control 1
+#define TVP7002_MISC_CTL_2              0x17    // Miscelaneous functions control 2
+#define TVP7002_MISC_CTL_3              0x18    // Miscelaneous functions control 3
+#define TVP7002_IN_MUX_SEL_1		0x19	// Input Mux Select 1
+#define TVP7002_IN_MUX_SEL_2            0x1a    // Input Mux Select 2
+#define TVP7002_B_AND_G_COARSE_GAIN	0x1b	// Coarse analog gain for Blue and Green
+#define TVP7002_R_COARSE_GAIN		0x1c	// Coarse analog gain for Red
+#define TVP7002_FINE_OFF_LSBS		0x1d	// Fine offset for RGB
+#define TVP7002_B_COARSE_OFF		0x1e	// 6-bit coarse analog offset for Blue channel (applied before ADC)
+#define TVP7002_G_COARSE_OFF            0x1f    // 6-bit coarse analog offset for Green channel (applied before ADC)
+#define TVP7002_R_COARSE_OFF            0x20    // 6-bit coarse analog offset for Red channel (applied before ADC)
+#define TVP7002_HSOUT_OUT_START		0x21	// Adjusts the leading edge of the HSYNC output relative to the leading edge 
+						// of the HSYNC input in pixel or clock cycles
+#define TVP7002_MISC_CTL_4		0x22	// Miscelaneous functions control 4
+#define TVP7002_B_DGTL_ALC_OUT_LSBS	0x23	// Eight LSBs of 10-bit filtered digital ALC output for Blue channel
+#define TVP7002_G_DGTL_ALC_OUT_LSBS     0x24    // Eight LSBs of 10-bit filtered digital ALC output for Green channel
+#define TVP7002_R_DGTL_ALC_OUT_LSBS     0x25    // Eight LSBs of 10-bit filtered digital ALC output for Red channel
+#define TVP7002_AUTO_LVL_CTL_ENABLE	0x26	// Active-high automatic level control (ALC) enable
+#define TVP7002_DGTL_ALC_OUT_MSBS	0x27	// Two LSBs of 10-bit filtered digital ALC output for RGB channels
+#define TVP7002_AUTO_LVL_CTL_FILTER	0x28	// Automatic Level Control Filter
+
+/* Reserved 0x29*/
+
+#define TVP7002_FINE_CLAMP_CTL		0x2a	// Fine clamp control
+#define TVP7002_PWR_CTL			0x2b	// Power control
+#define TVP7002_ADC_SETUP		0x2c	// ADC setup
+#define TVP7002_COARSE_CLAMP_CTL	0x2d	// Coarse clamp control
+#define TVP7002_SOG_CLAMP		0x2e	// SOG Clamp
+#define TVP7002_RGB_COARSE_CLAMP_CTL	0x2f	// RGB channel coarse clamp leakage current switch
+#define TVP7002_SOG_COARSE_CLAMP_CTL	0x30	// SOG coarse clamp leakage current switch
+#define TVP7002_ALC_PLACEMENT		0x31	// Positions the ALC signal an integer number of clock periods after either 
+						// the leading edge or the trailing edge (default) of the HSYNC signal
+/* Reserved 0x32 */
+
+/* Reserved 0x33 */
+
+#define TVP7002_MVIS_STRIPPER_W		0x34	// Macrovision Stripper Width
+#define TVP7002_VSYNC_ALGN		0x35	// Specifies the number of pixels that the leading edge of the VSYNC output 
+						// should be delayed or advanced relative to the leading edge of the HSYNC 
+						// output
+#define TVP7002_SYNC_BYPASS		0x36	// Sync bypass
+#define TVP7002_L_FRAME_STAT_LSBS	0x37	// Lines per frame status LSBs
+#define TVP7002_L_FRAME_STAT_MSBS	0x38	// Lines per frame statis MSBs
+#define TVP7002_CLK_L_STAT_LSBS		0x39	// Clocks per line status LSBs
+#define TVP7002_CLK_L_STAT_MSBS      	0x3a    // Clocks per line status MSBs
+#define TVP7002_HSYNC_W			0x3b	// Number of clock cycles between the leading and trailing edges of the 
+						// HSYNC input
+#define TVP7002_VSYNC_W                 0x3c    // Number of clock cycles between the leading and trailing edges of the 
+                                                // VSYNC input
+#define TVP7002_L_LENGTH_TOL 		0x3d	// Controls sensitivity to HSYNC input stability when using either the 
+						// internal or external clock reference
+
+/* Reserved 0x3e */
+
+#define TVP7002_VIDEO_BWTH_CTL		0x3f	// Selectable low-pass filter settings for controlling the analog 
+						// Video Bandwidth Control
+#define TVP7002_AVID_START_PIXEL_LSBS	0x40	// AVID Start Pixel LSBs
+#define TVP7002_AVID_START_PIXEL_MSBS   0x41    // AVID Start Pixel MSBs
+#define TVP7002_AVID_STOP_PIXEL_LSBS  	0x42    // AVID Stop Pixel LSBs
+#define TVP7002_AVID_STOP_PIXEL_MSBS    0x43    // AVID Stop Pixel MSBs
+#define TVP7002_VBLK_F_0_START_L_OFF	0x44	// VBLK start line offset for field 0 relative to the leading edge of VSYNC
+#define TVP7002_VBLK_F_1_START_L_OFF    0x45    // VBLK start line offset for field 1 relative to the leading edge of VSYNC
+#define TVP7002_VBLK_F_0_DURATION	0x46	// VBLK duration in lines for field 0
+#define TVP7002_VBLK_F_1_DURATION       0x47    // VBLK duration in lines for field 1
+#define TVP7002_FBIT_F_0_START_L_OFF	0x48	// F-bit Field 0 start line offset relative to the leading edge of VSYNC
+#define TVP7002_FBIT_F_1_START_L_OFF    0x49    // F-bit Field 1 start line offset relative to the leading edge of VSYNC
+#define TVP7002_YUV_Y_G_COEF_LSBS	0x4a	// 16-bit Gâ€™ coefficient MSB for Y LSBS
+#define TVP7002_YUV_Y_G_COEF_MSBS       0x4b    // 16-bit Gâ€™ coefficient MSB for Y MSBS
+#define TVP7002_YUV_Y_B_COEF_LSBS       0x4c    // 16-bit Bâ€™ coefficient MSB for Y LSBS
+#define TVP7002_YUV_Y_B_COEF_MSBS       0x4d    // 16-bit Bâ€™ coefficient MSB for Y MSBS
+#define TVP7002_YUV_Y_R_COEF_LSBS       0x4e    // 16-bit Râ€™ coefficient MSB for Y LSBS
+#define TVP7002_YUV_Y_R_COEF_MSBS       0x4f    // 16-bit Râ€™ coefficient MSB for Y MSBS
+#define TVP7002_YUV_U_G_COEF_LSBS       0x50    // 16-bit Gâ€™ coefficient MSB for U LSBS
+#define TVP7002_YUV_U_G_COEF_MSBS       0x51    // 16-bit Gâ€™ coefficient MSB for U MSBS
+#define TVP7002_YUV_U_B_COEF_LSBS       0x52    // 16-bit Bâ€™ coefficient MSB for U LSBS
+#define TVP7002_YUV_U_B_COEF_MSBS       0x53    // 16-bit Bâ€™ coefficient MSB for U MSBS
+#define TVP7002_YUV_U_R_COEF_LSBS       0x54    // 16-bit Râ€™ coefficient MSB for U LSBS
+#define TVP7002_YUV_U_R_COEF_MSBS       0x55    // 16-bit Râ€™ coefficient MSB for U MSBS
+#define TVP7002_YUV_V_G_COEF_LSBS       0x56    // 16-bit Gâ€™ coefficient MSB for V LSBS
+#define TVP7002_YUV_V_G_COEF_MSBS       0x57    // 16-bit Gâ€™ coefficient MSB for V MSBS
+#define TVP7002_YUV_V_B_COEF_LSBS       0x58    // 16-bit Bâ€™ coefficient MSB for V LSBS
+#define TVP7002_YUV_V_B_COEF_MSBS       0x59    // 16-bit Bâ€™ coefficient MSB for V MSBS
+#define TVP7002_YUV_V_R_COEF_LSBS       0x5a    // 16-bit Râ€™ coefficient MSB for V LSBS
+#define TVP7002_YUV_V_R_COEF_MSBS       0x5b    // 16-bit Râ€™ coefficient MSB for V MSBS
+
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 74f1687..935176b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -703,6 +703,14 @@ typedef __u64 v4l2_std_id;
 				 V4L2_STD_PAL_N		|\
 				 V4L2_STD_PAL_Nc	|\
 				 V4L2_STD_SECAM)
+#define V4L2_STD_725_50		(V4L2_STD_PAL		|\
+				 V4L2_STD_PAL_M		|\
+				 V4L2_STD_PAL_Nc	|\
+				 V4L2_STD_SECAM)
+#define V4L2_STD_825_60		(V4L2_STD_PAL_M		|\
+				 V4L2_STD_PAL_N		|\
+				 V4L2_STD_PAL_Nc	|\
+				 V4L2_STD_SECAM)
 #define V4L2_STD_ATSC           (V4L2_STD_ATSC_8_VSB    |\
 				 V4L2_STD_ATSC_16_VSB)
 
diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h
index e8272d1..bb7b2a5 100644
--- a/include/media/davinci/vpfe_capture.h
+++ b/include/media/davinci/vpfe_capture.h
@@ -65,7 +65,8 @@ struct vpfe_route {
 
 enum vpfe_subdev_id {
 	VPFE_SUBDEV_TVP5146 = 1,
-	VPFE_SUBDEV_MT9T031 = 2
+	VPFE_SUBDEV_MT9T031 = 2,
+	VPFE_SUBDEV_TVP7002 = 3
 };
 
 struct vpfe_subdev_info {
diff --git a/include/media/tvp7002.h b/include/media/tvp7002.h
new file mode 100644
index 0000000..0021906
--- /dev/null
+++ b/include/media/tvp7002.h
@@ -0,0 +1,250 @@
+/*
+    tvp7002.h - Definitions for TVP7002
+
+    Copyright (C) 2009 Santiago Nunez-Corrales (santiago.nunez@ridgerun.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.
+*/
+
+#ifndef _TVP7002_H_
+#define _TVP7002_H_
+
+/* Includes */
+#include <linux/videodev2.h>
+
+/* Definitions */
+
+// Boolean values
+#define TRUE	1
+#define FALSE	0
+
+// VCO Range
+#define TVP7002_VCO_RANGE_ULOW 	0x00
+#define TVP7002_VCO_RANGE_LOW	0x40
+#define TVP7002_VCO_RANGE_MED	0x80
+#define TVP7002_VCO_RANGE_HIGH	0xC0
+
+// Input selection
+enum tvp7002_input {
+	TVP7002_SOGIN_1 = 0x00,
+	TVP7002_SOGIN_2 = 0x01,
+	TVP7002_SOGIN_3 = 0x02,
+	TVP7002_RIN_1 = 0x04,
+	TVP7002_RIN_2 = 0x05,
+	TVP7002_RIN_3 = 0x06,
+	TVP7002_GIN_1 = 0x08,
+	TVP7002_GIN_2 = 0x09,
+	TVP7002_GIN_3 = 0x0a,
+	TVP7002_GIN_4 = 0x0b,
+	TVP7002_BIN_1 = 0x0c,
+	TVP7002_BIN_2 = 0x0d,
+	TVP7002_BIN_3 = 0x0e,
+	TVP7002_INVALID
+};
+
+// Sync-On-Green low pass filter select
+#define TVP7002_SOG_LPF_025	0x00		// 2.5 MHz
+#define TVP7002_SOG_LPF_100	0x01		// 10 MHz
+#define TVP7002_SOG_LPF_330	0x02		// 33 MHz
+#define TVP7002_SOG_LPF_BYP	0x03		// Bypass
+
+// Coarse clamp low pass filter select
+#define TVP7002_CLP_LPF_048	0x00		// 4.8 MHz
+#define TVP7002_CLP_LPF_005	0x01		// 0.5 MHz
+#define TVP7002_CLP_LPF_017	0x02		// 1.7 MHz
+
+// Clock reference select for Sync Processing Block
+#define TVP7002_CLK_REF_IN	0x00
+#define TVP7002_CLK_REF_OUT	0x01
+
+// VSYNC input select
+#define TVP7002_VSYNC_IN_A	0x00
+#define TVP7002_VSYNC_IN_B	0x01
+
+// Pixel clock select
+#define TVP7002_PIXEL_CLK_EXT	0x00
+#define TVP7002_PIXEL_CLC_HPLL	0x01
+
+// HSYNC input select
+#define TVP7002_HSYNC_IN_A	0x00
+#define TVP7002_HSYNX_IN_B	0x01
+
+// V4L2 CIDs for controls
+//
+// According to include/media/videodev2.h, control identifiers are tags
+// that label proper functions in the driver (i.e. existing functions that
+// are unique). V4L2_CID_PRIVATE_BASE defines a set of idetifiers that,
+// starting at address 0x08000000 allow definition of driver-specific
+// controls. 
+#define V4L2_CID_VIDEO_MODE			(V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_COARSE_GAIN_R		(V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_COARSE_GAIN_G		(V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_COARSE_GAIN_B		(V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_FINE_GAIN_R		(V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_FINE_GAIN_G		(V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_FINE_GAIN_B		(V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_SOG_IN				(V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_R_IN				(V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_G_IN				(V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_B_IN				(V4L2_CID_PRIVATE_BASE + 11)
+#define V4L2_CID_SOG_LPF			(V4L2_CID_PRIVATE_BASE + 12)
+#define V4L2_CID_CLAMP_LPF			(V4L2_CID_PRIVATE_BASE + 13)
+#define V4L2_CID_CLK_IN				(V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_VSYNC_IN			(V4L2_CID_PRIVATE_BASE + 15)
+#define V4L2_CID_PIXEL_CLK_IN		(V4L2_CID_PRIVATE_BASE + 16)
+#define V4L2_CID_HSYNC_IN			(V4L2_CID_PRIVATE_BASE + 17)
+#define V4L2_CID_SOG_THRS			(V4L2_CID_PRIVATE_BASE + 18)
+#define V4L2_CID_B_CLAMP			(V4L2_CID_PRIVATE_BASE + 19)
+#define V4L2_CID_G_CLAMP			(V4L2_CID_PRIVATE_BASE + 20)
+#define V4L2_CID_R_CLAMP			(V4L2_CID_PRIVATE_BASE + 21)
+#define V4L2_CID_CLAMP_OFF_EN		(V4L2_CID_PRIVATE_BASE + 22)
+#define V4L2_CID_FCTCA				(V4L2_CID_PRIVATE_BASE + 23)
+#define V4L2_CID_F_CLAMP_GB			(V4L2_CID_PRIVATE_BASE + 24)
+#define V4L2_CID_F_CLAMP_R			(V4L2_CID_PRIVATE_BASE + 25)
+#define V4L2_CID_CLAMP_START		(V4L2_CID_PRIVATE_BASE + 26)
+#define V4L2_CID_CLAMP_W			(V4L2_CID_PRIVATE_BASE + 27)
+#define V4L2_CID_B_COARSE_OFF		(V4L2_CID_PRIVATE_BASE + 28)
+#define V4L2_CID_G_COARSE_OFF		(V4L2_CID_PRIVATE_BASE + 29)
+#define V4L2_CID_R_COARSE_OFF		(V4L2_CID_PRIVATE_BASE + 30)
+#define V4L2_CID_B_FINE_OFF			(V4L2_CID_PRIVATE_BASE + 31)
+#define V4L2_CID_G_FINE_OFF			(V4L2_CID_PRIVATE_BASE + 32)
+#define V4L2_CID_R_FINE_OFF			(V4L2_CID_PRIVATE_BASE + 33)
+#define V4L2_CID_ALC_EN				(V4L2_CID_PRIVATE_BASE + 34)
+#define V4L2_CID_ALC_PLACEMENT		(V4L2_CID_PRIVATE_BASE + 35)
+#define V4L2_CID_ALC_FILTER_VERT_CF	(V4L2_CID_PRIVATE_BASE + 36)
+#define V4L2_CID_ALC_FILTER_HORZ_CF	(V4L2_CID_PRIVATE_BASE + 37)
+#define V4L2_CID_CLAMP_ALC_PULSE_RF	(V4L2_CID_PRIVATE_BASE + 38)
+#define V4L2_CID_OUT_CODE_RANGE		(V4L2_CID_PRIVATE_BASE + 39)
+#define V4L2_CID_OUT_CBCR_ORDER		(V4L2_CID_PRIVATE_BASE + 40)
+#define V4L2_CID_OUT_422_444		(V4L2_CID_PRIVATE_BASE + 41)
+#define V4L2_CID_OUT_EMB_SYNC_EN	(V4L2_CID_PRIVATE_BASE + 42)
+#define V4L2_CID_SYNC_HSPO			(V4L2_CID_PRIVATE_BASE + 43)
+#define V4L2_CID_SYNC_HSIP			(V4L2_CID_PRIVATE_BASE + 44)
+#define V4L2_CID_SYNC_HSOP			(V4L2_CID_PRIVATE_BASE + 45)
+#define V4L2_CID_SYNC_AHSO			(V4L2_CID_PRIVATE_BASE + 46)
+#define V4L2_CID_SYNC_AHSS			(V4L2_CID_PRIVATE_BASE + 47)
+#define V4L2_CID_SYNC_VSOP			(V4L2_CID_PRIVATE_BASE + 48)
+#define V4L2_CID_SYNC_AVSO			(V4L2_CID_PRIVATE_BASE + 49)
+#define V4L2_CID_SYNC_AVSS			(V4L2_CID_PRIVATE_BASE + 50)
+#define V4L2_CID_SEEK_MODE_OVRD		(V4L2_CID_PRIVATE_BASE + 51)
+#define V4L2_CID_PWR_FCPD			(V4L2_CID_PRIVATE_BASE + 52)
+#define V4L2_CID_PWR_SOG_PWDN		(V4L2_CID_PRIVATE_BASE + 53)
+#define V4L2_CID_PWR_SLICER_PWDN	(V4L2_CID_PRIVATE_BASE + 54)
+#define V4L2_CID_PWR_REF_PWDN		(V4L2_CID_PRIVATE_BASE + 55)
+#define V4L2_CID_PWR_CURRENT_PWDN	(V4L2_CID_PRIVATE_BASE + 56)
+#define V4L2_CID_PWR_ADC_B_PWDN		(V4L2_CID_PRIVATE_BASE + 57)
+#define V4L2_CID_PWR_ADC_G_PWDN		(V4L2_CID_PRIVATE_BASE + 58)
+#define V4L2_CID_PWR_ADC_R_PWDN		(V4L2_CID_PRIVATE_BASE + 59)
+
+/* Resolution identifiers 
+ *
+ * Standard_Resolution_FrameRate[_PixelRate]
+ */
+#define V4L2_STD_TVP7002_BASE_STD		0x04000000
+#define	TVP7002_VGA_640_480_60			((v4l2_std_id)V4L2_STD_TVP7002_BASE_STD)
+#define TVP7002_VGA_640_480_73			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 1))
+#define	TVP7002_VGA_640_480_75			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 2))
+#define TVP7002_VGA_640_480_85			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 3))
+#define TVP7002_SVGA_800_600_56			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 4))
+#define TVP7002_SVGA_800_600_60			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 5))
+#define TVP7002_SVGA_800_600_72			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 6))
+#define TVP7002_SVGA_800_600_75			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 7))
+#define TVP7002_SVGA_800_600_85			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 8))
+#define TVP7002_XGA_1024_768_60			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 9))
+#define TVP7002_XGA_1024_768_70			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 10))
+#define TVP7002_XGA_1024_768_75			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 11))
+#define TVP7002_XGA_1024_768_85			((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 12))
+#define TVP7002_WXGA1_1280_768_60_L		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 13))
+#define TVP7002_WXGA1_1280_768_60_H		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 14))
+#define TVP7002_WXGA1_1280_768_75		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 15))
+#define TVP7002_WXGA1_1280_768_85		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 16))
+#define TVP7002_SXGA_1280_1024_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 17))
+#define TVP7002_SXGA_1280_1024_75		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 18))
+#define TVP7002_SXGA_1280_1024_85		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 19))
+#define TVP7002_SXGAPLUS_1400_1050_60_L	((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 20))
+#define TVP7002_SXGAPLUS_1400_1050_60_H	((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 21))
+#define TVP7002_SXGAPLUS_1400_1050_75	((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 22))
+#define TVP7002_WXGA2_1440_900_60_L		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 23))
+#define TVP7002_WXGA2_1440_900_60_H		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 24))
+#define TVP7002_WXGA2_1440_900_75		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 25))
+#define TVP7002_WXGA2_1440_900_85		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 26))
+#define TVP7002_UXGA_1600_1200_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 27))
+#define TVP7002_VIDEOI_720_480_30		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 28))
+#define TVP7002_VIDEOI_720_576_25		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 29))
+#define TVP7002_VIDEOP_720_480_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 30))
+#define TVP7002_VIDEOP_720_576_50		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 31))
+#define TVP7002_VIDEOP_1280_720_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 32))
+#define TVP7002_VIDEOP_1280_720_50		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 33))
+#define TVP7002_VIDEOI_1920_1080_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 34))
+#define TVP7002_VIDEOI_1920_1080_50		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 35))
+#define TVP7002_VIDEOP_1920_1080_60		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 36))
+#define TVP7002_VIDEOP_1920_1080_50		((v4l2_std_id)(V4L2_STD_TVP7002_BASE_STD + 37))
+
+/* Struct for handling resolutions and associate register values */
+
+struct tvp7002_resol {
+	int id;			// ID
+	int hres;		// Horizontal resolution
+	int vres;		// Vertical resolution
+	int frate;		// Frame rate
+	int lrate;		// Line rate
+	int prate;		// Pixel rate
+	unsigned char reg01;	// Value for register 0x01h
+	unsigned char reg02;    // Value for register 0x02h
+	unsigned char reg03;	// Value for register 0x03h
+	unsigned char reg04;    // Value for register 0x04h
+	int available;		// Is this resolution available for this platform?
+};
+
+/* Struct for handling register values */
+struct i2c_reg_value {
+	unsigned char reg;
+	unsigned char value;
+};
+
+/* */
+struct tvp7002_platform_data {
+	/* Interface control params */
+	bool clk_polarity;
+	bool hs_polarity;
+	bool vs_polarity;
+};
+
+/* Prototypes */
+static int tvp7002_read(struct v4l2_subdev *, unsigned char);
+static int tvp7002_write(struct v4l2_subdev *, unsigned char, unsigned char);
+static void dump_reg_range(struct v4l2_subdev *, char *, u8, const u8, int);
+static int tvp7002_log_status(struct v4l2_subdev *);
+static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *);
+static int tvp7002_write_inittab(struct v4l2_subdev *, const struct i2c_reg_value *);
+static int tvp7002_set_video_mode(struct v4l2_subdev *, int);
+static int tvp7002_get_video_mode(struct v4l2_subdev *);
+static int tvp7002_s_std(struct v4l2_subdev *sd, v4l2_std_id std);
+static int tvp7002_querystd(struct v4l2_subdev *, v4l2_std_id *);
+static int tvp7002_g_chip_ident(struct v4l2_subdev *, struct v4l2_dbg_chip_ident *);
+static int tvp7002_set_std_format(struct v4l2_subdev *, unsigned int);
+static int tvp7002_g_ctrl(struct v4l2_subdev *, struct v4l2_control *);
+static int tvp7002_s_ctrl(struct v4l2_subdev *, struct v4l2_control *);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int tvp7002_g_register(struct v4l2_subdev *, struct v4l2_dbg_register *);
+static int tvp7002_s_register(struct v4l2_subdev *, struct v4l2_dbg_register *);
+#endif
+static int tvp7002_queryctrl(struct v4l2_subdev *, struct v4l2_queryctrl *);
+static int tvp7002_reset(struct v4l2_subdev *, u32);
+static int tvp7002_probe(struct i2c_client *, const struct i2c_device_id *);
+
+static int tvp7002_remove(struct i2c_client *);
+
+#endif
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 94e908c..b8c86d9 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -129,6 +129,9 @@ enum {
 	V4L2_IDENT_SAA6752HS = 6752,
 	V4L2_IDENT_SAA6752HS_AC3 = 6753,
 
+	/* module tvp7002: just ident 7002 */
+	V4L2_IDENT_TVP7002 = 7002,
+
 	/* module adv7170: just ident 7170 */
 	V4L2_IDENT_ADV7170 = 7170,
 
