This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/TMS320DM368: DM368 + TVP5150 + IPNC_RDK_DM36x_Version4.1.0

Part Number: TMS320DM368
Other Parts Discussed in Thread: TVP5150

Tool/software: Linux

Hardware environment: DM368 + TVP5150

Software environment: IPNC_RDK_DM36x_Version4.1.0

Problem description:

             Do you have a DM368 IPNC_RDK_DM36x_Version4.1.0 patch on TVP5150?

  • Hi,

    Please can you check DVSDK software for DM36X EVM?.It is downloadable from TI website.  TVP514X driver in dvsdk PSP can be used to TVP5150 with very minimal changes. 

    Hope it helps :)

    Thanks 

  • I could find tvp5150 driver code.  Attached here for the reference. This might still need few changes before working.

    Give a try :)

    tvp5150.c
    /*
     * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver
     *
     * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org)
     * This code is placed under the terms of the GNU General Public License v2
     */
    
    #include <linux/i2c.h>
    #include <linux/slab.h>
    #include <linux/videodev2.h>
    #include <linux/delay.h>
    #include <media/v4l2-device.h>
    #include <media/tvp5150.h>
    #include <media/v4l2-chip-ident.h>
    #include <media/v4l2-ctrls.h>
    #include <media/v4l2-subdev.h>
    
    #include <asm/io.h>
    #include "tvp5150_reg.h"
    
    MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver");
    MODULE_AUTHOR("Mauro Carvalho Chehab");
    MODULE_LICENSE("GPL");
    
    
    static int debug;
    module_param(debug, int, 0);
    MODULE_PARM_DESC(debug, "Debug level (0-2)");
    
    /* enum tvp515x_std - enum for supported standards */
    enum tvp515x_std {
    	STD_PAL_BDGHIN = 0,
    	STD_NTSC_MJ,
    	STD_INVALID
    };
    
    /**
     * struct tvp515x_std_info - Structure to store standard informations
     * @width: Line width in pixels
     * @height:Number of active lines
     * @video_std: Value to write in REG_VIDEO_STD register
     * @standard: v4l2 standard structure information
     */
    struct tvp515x_std_info {
    	u8 video_std;
    	struct v4l2_standard standard;
    	struct v4l2_mbus_framefmt format;
    };
    
    /**
     * Supported standards -
     *
     * Currently supports two standards only, need to add support for rest of the
     * modes, like SECAM, etc...
     */
    static struct tvp515x_std_info tvp515x_std_list[] = {
    	/* Standard: STD_NTSC_MJ */
    	/* Standard: STD_PAL_BDGHIN */
    	[STD_PAL_BDGHIN] = {
    		.video_std = VIDEO_STD_PAL_BDGHIN_BIT,
    		.standard = {
    			.index = 1,
    			.id = V4L2_STD_PAL,
    			.name = "PAL",
    			.frameperiod = {1, 25},
    			.framelines = 625
    		},
    		.format = {
    			.width = PAL_NUM_ACTIVE_PIXELS,
    			.height = PAL_NUM_ACTIVE_LINES,
    			.code = V4L2_MBUS_FMT_UYVY8_2X8,
    			.field = V4L2_FIELD_INTERLACED,
    			.colorspace = V4L2_COLORSPACE_SMPTE170M,
    		},
    	},
    	[STD_NTSC_MJ] = {
    		.video_std = VIDEO_STD_NTSC_MJ_BIT,
    		.standard = {
    			.index = 0,
    			.id = V4L2_STD_NTSC,
    			.name = "NTSC",
    			.frameperiod = {1001, 30000},
    			.framelines = 525
    		},
    		.format = {
    			.width = NTSC_NUM_ACTIVE_PIXELS,
    			.height = NTSC_NUM_ACTIVE_LINES,
    			.code = V4L2_MBUS_FMT_UYVY8_2X8,
    			.field = V4L2_FIELD_INTERLACED,
    			.colorspace = V4L2_COLORSPACE_SMPTE170M,
    		},
    	},
    	/* Standard: need to add for additional standard */
    };
    
    struct tvp5150 {
    	struct v4l2_subdev sd;
    	struct v4l2_ctrl_handler hdl;
    	struct media_pad pad;
    	struct v4l2_mbus_framefmt *format;
    	enum tvp515x_std std_idx;
    	v4l2_std_id norm;
    	u32 input;
    	u32 output;
    	int enable;
    };
    
    static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd)
    {
    	return container_of(sd, struct tvp5150, sd);
    }
    
    static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
    {
    	return &container_of(ctrl->handler, struct tvp5150, hdl)->sd;
    }
    
    static int tvp5150_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); KVA 
    //		printk(KERN_CRIT "KVA i2c i/o error:i2c_master_send rc == %d (should be 1)\n", rc);
    
    	msleep(100);
    	buffer[0] = 0x00;
    	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); KVA
    //		printk(KERN_CRIT "KVA i2c i/o error:i2c_master_recv rc == %d (should be 1)\n", rc);
    
    	v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
    	printk("tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
    
    	return (buffer[0]);
    }
    
    
    static inline void tvp5150_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, "tvp5150: 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);
    }
    
    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("tvp5150: %s reg 0x%02x = ", s, init);
    		}
    		printk("%02x ", tvp5150_read(sd, init));
    
    		init++;
    		i++;
    	}
    	printk("\n");
    }
    
    static int tvp5150_log_status(struct v4l2_subdev *sd)
    {
    	printk("tvp5150: Video input source selection #1 = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_VD_IN_SRC_SEL_1));
    	printk("tvp5150: Analog channel controls = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_ANAL_CHL_CTL));
    	printk("tvp5150: Operation mode controls = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_OP_MODE_CTL));
    	printk("tvp5150: Miscellaneous controls = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_MISC_CTL));
    	printk("tvp5150: Autoswitch mask= 0x%02x\n",
    			tvp5150_read(sd, TVP5150_AUTOSW_MSK));
    	printk("tvp5150: Color killer threshold control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_COLOR_KIL_THSH_CTL));
    	printk("tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n",
    			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_1),
    			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_2),
    			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_3));
    	printk("tvp5150: Brightness control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_BRIGHT_CTL));
    	printk("tvp5150: Color saturation control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_SATURATION_CTL));
    	printk("tvp5150: Hue control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_HUE_CTL));
    	printk("tvp5150: Contrast control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_CONTRAST_CTL));
    	printk("tvp5150: Outputs and data rates select = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_DATA_RATE_SEL));
    	printk("tvp5150: Configuration shared pins = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_CONF_SHARED_PIN));
    	printk("tvp5150: Active video cropping start = 0x%02x%02x\n",
    			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_MSB),
    			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_LSB));
    	printk("tvp5150: Active video cropping stop  = 0x%02x%02x\n",
    			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_MSB),
    			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_LSB));
    	printk("tvp5150: Genlock/RTC = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_GENLOCK));
    	printk("tvp5150: Horizontal sync start = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_HORIZ_SYNC_START));
    	printk("tvp5150: Vertical blanking start = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_VERT_BLANKING_START));
    	printk("tvp5150: Vertical blanking stop = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_VERT_BLANKING_STOP));
    	printk("tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n",
    			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_1),
    			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_2));
    	printk("tvp5150: Interrupt reset register B = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_RESET_REG_B));
    	printk("tvp5150: Interrupt enable register B = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_B));
    	printk("tvp5150: Interrupt configuration register B = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INTT_CONFIG_REG_B));
    	printk("tvp5150: Video standard = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_VIDEO_STD));
    	printk("tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n",
    			tvp5150_read(sd, TVP5150_CB_GAIN_FACT),
    			tvp5150_read(sd, TVP5150_CR_GAIN_FACTOR));
    	printk("tvp5150: Macrovision on counter = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_MACROVISION_ON_CTR));
    	printk("tvp5150: Macrovision off counter = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_MACROVISION_OFF_CTR));
    	printk("tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n",
    			(tvp5150_read(sd, TVP5150_REV_SELECT) & 1) ? 3 : 4);
    	printk("tvp5150: Device ID = %02x%02x\n",
    			tvp5150_read(sd, TVP5150_MSB_DEV_ID),
    			tvp5150_read(sd, TVP5150_LSB_DEV_ID));
    	printk("tvp5150: ROM version = (hex) %02x.%02x\n",
    			tvp5150_read(sd, TVP5150_ROM_MAJOR_VER),
    			tvp5150_read(sd, TVP5150_ROM_MINOR_VER));
    	printk("tvp5150: Vertical line count = 0x%02x%02x\n",
    			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_MSB),
    			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_LSB));
    	printk("tvp5150: Interrupt status register B = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_STATUS_REG_B));
    	printk("tvp5150: Interrupt active register B = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_ACTIVE_REG_B));
    	printk("tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n",
    			tvp5150_read(sd, TVP5150_STATUS_REG_1),
    			tvp5150_read(sd, TVP5150_STATUS_REG_2),
    			tvp5150_read(sd, TVP5150_STATUS_REG_3),
    			tvp5150_read(sd, TVP5150_STATUS_REG_4),
    			tvp5150_read(sd, TVP5150_STATUS_REG_5));
    
    	dump_reg_range(sd, "Teletext filter 1",   TVP5150_TELETEXT_FIL1_INI,
    			TVP5150_TELETEXT_FIL1_END, 8);
    	dump_reg_range(sd, "Teletext filter 2",   TVP5150_TELETEXT_FIL2_INI,
    			TVP5150_TELETEXT_FIL2_END, 8);
    
    	printk("tvp5150: Teletext filter enable = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_TELETEXT_FIL_ENA));
    	printk("tvp5150: Interrupt status register A = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_STATUS_REG_A));
    	printk("tvp5150: Interrupt enable register A = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_A));
    	printk("tvp5150: Interrupt configuration = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_INT_CONF));
    	printk("tvp5150: VDP status register = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_VDP_STATUS_REG));
    	printk("tvp5150: FIFO word count = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT));
    	printk("tvp5150: FIFO interrupt threshold = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FIFO_INT_THRESHOLD));
    	printk("tvp5150: FIFO reset = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FIFO_RESET));
    	printk("tvp5150: Line number interrupt = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_LINE_NUMBER_INT));
    	printk("tvp5150: Pixel alignment register = 0x%02x%02x\n",
    			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_HIGH),
    			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_LOW));
    	printk("tvp5150: FIFO output control = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FIFO_OUT_CTRL));
    	printk("tvp5150: Full field enable = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FULL_FIELD_ENA));
    	printk("tvp5150: Full field mode register = 0x%02x\n",
    			tvp5150_read(sd, TVP5150_FULL_FIELD_MODE_REG));
    
    	dump_reg_range(sd, "CC   data",   TVP5150_CC_DATA_INI,
    			TVP5150_CC_DATA_END, 8);
    
    	dump_reg_range(sd, "WSS  data",   TVP5150_WSS_DATA_INI,
    			TVP5150_WSS_DATA_END, 8);
    
    	dump_reg_range(sd, "VPS  data",   TVP5150_VPS_DATA_INI,
    			TVP5150_VPS_DATA_END, 8);
    
    	dump_reg_range(sd, "VITC data",   TVP5150_VITC_DATA_INI,
    			TVP5150_VITC_DATA_END, 10);
    
    	dump_reg_range(sd, "Line mode",   TVP5150_LINE_MODE_INI,
    			TVP5150_LINE_MODE_END, 8);
    	return 0;
    }
    
    /****************************************************************************
    			Basic functions
     ****************************************************************************/
    
    static inline void tvp5150_selmux(struct v4l2_subdev *sd)
    {
    	int opmode = 0;
    	struct tvp5150 *decoder = to_tvp5150(sd);
    	int input = 0;
    	unsigned char val;
    
    	if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable)
    		input = 8;
    
    	switch (decoder->input) {
    	case TVP5150_COMPOSITE1:
    		input |= 2;
    		/* fall through */
    	case TVP5150_COMPOSITE0:
    		break;
    	case TVP5150_SVIDEO:
    	default:
    		input |= 1;
    		break;
    	}
    
    	v4l2_dbg(1, debug, sd, "Selecting video route: route input=%i, output=%i "
    			"=> tvp5150 input=%i, opmode=%i\n",
    			decoder->input, decoder->output,
    			input, opmode);
    
    	tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
    	tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
    
    	/* Svideo should enable YCrCb output and disable GPCL output
    	 * For Composite and TV, it should be the reverse
    	 */
    	val = tvp5150_read(sd, TVP5150_MISC_CTL);
    	if (decoder->input == TVP5150_SVIDEO)
    		val = (val & ~0x40) | 0x10;
    	else
    		val = (val & ~0x10) | 0x40;
    		val=val | 0x08; /*BEL changes */
    	tvp5150_write(sd, TVP5150_MISC_CTL, val);
    };
    
    struct i2c_reg_value {
    	unsigned char reg;
    	unsigned char value;
    };
    
    /* Default values as sugested at TVP5150AM1 datasheet */
    static const struct i2c_reg_value tvp5150_init_default[] = {
    	{ /* 0x00 */
    		TVP5150_VD_IN_SRC_SEL_1,0x00
    	},
    	{ /* 0x01 */
    		TVP5150_ANAL_CHL_CTL,0x15
    	},
    	{ /* 0x02 */
    		TVP5150_OP_MODE_CTL,0x00
    	},
    	{ /* 0x03 */
    		TVP5150_MISC_CTL,0x01
    	},
    	{ /* 0x06 */
    		TVP5150_COLOR_KIL_THSH_CTL,0x10
    	},
    	{ /* 0x07 */
    		TVP5150_LUMA_PROC_CTL_1,0x60
    	},
    	{ /* 0x08 */
    		TVP5150_LUMA_PROC_CTL_2,0x00
    	},
    	{ /* 0x09 */
    		TVP5150_BRIGHT_CTL,0x80
    	},
    	{ /* 0x0a */
    		TVP5150_SATURATION_CTL,0x80
    	},
    	{ /* 0x0b */
    		TVP5150_HUE_CTL,0x00
    	},
    	{ /* 0x0c */
    		TVP5150_CONTRAST_CTL,0x80
    	},
    	{ /* 0x0d */
    		TVP5150_DATA_RATE_SEL,0x47
    	},
    	{ /* 0x0e */
    		TVP5150_LUMA_PROC_CTL_3,0x00
    	},
    	{ /* 0x0f */
    		TVP5150_CONF_SHARED_PIN,0x08
    	},
    	{ /* 0x11 */
    		TVP5150_ACT_VD_CROP_ST_MSB,0x00
    	},
    	{ /* 0x12 */
    		TVP5150_ACT_VD_CROP_ST_LSB,0x00
    	},
    	{ /* 0x13 */
    		TVP5150_ACT_VD_CROP_STP_MSB,0x00
    	},
    	{ /* 0x14 */
    		TVP5150_ACT_VD_CROP_STP_LSB,0x00
    	},
    	{ /* 0x15 */
    		TVP5150_GENLOCK,0x01
    	},
    	{ /* 0x16 */
    		TVP5150_HORIZ_SYNC_START,0x80
    	},
    	{ /* 0x18 */
    		TVP5150_VERT_BLANKING_START,0x00
    	},
    	{ /* 0x19 */
    		TVP5150_VERT_BLANKING_STOP,0x00
    	},
    	{ /* 0x1a */
    		TVP5150_CHROMA_PROC_CTL_1,0x0c
    	},
    	{ /* 0x1b */
    		TVP5150_CHROMA_PROC_CTL_2,0x14
    	},
    	{ /* 0x1c */
    		TVP5150_INT_RESET_REG_B,0x00
    	},
    	{ /* 0x1d */
    		TVP5150_INT_ENABLE_REG_B,0x00
    	},
    	{ /* 0x1e */
    		TVP5150_INTT_CONFIG_REG_B,0x00
    	},
    	{ /* 0x28 */
    		TVP5150_VIDEO_STD,0x00
    	},
    	{ /* 0x2e */
    		TVP5150_MACROVISION_ON_CTR,0x0f
    	},
    	{ /* 0x2f */
    		TVP5150_MACROVISION_OFF_CTR,0x01
    	},
    	{ /* 0xbb */
    		TVP5150_TELETEXT_FIL_ENA,0x00
    	},
    	{ /* 0xc0 */
    		TVP5150_INT_STATUS_REG_A,0x00
    	},
    	{ /* 0xc1 */
    		TVP5150_INT_ENABLE_REG_A,0x00
    	},
    	{ /* 0xc2 */
    		TVP5150_INT_CONF,0x04
    	},
    	{ /* 0xc8 */
    		TVP5150_FIFO_INT_THRESHOLD,0x80
    	},
    	{ /* 0xc9 */
    		TVP5150_FIFO_RESET,0x00
    	},
    	{ /* 0xca */
    		TVP5150_LINE_NUMBER_INT,0x00
    	},
    	{ /* 0xcb */
    		TVP5150_PIX_ALIGN_REG_LOW,0x4e
    	},
    	{ /* 0xcc */
    		TVP5150_PIX_ALIGN_REG_HIGH,0x00
    	},
    	{ /* 0xcd */
    		TVP5150_FIFO_OUT_CTRL,0x01
    	},
    	{ /* 0xcf */
    		TVP5150_FULL_FIELD_ENA,0x00
    	},
    	{ /* 0xd0 */
    		TVP5150_LINE_MODE_INI,0x00
    	},
    	{ /* 0xfc */
    		TVP5150_FULL_FIELD_MODE_REG,0x7f
    	},
    	{ /* end of data */
    		0xff,0xff
    	}
    };
    
    /* Default values as sugested at TVP5150AM1 datasheet */
    static const struct i2c_reg_value tvp5150_init_enable[] = {
    	{
    		TVP5150_CONF_SHARED_PIN, 2
    	},{	/* Automatic offset and AGC enabled */
    		TVP5150_ANAL_CHL_CTL, 0x15
    	},{	/* Activate YCrCb output 0x9 or 0xd ? */
    		TVP5150_MISC_CTL, 0x6f
    	},{	/* Activates video std autodetection for all standards */
    		TVP5150_AUTOSW_MSK, 0x0
    	},{	/* Default format: 0x47. For 4:2:2: 0x40 */
    		TVP5150_DATA_RATE_SEL, 0x47
    	},{
    		TVP5150_CHROMA_PROC_CTL_1, 0x0c
    	},{
    		TVP5150_CHROMA_PROC_CTL_2, 0x54
    	},{	/* Non documented, but initialized on WinTV USB2 */
    		0x27, 0x20
    	},{
    		0xff,0xff
    	}
    };
    
    struct tvp5150_vbi_type {
    	unsigned int vbi_type;
    	unsigned int ini_line;
    	unsigned int end_line;
    	unsigned int by_field :1;
    };
    
    struct i2c_vbi_ram_value {
    	u16 reg;
    	struct tvp5150_vbi_type type;
    	unsigned char values[16];
    };
    
    /* This struct have the values for each supported VBI Standard
     * by
     tvp5150_vbi_types should follow the same order as vbi_ram_default
     * value 0 means rom position 0x10, value 1 means rom position 0x30
     * and so on. There are 16 possible locations from 0 to 15.
     */
    
    static struct i2c_vbi_ram_value vbi_ram_default[] =
    {
    	/* FIXME: Current api doesn't handle all VBI types, those not
    	   yet supported are placed under #if 0 */
    #if 0
    	{0x010, /* Teletext, SECAM, WST System A */
    		{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
    		  0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
    	},
    #endif
    	{0x030, /* Teletext, PAL, WST System B */
    		{V4L2_SLICED_TELETEXT_B,6,22,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
    		  0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
    	},
    #if 0
    	{0x050, /* Teletext, PAL, WST System C */
    		{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
    		  0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
    	},
    	{0x070, /* Teletext, NTSC, WST System B */
    		{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
    		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
    	},
    	{0x090, /* Tetetext, NTSC NABTS System C */
    		{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
    		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
    	},
    	{0x0b0, /* Teletext, NTSC-J, NABTS System D */
    		{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
    		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
    	},
    	{0x0d0, /* Closed Caption, PAL/SECAM */
    		{V4L2_SLICED_CAPTION_625,22,22,1},
    		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
    		  0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
    	},
    #endif
    	{0x0f0, /* Closed Caption, NTSC */
    		{V4L2_SLICED_CAPTION_525,21,21,1},
    		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
    		  0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
    	},
    	{0x110, /* Wide Screen Signal, PAL/SECAM */
    		{V4L2_SLICED_WSS_625,23,23,1},
    		{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
    		  0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
    	},
    #if 0
    	{0x130, /* Wide Screen Signal, NTSC C */
    		{V4L2_SLICED_WSS_525,20,20,1},
    		{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
    		  0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
    	},
    	{0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
    		{V4l2_SLICED_VITC_625,6,22,0},
    		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
    		  0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
    	},
    	{0x170, /* Vertical Interval Timecode (VITC), NTSC */
    		{V4l2_SLICED_VITC_525,10,20,0},
    		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
    		  0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
    	},
    #endif
    	{0x190, /* Video Program System (VPS), PAL */
    		{V4L2_SLICED_VPS,16,16,0},
    		{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
    		  0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
    	},
    	/* 0x1d0 User programmable */
    
    	/* End of struct */
    	{ (u16)-1 }
    };
    
    static int tvp5150_write_inittab(struct v4l2_subdev *sd,
    				const struct i2c_reg_value *regs)
    {
    	while (regs->reg != 0xff) {
    		tvp5150_write(sd, regs->reg, regs->value);
    		regs++;
    	}
    	return 0;
    }
    
    static int tvp5150_vdp_init(struct v4l2_subdev *sd,
    				const struct i2c_vbi_ram_value *regs)
    {
    	unsigned int i;
    
    	/* Disable Full Field */
    	tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
    
    	/* Before programming, Line mode should be at 0xff */
    	for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
    		tvp5150_write(sd, i, 0xff);
    
    	/* Load Ram Table */
    	while (regs->reg != (u16)-1) {
    		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
    		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
    
    		for (i = 0; i < 16; i++)
    			tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
    
    		regs++;
    	}
    	return 0;
    }
    
    /* Fills VBI capabilities based on i2c_vbi_ram_value struct */
    static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
    				struct v4l2_sliced_vbi_cap *cap)
    {
    	const struct i2c_vbi_ram_value *regs = vbi_ram_default;
    	int line;
    
    	v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n");
    	memset(cap, 0, sizeof *cap);
    
    	while (regs->reg != (u16)-1 ) {
    		for (line=regs->type.ini_line;line<=regs->type.end_line;line++) {
    			cap->service_lines[0][line] |= regs->type.vbi_type;
    		}
    		cap->service_set |= regs->type.vbi_type;
    
    		regs++;
    	}
    	return 0;
    }
    
    /* Set vbi processing
     * type - one of tvp5150_vbi_types
     * line - line to gather data
     * fields: bit 0 field1, bit 1, field2
     * flags (default=0xf0) is a bitmask, were set means:
     *	bit 7: enable filtering null bytes on CC
     *	bit 6: send data also to FIFO
     *	bit 5: don't allow data with errors on FIFO
     *	bit 4: enable ECC when possible
     * pix_align = pix alignment:
     *	LSB = field1
     *	MSB = field2
     */
    static int tvp5150_set_vbi(struct v4l2_subdev *sd,
    			const struct i2c_vbi_ram_value *regs,
    			unsigned int type,u8 flags, int line,
    			const int fields)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    	v4l2_std_id std = decoder->norm;
    	u8 reg;
    	int pos=0;
    
    	if (std == V4L2_STD_ALL) {
    		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
    		return 0;
    	} else if (std & V4L2_STD_625_50) {
    		/* Don't follow NTSC Line number convension */
    		line += 3;
    	}
    
    	if (line<6||line>27)
    		return 0;
    
    	while (regs->reg != (u16)-1 ) {
    		if ((type & regs->type.vbi_type) &&
    		    (line>=regs->type.ini_line) &&
    		    (line<=regs->type.end_line)) {
    			type=regs->type.vbi_type;
    			break;
    		}
    
    		regs++;
    		pos++;
    	}
    	if (regs->reg == (u16)-1)
    		return 0;
    
    	type=pos | (flags & 0xf0);
    	reg=((line-6)<<1)+TVP5150_LINE_MODE_INI;
    
    	if (fields&1) {
    		tvp5150_write(sd, reg, type);
    	}
    
    	if (fields&2) {
    		tvp5150_write(sd, reg+1, type);
    	}
    
    	return type;
    }
    
    static int tvp5150_get_vbi(struct v4l2_subdev *sd,
    			const struct i2c_vbi_ram_value *regs, int line)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    	v4l2_std_id std = decoder->norm;
    	u8 reg;
    	int pos, type = 0;
    
    	if (std == V4L2_STD_ALL) {
    		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
    		return 0;
    	} else if (std & V4L2_STD_625_50) {
    		/* Don't follow NTSC Line number convension */
    		line += 3;
    	}
    
    	if (line < 6 || line > 27)
    		return 0;
    
    	reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
    
    	pos = tvp5150_read(sd, reg) & 0x0f;
    	if (pos < 0x0f)
    		type = regs[pos].type.vbi_type;
    
    	pos = tvp5150_read(sd, reg + 1) & 0x0f;
    	if (pos < 0x0f)
    		type |= regs[pos].type.vbi_type;
    
    	return type;
    }
    
    /**
     * tvp515x_query_current_std() : Query the current standard detected by TVP5151
     * @sd: ptr to v4l2_subdev struct
     *
     * Returns the current standard detected by TVP5151, STD_INVALID if there is no
     * standard detected.
     */
    static int tvp515x_query_current_std(struct v4l2_subdev *sd)
    {
    	u8 std, std_status;
    
    	std = tvp5150_read(sd, TVP5150_VIDEO_STD);
    	printk(KERN_CRIT "KVA Auto switch bit is %d\n",VIDEO_STD_AUTO_SWITCH_BIT);
    	if ((std & 0xf /* KVA VIDEO_STD_MASK */) == VIDEO_STD_AUTO_SWITCH_BIT) {
    		/* use the standard status register */
    		std_status = tvp5150_read(sd, TVP5150_STATUS_REG_5);
    		printk(KERN_CRIT "KVA Auto switch set: video standard is %d\n",std);
    	}
    	else {
    		/* use the standard register itself */
    		std_status = std;
    		printk(KERN_CRIT "KVA Auto switch not set: video standard is %d\n",std);
    	}
    
    	switch (std_status & VIDEO_STD_MASK) {
    // KVA 	case VIDEO_STD_NTSC_MJ_BIT:
    	case VIDEO_STD_NTSC_MJ_BIT_AS:
    		return STD_NTSC_MJ;
    
    	case VIDEO_STD_PAL_BDGHIN_BIT:
    // KVA 	case VIDEO_STD_PAL_BDGHIN_BIT_AS:
    		return STD_PAL_BDGHIN;
    
    	default:
    		return STD_INVALID;
    	}
    
    	return STD_INVALID;
    }
    
    /****************************************************************************
    			V4L2 subdev video operations
     ****************************************************************************/
    
    static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    	int fmt = 0;
    
    	decoder->norm = std;
    
    	/* First tests should be against specific std */
    
    	if (std == V4L2_STD_ALL) {
    		fmt = 0;	/* Autodetect mode */
    	} else if (std & V4L2_STD_NTSC_443) {
    		fmt = VIDEO_STD_NTSC_4_43_BIT;
    	} else if (std & V4L2_STD_PAL_M) {
    		fmt = VIDEO_STD_PAL_M_BIT;
    	} else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
    		fmt = VIDEO_STD_PAL_COMBINATION_N_BIT;
    	} else {
    		/* Then, test against generic ones */
    		if (std & V4L2_STD_NTSC)
    			fmt = VIDEO_STD_NTSC_MJ_BIT;
    		else if (std & V4L2_STD_PAL)
    			fmt = VIDEO_STD_PAL_BDGHIN_BIT;
    		else if (std & V4L2_STD_SECAM)
    			fmt = VIDEO_STD_SECAM_BIT;
    	}
    
    	v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt);
    	printk(KERN_CRIT "KVA setting TVP5150_VIDEO_STD, to 0x%x from tvp5150_set_std\n",fmt);
     	tvp5150_write(sd, TVP5150_VIDEO_STD, fmt);
    	return 0;
    }
    
    static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    	int i;
    	int num_stds = ARRAY_SIZE(tvp515x_std_list);
    
    	if (decoder->norm == std)
    		return 0;
    
    	for (i = 0; i < num_stds; i++)
    		if (std & tvp515x_std_list[i].standard.id)
    			break;
    
    	if ((i == num_stds) || (i == STD_INVALID))
    		return -EINVAL;
    
    	printk(KERN_CRIT "KVA setting TVP5150_VIDEO_STD, to 0x%x from tvp5150_s_std\n",tvp515x_std_list[i].video_std);
    	tvp5150_write(sd, TVP5150_VIDEO_STD, tvp515x_std_list[i].video_std);
    	printk(KERN_CRIT "KVA TVP5150_VIDEO_STD value is 0x%x\n",tvp5150_read(sd, TVP5150_VIDEO_STD)); 
    	decoder->norm = i;
    
    /* 	return tvp5150_set_std(sd, std);  */
     	return 0; 
    }
    
    static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    
    	/* Initializes TVP5150 to its default values */
    	tvp5150_write_inittab(sd, tvp5150_init_default);
    
    	/* Initializes VDP registers */
    	tvp5150_vdp_init(sd, vbi_ram_default);
    
    	/* Selects decoder input */
    	tvp5150_selmux(sd);
    
    	/* Initializes TVP5150 to stream enabled values */
    	tvp5150_write_inittab(sd, tvp5150_init_enable);
    
    	/* Initialize image preferences */
    	v4l2_ctrl_handler_setup(&decoder->hdl);
    
    	tvp5150_set_std(sd, decoder->norm);
    	return 0;
    };
    
    static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
    {
    	struct v4l2_subdev *sd = to_sd(ctrl);
    
    	switch (ctrl->id) {
    	case V4L2_CID_BRIGHTNESS:
    		tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val);
    		return 0;
    	case V4L2_CID_CONTRAST:
    		tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val);
    		return 0;
    	case V4L2_CID_SATURATION:
    		tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val);
    		return 0;
    	case V4L2_CID_HUE:
    		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
    		return 0;
    	}
    	return -EINVAL;
    }
    
    static int tvp5150_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
    {
    	struct v4l2_subdev *sd = to_sd(ctrl);
    	int ret;
    
    	switch (ctrl->id) {
    	case V4L2_CID_BRIGHTNESS:
    		ret = tvp5150_read(sd, TVP5150_BRIGHT_CTL);
    		return ret;
    	case V4L2_CID_CONTRAST:
    		ret = tvp5150_read(sd, TVP5150_CONTRAST_CTL);
    		return ret;
    	case V4L2_CID_SATURATION:
    		ret = tvp5150_read(sd, TVP5150_SATURATION_CTL);
    		return ret;
    	case V4L2_CID_HUE:
    		ret = tvp5150_read(sd, TVP5150_HUE_CTL);
    		return ret;
    	}
    
    	return -EINVAL;
    }
    
    /*
    static struct v4l2_mbus_framefmt *
    __tvp5150_get_pad_format(struct tvp5150 *tvp5150, struct v4l2_subdev_fh *fh,
    			 unsigned int pad, enum v4l2_subdev_format_whence which)
    {
    	switch (which) {
    	case V4L2_SUBDEV_FORMAT_TRY:
    		return v4l2_subdev_get_try_format(fh, pad);
    	case V4L2_SUBDEV_FORMAT_ACTIVE:
    		return tvp5150->format;
    	default:
    		return NULL;
    	}
    }
    */
    
    static int tvp5150_get_pad_format(struct v4l2_subdev *subdev,
    			      struct v4l2_subdev_fh *fh,
    			      struct v4l2_subdev_format *format)
    {
    	struct tvp5150 *tvp5150 = to_tvp5150(subdev);
    	struct v4l2_mbus_framefmt *current_fmt;
    	int norm;
    
    /*
    	format->format = *__tvp5150_get_pad_format(tvp5150, fh, format->pad,
    						   format->which);
    */
    	/* Paranoid ? */
    	if (tvp5150->format) {
    		current_fmt = tvp5150->format;
    		norm = tvp5150->norm;
    	} else {
    		current_fmt = &tvp515x_std_list[STD_PAL_BDGHIN].format;
    		norm = V4L2_STD_PAL;
    	}
    
    	format->format.width =  current_fmt->width;
    	format->format.height = current_fmt->height;
    	format->format.code = current_fmt->code;
    	format->format.colorspace = current_fmt->colorspace;
    	format->format.priv = norm;
    
    	return 0;
    }
    
    static int tvp5150_set_pad_format(struct v4l2_subdev *subdev,
    			      struct v4l2_subdev_fh *fh,
    			      struct v4l2_subdev_format *format)
    {
    	struct tvp5150 *tvp5150 = to_tvp5150(subdev);
    	tvp5150->std_idx = STD_INVALID;
    
    	tvp5150->std_idx = tvp515x_query_current_std(subdev);
    	if (tvp5150->std_idx == STD_INVALID) {
    		v4l2_err(subdev, "Unable to query std\n");
    /*	return 0; */
    		tvp5150->std_idx = STD_PAL_BDGHIN;
    	}
    	tvp5150->norm = tvp515x_std_list[tvp5150->std_idx].standard.id;
    
    	tvp5150->format = &tvp515x_std_list[tvp5150->std_idx].format;
    
    /*
    	format->format = *__tvp5150_get_pad_format(tvp5150, fh, format->pad,
    	format->which);
    */
    
    	format->format.width =  tvp5150->format->width;
    	format->format.height = tvp5150->format->height;
    	format->format.code = tvp5150->format->code;
    	format->format.colorspace = tvp5150->format->colorspace;
    	format->format.priv = tvp5150->norm;
    
    
    	v4l2_info(subdev, "code=x%x width=%u height=%u colorspace=0x%x\n",
    			format->format.code, format->format.width,
    			format->format.height, format->format.colorspace);
    	//printk("************* the value are*************\n");
    	//printk("code=x%x width=%u height=%u colorspace=0x%x\n",
    	//		format->format.code, format->format.width,
    	//		format->format.height, format->format.colorspace);
    
    	return 0;
    }
    
    /**
     * tvp515x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt
     * @sd: pointer to standard V4L2 sub-device structure
     * @f: pointer to the mediabus format structure
     *
     * Negotiates the image capture size and mediabus format.
     */
    static int
    tvp515x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    
    	if (f == NULL)
    		return -EINVAL;
    
    	f = decoder->format;
    	f->priv = decoder->norm;
    
    	v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
    			f->width, f->height);
    	return 0;
    }
    
    /*
     * tvp515x_s_stream() - V4L2 decoder i/f handler for s_stream
     * @sd: pointer to standard V4L2 sub-device structure
     * @enable: streaming enable or disable
     *
     * Sets streaming to enable or disable, if possible.
     */
    static int tvp515x_s_stream(struct v4l2_subdev *subdev, int enable)
    {
    
    	/* Initializes TVP5150 to its default values */
    	/* # set PCLK (27MHz) */
    	tvp5150_write(subdev, TVP5150_CONF_SHARED_PIN, 0x00);
    
    	/* Output format: 8-bit ITU-R BT.656 with embedded syncs */
    	if (enable)
    		tvp5150_write(subdev, TVP5150_MISC_CTL, 0x09);
    	else
    		tvp5150_write(subdev, TVP5150_MISC_CTL, 0x00);
    
    	return 0;
    }
    
    
    /**
     * tvp515x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt
     * @sd: pointer to standard V4L2 sub-device structure
     * @index: index of pixelcode to retrieve
     * @code: receives the pixelcode
     *
     * Enumerates supported mediabus formats
     */
    static int
    tvp515x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
    					enum v4l2_mbus_pixelcode *code)
    {
    	if (index)
    		return -EINVAL;
    
    	*code = V4L2_MBUS_FMT_UYVY8_2X8;
    	return 0;
    }
    
    /**
     * tvp515x_g_parm() - V4L2 decoder interface handler for g_parm
     * @sd: pointer to standard V4L2 sub-device structure
     * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
     *
     * Returns the decoder's video CAPTURE parameters.
     */
    static int
    tvp515x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
    {
    	struct v4l2_captureparm *cparm;
    
    	if (a == NULL)
    		return -EINVAL;
    
    	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    		/* only capture is supported */
    		return -EINVAL;
    
    	cparm = &a->parm.capture;
    	cparm->capability = V4L2_CAP_TIMEPERFRAME;
    	cparm->timeperframe = a->parm.capture.timeperframe;
    
    	return 0;
    }
    
    /**
     * tvp515x_s_parm() - V4L2 decoder interface handler for s_parm
     * @sd: pointer to standard V4L2 sub-device structure
     * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
     *
     * Configures the decoder to use the input parameters, if possible. If
     * not possible, returns the appropriate error code.
     */
    static int
    tvp515x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
    {
    	struct v4l2_fact *timeperframe;
    
    	if (a == NULL)
    		return -EINVAL;
    
    	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    		/* only capture is supported */
    		return -EINVAL;
    
    	timeperframe = &a->parm.capture.timeperframe;
    
    	return 0;
    }
    
    
    
    /****************************************************************************
    			I2C Command
     ****************************************************************************/
    
    static int tvp5150_s_routing(struct v4l2_subdev *sd,
    			     u32 input, u32 output, u32 config)
    {
    	struct tvp5150 *decoder = to_tvp5150(sd);
    
    	decoder->input = input;
    	decoder->output = output;
    	tvp5150_selmux(sd);
    	return 0;
    }
    
    static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
    {
    	/* this is for capturing 36 raw vbi lines
    	   if there's a way to cut off the beginning 2 vbi lines
    	   with the tvp5150 then the vbi line count could be lowered
    	   to 17 lines/field again, although I couldn't find a register
    	   which could do that cropping */
    	if (fmt->sample_format == V4L2_PIX_FMT_GREY)
    		tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
    	if (fmt->count[0] == 18 && fmt->count[1] == 18) {
    		tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00);
    		tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01);
    	}
    	return 0;
    }
    
    static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
    {
    	int i;
    
    	if (svbi->service_set != 0) {
    		for (i = 0; i <= 23; i++) {
    			svbi->service_lines[1][i] = 0;
    			svbi->service_lines[0][i] =
    				tvp5150_set_vbi(sd, vbi_ram_default,
    				       svbi->service_lines[0][i], 0xf0, i, 3);
    		}
    		/* Enables FIFO */
    		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
    	} else {
    		/* Disables FIFO*/
    		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0);
    
    		/* Disable Full Field */
    		tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
    
    		/* Disable Line modes */
    		for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
    			tvp5150_write(sd, i, 0xff);
    	}
    	return 0;
    }
    
    static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
    {
    	int i, mask = 0;
    
    	memset(svbi, 0, sizeof(*svbi));
    
    	for (i = 0; i <= 23; i++) {
    		svbi->service_lines[0][i] =
    			tvp5150_get_vbi(sd, vbi_ram_default, i);
    		mask |= svbi->service_lines[0][i];
    	}
    	svbi->service_set = mask;
    	return 0;
    }
    
    static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
    				struct v4l2_dbg_chip_ident *chip)
    {
    	int rev;
    	struct i2c_client *client = v4l2_get_subdevdata(sd);
    
    	rev = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER) << 8 |
    	      tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
    
    	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5150,
    					  rev);
    }
    
    
    #ifdef CONFIG_VIDEO_ADV_DEBUG
    static int tvp5150_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 = tvp5150_read(sd, reg->reg & 0xff);
    	reg->size = 1;
    	return 0;
    }
    
    static int tvp5150_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;
    	tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff);
    	return 0;
    }
    #endif
    
    static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
    {
    	int status = tvp5150_read(sd, 0x88);
    
    	vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0;
    	return 0;
    }
    
    /****************************************************************************
    		    V4L2 subdev core operations
     ****************************************************************************/
    
    static int tvp5150_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
    {
    	struct tvp5150 *decoder = to_tvp5150(subdev);
    
    	decoder->std_idx = STD_INVALID;
    
    	decoder->std_idx = tvp515x_query_current_std(subdev);
    
    	if (decoder->std_idx == STD_INVALID) {
    		v4l2_err(subdev, "Unable to query std\n");
    /*		return 0;  */
                    /* If no standard is found when open the device, maybe is
    		 * because there isn't an analog video input stream on the
    		 * device, let's just force a predefined initial standard
    		 */
    		decoder->std_idx = STD_PAL_BDGHIN;
    	}
    
    	decoder->format = (&(tvp515x_std_list[decoder->std_idx].format));
    	decoder->norm = tvp515x_std_list[decoder->std_idx].standard.id;
    
    	return 0;
    }
    
    static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
    	.s_ctrl = tvp5150_s_ctrl,
    	.g_volatile_ctrl = tvp5150_g_volatile_ctrl,
    };
    
    static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
    	.log_status = tvp5150_log_status,
    	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
    	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
    	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
    	.g_ctrl = v4l2_subdev_g_ctrl,
    	.s_ctrl = v4l2_subdev_s_ctrl,
    	.queryctrl = v4l2_subdev_queryctrl,
    	.querymenu = v4l2_subdev_querymenu,
    	.s_std = tvp5150_s_std,
    	.reset = tvp5150_reset,
    	.g_chip_ident = tvp5150_g_chip_ident,
    #ifdef CONFIG_VIDEO_ADV_DEBUG
    	.g_register = tvp5150_g_register,
    	.s_register = tvp5150_s_register,
    #endif
    };
    
    static struct v4l2_subdev_file_ops tvp5150_subdev_file_ops = {
    	.open		= tvp5150_open,
    };
    
    static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
    	.g_tuner = tvp5150_g_tuner,
    };
    
    static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
    	.s_routing = tvp5150_s_routing,
    	.s_stream = tvp515x_s_stream,
    	.enum_mbus_fmt = tvp515x_enum_mbus_fmt,
    	.g_mbus_fmt = tvp515x_mbus_fmt,
    	.try_mbus_fmt = tvp515x_mbus_fmt,
    	.s_mbus_fmt = tvp515x_mbus_fmt,
    	.g_parm = tvp515x_g_parm,
    	.s_parm = tvp515x_s_parm,
    	.s_std_output = tvp5150_s_std,
    };
    
    static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
    	.g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap,
    	.g_sliced_fmt = tvp5150_g_sliced_fmt,
    	.s_sliced_fmt = tvp5150_s_sliced_fmt,
    	.s_raw_fmt = tvp5150_s_raw_fmt,
    };
    
    static int tvp515x_enum_mbus_code(struct v4l2_subdev *subdev,
    				  struct v4l2_subdev_fh *fh,
    				  struct v4l2_subdev_mbus_code_enum *code)
    {
    	if (code->index >= ARRAY_SIZE(tvp515x_std_list))
    		return -EINVAL;
    
    	code->code = V4L2_MBUS_FMT_UYVY8_2X8;
    
    	return 0;
    }
    
    static int tvp515x_enum_frame_size(struct v4l2_subdev *subdev,
    				   struct v4l2_subdev_fh *fh,
    				   struct v4l2_subdev_frame_size_enum *fse)
    {
    	int current_std = STD_INVALID;
    
    	if (fse->code != V4L2_MBUS_FMT_UYVY8_2X8)
    		return -EINVAL;
    
    	/* query the current standard */
    	current_std = tvp515x_query_current_std(subdev);
    	if (current_std == STD_INVALID) {
    		v4l2_err(subdev, "Unable to query std\n");
    		return 0;
    	}
    
    	fse->min_width = tvp515x_std_list[current_std].format.width;
    	fse->min_height = tvp515x_std_list[current_std].format.height;
    	fse->max_width = fse->min_width;
    	fse->max_height = fse->min_height;
    	return 0;
    }
    
    static struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
    	.enum_mbus_code = tvp515x_enum_mbus_code,
    	.enum_frame_size = tvp515x_enum_frame_size,
    	.get_fmt = tvp5150_get_pad_format,
    	.set_fmt = tvp5150_set_pad_format,
    };
    
    static const struct v4l2_subdev_ops tvp5150_ops = {
    	.core = &tvp5150_core_ops,
    	.file	= &tvp5150_subdev_file_ops,
    	.tuner = &tvp5150_tuner_ops,
    	.video = &tvp5150_video_ops,
    	.vbi = &tvp5150_vbi_ops,
    	.pad = &tvp5150_pad_ops,
    };
    
    /****************************************************************************
    			I2C Client & Driver
     ****************************************************************************/
    
    static int tvp5150_probe(struct i2c_client *c,
    			 const struct i2c_device_id *id)
    {
    	struct tvp5150 *core;
    	struct v4l2_subdev *sd;
    	u8 msb_id, lsb_id, msb_rom, lsb_rom;
    	int ret;
    
    	/* 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 tvp5150), GFP_KERNEL);
    	if (!core) {
    		return -ENOMEM;
    	}
    	sd = &core->sd;
    	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
    	v4l_info(c, "chip found @ 0x%02x (%s)\n",
    		 c->addr << 1, c->adapter->name);
    	//printk("TVP address chip found @ 0x%02x (%s)\n",
    //		 c->addr >> 1, c->adapter->name);		//BEL
    // BEL
    //	unsigned int *test, val;
    //	test = ioremap(0x01C4000C, 0x01);
    //	val = *(test + 0x0);
    //	printk("the pinmux remap is %x", val);
    //	iounmap(test);
    // BEL
    //	while(1) {
    	msb_id = tvp5150_read(sd, TVP5150_MSB_DEV_ID);
    //	}
    	lsb_id = tvp5150_read(sd, TVP5150_LSB_DEV_ID);
    	msb_rom = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER);
    	lsb_rom = tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
    
    	if (msb_rom == 4 && lsb_rom == 0) { /* Is TVP5150AM1 */
    		v4l2_info(sd, "tvp%02x%02xam1 detected.\n", msb_id, lsb_id);
    		printk("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
    		printk("BEL=> tvp%02x%02xam1 detected.\n", msb_id, lsb_id);
    
    		/* ITU-T BT.656.4 timing */
    		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
    	} else {
    		if (msb_rom == 3 || lsb_rom == 0x21) { /* Is TVP5150A */
    			v4l2_info(sd, "tvp%02x%02xa detected.\n", msb_id, lsb_id);
    		} else {
    			v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
    					msb_id, lsb_id);
    			v4l2_info(sd, "*** Rom ver is %d.%d\n", msb_rom, lsb_rom);
    		}
    	}
    
    	core->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
    	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
    	core->input = TVP5150_COMPOSITE0;
    	core->enable = 1;
    
    	v4l2_ctrl_handler_init(&core->hdl, 4);
    	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
    			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
    	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
    			V4L2_CID_CONTRAST, 0, 255, 1, 128);
    	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
    			V4L2_CID_SATURATION, 0, 255, 1, 128);
    	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
    			V4L2_CID_HUE, -128, 127, 1, 0);
    	sd->ctrl_handler = &core->hdl;
    	if (core->hdl.error) {
    		int err = core->hdl.error;
    
    		v4l2_ctrl_handler_free(&core->hdl);
    		kfree(core);
    		return err;
    	}
    	v4l2_ctrl_handler_setup(&core->hdl);
    
    /*	if (debug > 1) KVA */
    		tvp5150_log_status(sd);
    
    	core->pad.flags = MEDIA_PAD_FLAG_OUTPUT;
    	ret = media_entity_init(&core->sd.entity, 1, &core->pad, 0);
    	if (ret < 0)
    		kfree(core);
    	printk("\n THE DRIVER IS REGISTER AT the probe function  \n");
    	return 0;
    }
    
    static int tvp5150_remove(struct i2c_client *c)
    {
    	struct v4l2_subdev *sd = i2c_get_clientdata(c);
    	struct tvp5150 *decoder = to_tvp5150(sd);
    
    	v4l2_dbg(1, debug, sd,
    		"tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
    		c->addr << 1);
    
    	v4l2_device_unregister_subdev(sd);
    	v4l2_ctrl_handler_free(&decoder->hdl);
    	kfree(to_tvp5150(sd));
    	return 0;
    }
    
    /* ----------------------------------------------------------------------- */
    
    static const struct i2c_device_id tvp5150_id[] = {
    	{ "tvp5150", 0 },
    	{ }
    };
    MODULE_DEVICE_TABLE(i2c, tvp5150_id);
    
    static struct i2c_driver tvp5150_driver = {
    	.driver = {
    		.owner	= THIS_MODULE,
    		.name	= "tvp5150",
    	},
    	.probe		= tvp5150_probe,
    	.remove		= tvp5150_remove,
    	.id_table	= tvp5150_id,
    };
    
    static __init int init_tvp5150(void)
    {
    	return i2c_add_driver(&tvp5150_driver);
    }
    
    static __exit void exit_tvp5150(void)
    {
    	i2c_del_driver(&tvp5150_driver);
    }
    
    module_init(init_tvp5150);
    module_exit(exit_tvp5150);
    

  • Thank you Ravikiran HV. But the IPNC RDK calls the driver of the sensor in the ipnc_rdk / av_capture / framework / drv / usermod / src / imgs_TVP514x / drv_imgs_TVP514X.c instead of the kernel layer ipnc_psp_03_21_00_04 / ti-davinci / drivers / media / video / tvp514x.c Drv_imgs_TVP514X.c related functions modified TVP5150 operating function.

  • Yes I agree.

    Driver file shared is a reference, so that you can customize IPNC for TVP5150.

    Only difference b/w IPNC & DVSDK is , in IPNC driver code is placed in frame work itself and copied to kernel directory during build where in DVSDK all the driver as placed as per kernel hierarchy 

    Hope this reference code will help :)

  • Hi,

    I hope above inputs were helpful in solving your issue.
    If the issue is resolved then please close the thread by verifying answer.

    Regards,
    Anuj
    Pathpartner Technology Pvt Ltd