Thanks, Vaibhav Hiremath > -----Original Message----- > From: Hans Verkuil [mailto:hverkuil@xxxxxxxxx] > Sent: Tuesday, December 02, 2008 10:50 PM > To: video4linux-list@xxxxxxxxxx > Cc: Hiremath, Vaibhav; davinci-linux-open-source- > bounces@xxxxxxxxxxxxxxxxxxxx; Karicheri, Muralidharan; linux- > omap@xxxxxxxxxxxxxxx > Subject: Re: [PATCH 2/2] TVP514x Driver with Review comments fixed > [V4] > > Hi Vaibhav, > > I'm sorry, but this is still wrong. You basically renamed s_input > with > s_routing while still using the list with user inputs from the > platform > data. > > These three fields in struct tvp514x_platform_data should be removed > as > they do not belong here: > > > + /* Input params */ > > + int num_inputs; > > + const struct tvp514x_input_info *input_list; > > + int default_input; > > This is all high-level stuff that does not belong in an i2c driver. > It's > the master driver that has to translate the input as specified by > the > user to a pin of the tvp514x (like INPUT_CVBS_VI1A). > > Also, ioctl_g_routing() can be removed as I have yet to see a master > driver that is interested in obtaining this information. Besides, > that > function looks very strange because it is calling ioctl_s_routing. A > get function that sets something?!? > > Eventually the whole tvp514x_platform_data will have to be removed. > Everything that's in there should be passed to the i2c driver using > v4l2_subdev ops. But that's something for the future. > [Hiremath, Vaibhav] Definitely, as you mentioned eventually the platform data dependency from TVP driver will be removed. But I will have to start with master driver to do it, since now platform data will go to master driver which will maintain list or table at his level. I think yesterday on chat I had mentioned clearly that, simultaneously I will have to start with master driver which will automatically address your all comments, like - - g_routing: Since this will get handled at master level no need to support at slave or TVP level. - s_routing: The input params will change to v4l2_routing, and argument will come directly from master. Master will now include "tvp514x.h" file to pass appropriate routing data. - tvp514x_platform_data: Again, the data related to input will go to master. Since it would take good amount of change and time, I thought to get reviewed first and while submitting master driver anyway I will have to change. I believe once master driver becomes slave aware (including tvp514x.h); all issues automatically will get addressed. Probably I missed to mention all these points in the patch, which lead to confusion. Hope this clears. > I'm available in the #v4l IRC channel tomorrow for further > discussions > on this. > > BTW1, struct tvp514x_decoder shouldn't be in > include/media/tvp514x.h. > It's internal to the driver (at least, I sincerely hope so), so it > can > be moved to either the source or the tvp514x_regs.h header. > > BTW2, I'm not going to make it a blocking issue, but those callback > functions in tvp514x_platform_data are horrible. The priv_data_set > callback is the clearest example of what's wrong with this design: a > master driver calls ioctl_g_priv in tvp whose only action is to call > priv_data_set in the platform code! The master driver shouldn't have > to > go through the i2c driver for that! The only reason a low level v4l > i2c > driver would ever make a call to higher level code is for > notifications. > > Regards, > > Hans > > On Tuesday 02 December 2008 16:35:42 hvaibhav@xxxxxx wrote: > > From: Vaibhav Hiremath <hvaibhav@xxxxxx> > > > > I have fixed all the review commentsreceived so far. > > Here are the details - > > > > FIXSES: > > Make use of i2c_smbus_read/write_byte API: > > Probe function now checks for SMBUS capability, > > and read/write functions make use of the above API. > > > > Error check for I2C Read/Write: > > Added error condition check for both read and write > > API. > > This has been added for completeness. > > > > input set/get ioctl: > > As we do have support for set and get routing ioctl, > > instead of adding new ioctl used them. > > > > enum_ioctl: > > After discussing with Hans verkuil, came to conclusion > > that as of now just remove support for enum_ioctl from > > decoder, since this has to handle at master driver level. > > > > TODO LIST: > > OMAP Master capture driver: > > This should be completely aligned with the current > > discussion. > > > > Migration to sub_device framework: > > Immediately after all the above task, migrate both > > Master and slave driver to sub_device framework. > > > > Signed-off-by: Brijesh Jadav <brijesh.j@xxxxxx> > > Signed-off-by: Hardik Shah <hardik.shah@xxxxxx> > > Signed-off-by: Manjunath Hadli <mrh@xxxxxx> > > Signed-off-by: R Sivaraj <sivaraj@xxxxxx> > > Signed-off-by: Vaibhav Hiremath <hvaibhav@xxxxxx> > > Signed-off-by: Karicheri Muralidharan <m-karicheri2@xxxxxx> > > --- > > drivers/media/video/Kconfig | 11 + > > drivers/media/video/Makefile | 1 + > > drivers/media/video/tvp514x.c | 1521 > > ++++++++++++++++++++++++++++++++++++ > > drivers/media/video/tvp514x_regs.h | 292 +++++++ > > include/media/tvp514x.h | 232 ++++++ > > 5 files changed, 2057 insertions(+), 0 deletions(-) > > create mode 100755 drivers/media/video/tvp514x.c > > create mode 100755 drivers/media/video/tvp514x_regs.h > > create mode 100755 include/media/tvp514x.h > > > > diff --git a/drivers/media/video/Kconfig > > b/drivers/media/video/Kconfig index 47102c2..2e5dc3e 100644 > > --- a/drivers/media/video/Kconfig > > +++ b/drivers/media/video/Kconfig > > @@ -361,6 +361,17 @@ config VIDEO_SAA7191 > > To compile this driver as a module, choose M here: the > > module will be called saa7191. > > > > +config VIDEO_TVP514X > > + tristate "Texas Instruments TVP514x video decoder" > > + depends on VIDEO_V4L2 && I2C > > + ---help--- > > + This is a Video4Linux2 sensor-level driver for the TI > TVP5146/47 > > + decoder. It is currently working with the TI OMAP3 camera > > + controller. > > + > > + To compile this driver as a module, choose M here: the > > + module will be called tvp514x. > > + > > config VIDEO_TVP5150 > > tristate "Texas Instruments TVP5150 video decoder" > > depends on VIDEO_V4L2 && I2C > > diff --git a/drivers/media/video/Makefile > > b/drivers/media/video/Makefile index 16962f3..cdbbf38 100644 > > --- a/drivers/media/video/Makefile > > +++ b/drivers/media/video/Makefile > > @@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ > > obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ > > obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ > > obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o > > +obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o > > obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ > > obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o > > obj-$(CONFIG_VIDEO_CS5345) += cs5345.o > > diff --git a/drivers/media/video/tvp514x.c > > b/drivers/media/video/tvp514x.c new file mode 100755 > > index 0000000..c0834e4 > > --- /dev/null > > +++ b/drivers/media/video/tvp514x.c > > @@ -0,0 +1,1521 @@ > > +/* > > + * drivers/media/video/tvp514x.c > > + * > > + * TI TVP5146/47 decoder driver > > + * > > + * Copyright (C) 2008 Texas Instruments Inc > > + * Author: Vaibhav Hiremath <hvaibhav@xxxxxx> > > + * > > + * Contributors: > > + * Sivaraj R <sivaraj@xxxxxx> > > + * Brijesh R Jadav <brijesh.j@xxxxxx> > > + * Hardik Shah <hardik.shah@xxxxxx> > > + * Manjunath Hadli <mrh@xxxxxx> > > + * Karicheri Muralidharan <m-karicheri2@xxxxxx> > > + * > > + * This package is free software; you can redistribute it and/or > > modify + * it under the terms of the GNU General Public License > > version 2 as + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be > useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public > License > > + * along with this program; if not, write to the Free Software > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > + * > > + */ > > + > > +#include <linux/i2c.h> > > +#include <linux/delay.h> > > +#include <linux/videodev2.h> > > +#include <media/v4l2-int-device.h> > > +#include <media/tvp514x.h> > > + > > +#include "tvp514x_regs.h" > > + > > +#define MODULE_NAME TVP514X_MODULE_NAME > > + > > +/* Debug functions */ > > +static int debug; > > +module_param(debug, bool, 0644); > > +MODULE_PARM_DESC(debug, "Debug level (0-1)"); > > + > > +#define dump_reg(client, reg, val) \ > > + do { \ > > + val = tvp514x_read_reg(client, reg); \ > > + v4l_info(client, "Reg(0x%.2X): 0x%.2X\n", reg, val); \ > > + } while (0) > > + > > + > > +/* TVP514x default register values */ > > +static struct tvp514x_reg tvp514x_reg_list[] = { > > + {TOK_WRITE, REG_INPUT_SEL, 0x05}, /* Composite selected */ > > + {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, > > + {TOK_WRITE, REG_VIDEO_STD, 0x00}, /* Auto mode */ > > + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, > > + {TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F}, > > + {TOK_WRITE, REG_COLOR_KILLER, 0x10}, > > + {TOK_WRITE, REG_LUMA_CONTROL1, 0x00}, > > + {TOK_WRITE, REG_LUMA_CONTROL2, 0x00}, > > + {TOK_WRITE, REG_LUMA_CONTROL3, 0x02}, > > + {TOK_WRITE, REG_BRIGHTNESS, 0x80}, > > + {TOK_WRITE, REG_CONTRAST, 0x80}, > > + {TOK_WRITE, REG_SATURATION, 0x80}, > > + {TOK_WRITE, REG_HUE, 0x00}, > > + {TOK_WRITE, REG_CHROMA_CONTROL1, 0x00}, > > + {TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E}, > > + {TOK_SKIP, 0x0F, 0x00}, /* Reserved */ > > + {TOK_WRITE, REG_COMP_PR_SATURATION, 0x80}, > > + {TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80}, > > + {TOK_WRITE, REG_COMP_PB_SATURATION, 0x80}, > > + {TOK_SKIP, 0x13, 0x00}, /* Reserved */ > > + {TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80}, > > + {TOK_SKIP, 0x15, 0x00}, /* Reserved */ > > + {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, /* NTSC timing > */ > > + {TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00}, > > + {TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25}, > > + {TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03}, > > + {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, /* NTSC timing > */ > > + {TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00}, > > + {TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40}, > > + {TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00}, > > + {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, /* NTSC timing > */ > > + {TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00}, > > + {TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07}, > > + {TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00}, > > + {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, /* NTSC timing > */ > > + {TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00}, > > + {TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15}, > > + {TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00}, > > + {TOK_SKIP, 0x26, 0x00}, /* Reserved */ > > + {TOK_SKIP, 0x27, 0x00}, /* Reserved */ > > + {TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC}, > > + {TOK_SKIP, 0x29, 0x00}, /* Reserved */ > > + {TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00}, > > + {TOK_SKIP, 0x2B, 0x00}, /* Reserved */ > > + {TOK_SKIP, REG_SCART_DELAY, 0x00}, > > + {TOK_SKIP, REG_CTI_DELAY, 0x00}, > > + {TOK_SKIP, REG_CTI_CONTROL, 0x00}, > > + {TOK_SKIP, 0x2F, 0x00}, /* Reserved */ > > + {TOK_SKIP, 0x30, 0x00}, /* Reserved */ > > + {TOK_SKIP, 0x31, 0x00}, /* Reserved */ > > + {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, /* HS, VS active > high */ > > + {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, /* 10-bit BT.656 */ > > + {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, /* Enable clk & data > */ > > + {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, /* Enable AVID & FLD > */ > > + {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, /* Enable VS & HS */ > > + {TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF}, > > + {TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF}, > > + {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, /* Clear status */ > > + {TOK_TERM, 0, 0}, > > +}; > > + > > +/* List of image formats supported by TVP5146/47 decoder > > + * Currently we are using 8 bit mode only, but can be > > + * extended to 10/20 bit mode. > > + */ > > +static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { > > + { > > + .index = 0, > > + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, > > + .flags = 0, > > + .description = "8-bit UYVY 4:2:2 Format", > > + .pixelformat = V4L2_PIX_FMT_UYVY, > > + }, > > +}; > > + > > +#define TVP514X_NUM_FORMATS > ARRAY_SIZE(tvp514x_fmt_list) > > + > > +/* > > + * Supported standards - > > + * > > + * Currently supports two standards only, need to add support for > > rest of the + * modes, like SECAM, etc... > > + */ > > +static struct tvp514x_std_info tvp514x_std_list[] = { > > + /* Standard: STD_NTSC_MJ */ > > + [STD_NTSC_MJ] = { > > + .width = NTSC_NUM_ACTIVE_PIXELS, > > + .height = NTSC_NUM_ACTIVE_LINES, > > + .video_std = VIDEO_STD_NTSC_MJ_BIT, > > + .standard = { > > + .index = 0, > > + .id = V4L2_STD_NTSC, > > + .name = "NTSC", > > + .frameperiod = {1001, 30000}, > > + .framelines = 525 > > + }, > > + /* Standard: STD_PAL_BDGHIN */ > > + }, > > + [STD_PAL_BDGHIN] = { > > + .width = PAL_NUM_ACTIVE_PIXELS, > > + .height = PAL_NUM_ACTIVE_LINES, > > + .video_std = VIDEO_STD_PAL_BDGHIN_BIT, > > + .standard = { > > + .index = 1, > > + .id = V4L2_STD_PAL, > > + .name = "PAL", > > + .frameperiod = {1, 25}, > > + .framelines = 625 > > + }, > > + }, > > + /* Standard: need to add for additional standard */ > > +}; > > + > > +#define TVP514X_NUM_STANDARDS > ARRAY_SIZE(tvp514x_std_list) > > + > > +/* Supported controls */ > > +static const struct tvp514x_ctrl_info tvp514x_ctrl_list[] = { > > + { > > + .reg_address = REG_BRIGHTNESS, > > + .query_ctrl = { > > + .id = V4L2_CID_BRIGHTNESS, > > + .name = "BRIGHTNESS", > > + .type = V4L2_CTRL_TYPE_INTEGER, > > + .minimum = 0, > > + .maximum = 255, > > + .step = 1, > > + .default_value = 128 > > + }, > > + }, { > > + .reg_address = REG_CONTRAST, > > + .query_ctrl = { > > + .id = V4L2_CID_CONTRAST, > > + .name = "CONTRAST", > > + .type = V4L2_CTRL_TYPE_INTEGER, > > + .minimum = 0, > > + .maximum = 255, > > + .step = 1, > > + .default_value = 128 > > + }, > > + }, { > > + .reg_address = REG_SATURATION, > > + .query_ctrl = { > > + .id = V4L2_CID_SATURATION, > > + .name = "SATURATION", > > + .type = V4L2_CTRL_TYPE_INTEGER, > > + .minimum = 0, > > + .maximum = 255, > > + .step = 1, > > + .default_value = 128 > > + }, > > + }, { > > + .reg_address = REG_HUE, > > + .query_ctrl = { > > + .id = V4L2_CID_HUE, > > + .name = "HUE", > > + .type = V4L2_CTRL_TYPE_INTEGER, > > + .minimum = -180, > > + .maximum = 180, > > + .step = 180, > > + .default_value = 0 > > + }, > > + }, { > > + .reg_address = REG_AFE_GAIN_CTRL, > > + .query_ctrl = { > > + .id = V4L2_CID_AUTOGAIN, > > + .name = "Automatic Gain Control", > > + .type = V4L2_CTRL_TYPE_BOOLEAN, > > + .minimum = 0, > > + .maximum = 1, > > + .step = 1, > > + .default_value = 1 > > + }, > > + }, > > +}; > > + > > +#define TVP514X_NUM_CONTROLS > ARRAY_SIZE(tvp514x_ctrl_list) > > + > > +/* > > + * Read a value from a register in an TVP5146/47 decoder device. > > + * Returns value read if successful, or non-zero (-1) otherwise. > > + */ > > +static int tvp514x_read_reg(struct i2c_client *client, u8 reg) > > +{ > > + int err; > > + int retry = 0; > > +read_again: > > + > > + err = i2c_smbus_read_byte_data(client, reg); > > + if (err == -1) { > > + if (retry <= I2C_RETRY_COUNT) { > > + v4l_warn(client, "Read: retry ... %d\n", retry); > > + retry++; > > + msleep_interruptible(10); > > + goto read_again; > > + } > > + } > > + > > + return err; > > +} > > + > > +/* > > + * Write a value to a register in an TVP5146/47 decoder device. > > + * Returns zero if successful, or non-zero otherwise. > > + */ > > +static int tvp514x_write_reg(struct i2c_client *client, u8 reg, > u8 > > val) +{ > > + int err; > > + int retry = 0; > > +write_again: > > + > > + err = i2c_smbus_write_byte_data(client, reg, val); > > + if (err) { > > + if (retry <= I2C_RETRY_COUNT) { > > + v4l_warn(client, "Write: retry ... %d\n", retry); > > + retry++; > > + msleep_interruptible(10); > > + goto write_again; > > + } > > + } > > + > > + return err; > > +} > > + > > +/* > > + * tvp514x_write_regs : Initializes a list of TVP5146/47 > registers > > + * if token is TOK_TERM, then entire write operation > terminates > > + * if token is TOK_DELAY, then a delay of 'val' msec is > introduced > > + * if token is TOK_SKIP, then the register write is skipped > > + * if token is TOK_WRITE, then the register write is > performed > > + * > > + * reglist - list of registers to be written > > + * Returns zero if successful, or non-zero otherwise. > > + */ > > +static int tvp514x_write_regs(struct i2c_client *client, > > + const struct tvp514x_reg reglist[]) > > +{ > > + int err; > > + const struct tvp514x_reg *next = reglist; > > + > > + for (; next->token != TOK_TERM; next++) { > > + if (next->token == TOK_DELAY) { > > + msleep(next->val); > > + continue; > > + } > > + > > + if (next->token == TOK_SKIP) > > + continue; > > + > > + err = tvp514x_write_reg(client, next->reg, (u8) next- > >val); > > + if (err) { > > + v4l_err(client, "Write failed. Err[%d]\n", err); > > + return err; > > + } > > + } > > + return 0; > > +} > > + > > +/* > > + * tvp514x_get_current_std: > > + * Returns the current standard detected by TVP5146/47 > > + */ > > +static enum tvp514x_std tvp514x_get_current_std(struct > > tvp514x_decoder + *decoder) > > +{ > > + u8 std, std_status; > > + > > + std = tvp514x_read_reg(decoder->client, REG_VIDEO_STD); > > + if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) { > > + /* use the standard status register */ > > + std_status = tvp514x_read_reg(decoder->client, > > + REG_VIDEO_STD_STATUS); > > + } else > > + std_status = std; /* use the standard register itself */ > > + > > + switch (std_status & VIDEO_STD_MASK) { > > + case VIDEO_STD_NTSC_MJ_BIT: > > + return STD_NTSC_MJ; > > + > > + case VIDEO_STD_PAL_BDGHIN_BIT: > > + return STD_PAL_BDGHIN; > > + > > + default: > > + return STD_INVALID; > > + } > > + > > + return STD_INVALID; > > +} > > + > > +/* > > + * TVP5146/47 register dump function > > + */ > > +void tvp514x_reg_dump(struct tvp514x_decoder *decoder) > > +{ > > + u8 value; > > + > > + dump_reg(decoder->client, REG_INPUT_SEL, value); > > + dump_reg(decoder->client, REG_AFE_GAIN_CTRL, value); > > + dump_reg(decoder->client, REG_VIDEO_STD, value); > > + dump_reg(decoder->client, REG_OPERATION_MODE, value); > > + dump_reg(decoder->client, REG_COLOR_KILLER, value); > > + dump_reg(decoder->client, REG_LUMA_CONTROL1, value); > > + dump_reg(decoder->client, REG_LUMA_CONTROL2, value); > > + dump_reg(decoder->client, REG_LUMA_CONTROL3, value); > > + dump_reg(decoder->client, REG_BRIGHTNESS, value); > > + dump_reg(decoder->client, REG_CONTRAST, value); > > + dump_reg(decoder->client, REG_SATURATION, value); > > + dump_reg(decoder->client, REG_HUE, value); > > + dump_reg(decoder->client, REG_CHROMA_CONTROL1, value); > > + dump_reg(decoder->client, REG_CHROMA_CONTROL2, value); > > + dump_reg(decoder->client, REG_COMP_PR_SATURATION, value); > > + dump_reg(decoder->client, REG_COMP_Y_CONTRAST, value); > > + dump_reg(decoder->client, REG_COMP_PB_SATURATION, value); > > + dump_reg(decoder->client, REG_COMP_Y_BRIGHTNESS, value); > > + dump_reg(decoder->client, REG_AVID_START_PIXEL_LSB, value); > > + dump_reg(decoder->client, REG_AVID_START_PIXEL_MSB, value); > > + dump_reg(decoder->client, REG_AVID_STOP_PIXEL_LSB, value); > > + dump_reg(decoder->client, REG_AVID_STOP_PIXEL_MSB, value); > > + dump_reg(decoder->client, REG_HSYNC_START_PIXEL_LSB, value); > > + dump_reg(decoder->client, REG_HSYNC_START_PIXEL_MSB, value); > > + dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_LSB, value); > > + dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_MSB, value); > > + dump_reg(decoder->client, REG_VSYNC_START_LINE_LSB, value); > > + dump_reg(decoder->client, REG_VSYNC_START_LINE_MSB, value); > > + dump_reg(decoder->client, REG_VSYNC_STOP_LINE_LSB, value); > > + dump_reg(decoder->client, REG_VSYNC_STOP_LINE_MSB, value); > > + dump_reg(decoder->client, REG_VBLK_START_LINE_LSB, value); > > + dump_reg(decoder->client, REG_VBLK_START_LINE_MSB, value); > > + dump_reg(decoder->client, REG_VBLK_STOP_LINE_LSB, value); > > + dump_reg(decoder->client, REG_VBLK_STOP_LINE_MSB, value); > > + dump_reg(decoder->client, REG_SYNC_CONTROL, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER1, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER2, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER3, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER4, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER5, value); > > + dump_reg(decoder->client, REG_OUTPUT_FORMATTER6, value); > > + dump_reg(decoder->client, REG_CLEAR_LOST_LOCK, value); > > +} > > + > > +/* > > + * Configure the TVP5146/47 with the current register settings > > + * Returns zero if successful, or non-zero otherwise. > > + */ > > +static int tvp514x_configure(struct tvp514x_decoder *decoder) > > +{ > > + int err; > > + > > + /* common register initialization */ > > + err = > > + tvp514x_write_regs(decoder->client, tvp514x_reg_list); > > + if (err) > > + return err; > > + > > + if (debug) > > + tvp514x_reg_dump(decoder); > > + > > + return 0; > > +} > > + > > +/* > > + * Detect if an tvp514x is present, and if so which revision. > > + * A device is considered to be detected if the chip ID (LSB and > > MSB) + * registers match the expected values. > > + * Any value of the rom version register is accepted. > > + * Returns ENODEV error number if no device is detected, or zero > > + * if a device is detected. > > + */ > > +static int tvp514x_detect(struct tvp514x_decoder *decoder) > > +{ > > + u8 chip_id_msb, chip_id_lsb, rom_ver; > > + > > + chip_id_msb = tvp514x_read_reg(decoder->client, > REG_CHIP_ID_MSB); > > + chip_id_lsb = tvp514x_read_reg(decoder->client, > REG_CHIP_ID_LSB); > > + rom_ver = tvp514x_read_reg(decoder->client, REG_ROM_VERSION); > > + > > + v4l_dbg(1, debug, decoder->client, > > + "chip id detected msb:0x%x lsb:0x%x rom > version:0x%x\n", > > + chip_id_msb, chip_id_lsb, rom_ver); > > + if ((chip_id_msb != TVP514X_CHIP_ID_MSB) > > + || ((chip_id_lsb != TVP5146_CHIP_ID_LSB) > > + && (chip_id_lsb != TVP5147_CHIP_ID_LSB))) { > > + /* We didn't read the values we expected, so this must > not be > > + * an TVP5146/47. > > + */ > > + v4l_err(decoder->client, > > + "chip id mismatch msb:0x%x lsb:0x%x\n", > > + chip_id_msb, chip_id_lsb); > > + return -ENODEV; > > + } > > + > > + decoder->ver = rom_ver; > > + decoder->state = STATE_DETECTED; > > + > > + v4l_info(decoder->client, > > + "\n%s found at 0x%x (%s)\n", decoder->client- > >name, > > + decoder->client->addr << 1, > > + decoder->client->adapter->name); > > + return 0; > > +} > > + > > +/* > > + * Following are decoder interface functions implemented by > > + * TVP5146/47 decoder driver. > > + */ > > + > > +/** > > + * ioctl_querystd - V4L2 decoder interface handler for > > VIDIOC_QUERYSTD ioctl + * @s: pointer to standard V4L2 device > > structure > > + * @std_id: standard V4L2 std_id ioctl enum > > + * > > + * Returns the current standard detected by TVP5146/47. If no > active > > input is + * detected, returns -EINVAL > > + */ > > +static int ioctl_querystd(struct v4l2_int_device *s, v4l2_std_id > > *std_id) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + enum tvp514x_std current_std; > > + enum tvp514x_input input_sel; > > + u8 sync_lock_status, lock_mask; > > + > > + if (std_id == NULL) > > + return -EINVAL; > > + > > + /* get the current standard */ > > + current_std = tvp514x_get_current_std(decoder); > > + if (current_std == STD_INVALID) > > + return -EINVAL; > > + > > + input_sel = > > decoder->pdata->input_list[decoder->inputidx].input_sel; + > > + switch (input_sel) { > > + case INPUT_CVBS_VI1A: > > + case INPUT_CVBS_VI1B: > > + case INPUT_CVBS_VI1C: > > + case INPUT_CVBS_VI2A: > > + case INPUT_CVBS_VI2B: > > + case INPUT_CVBS_VI2C: > > + case INPUT_CVBS_VI3A: > > + case INPUT_CVBS_VI3B: > > + case INPUT_CVBS_VI3C: > > + case INPUT_CVBS_VI4A: > > + lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | > > + STATUS_HORZ_SYNC_LOCK_BIT | > > + STATUS_VIRT_SYNC_LOCK_BIT; > > + break; > > + > > + case INPUT_SVIDEO_VI2A_VI1A: > > + case INPUT_SVIDEO_VI2B_VI1B: > > + case INPUT_SVIDEO_VI2C_VI1C: > > + case INPUT_SVIDEO_VI2A_VI3A: > > + case INPUT_SVIDEO_VI2B_VI3B: > > + case INPUT_SVIDEO_VI2C_VI3C: > > + case INPUT_SVIDEO_VI4A_VI1A: > > + case INPUT_SVIDEO_VI4A_VI1B: > > + case INPUT_SVIDEO_VI4A_VI1C: > > + case INPUT_SVIDEO_VI4A_VI3A: > > + case INPUT_SVIDEO_VI4A_VI3B: > > + case INPUT_SVIDEO_VI4A_VI3C: > > + lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | > > + STATUS_VIRT_SYNC_LOCK_BIT; > > + break; > > + /*Need to add other interfaces*/ > > + default: > > + return -EINVAL; > > + } > > + /* check whether signal is locked */ > > + sync_lock_status = tvp514x_read_reg(decoder->client, > REG_STATUS1); > > + if (lock_mask != (sync_lock_status & lock_mask)) > > + return -EINVAL; /* No input detected */ > > + > > + decoder->current_std = current_std; > > + *std_id = decoder->std_list[current_std].standard.id; > > + > > + v4l_dbg(1, debug, decoder->client, "Current STD: %s", > > + decoder->std_list[current_std].standard.name); > > + return 0; > > +} > > + > > +/** > > + * ioctl_s_std - V4L2 decoder interface handler for VIDIOC_S_STD > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @std_id: standard V4L2 v4l2_std_id ioctl enum > > + * > > + * If std_id is supported, sets the requested standard. > Otherwise, > > returns + * -EINVAL > > + */ > > +static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id > > *std_id) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err, i; > > + > > + if (std_id == NULL) > > + return -EINVAL; > > + > > + for (i = 0; i < decoder->num_stds; i++) > > + if (*std_id & decoder->std_list[i].standard.id) > > + break; > > + > > + if ((i == decoder->num_stds) || (i == STD_INVALID)) > > + return -EINVAL; > > + > > + err = tvp514x_write_reg(decoder->client, REG_VIDEO_STD, > > + decoder->std_list[i].video_std); > > + if (err) > > + return err; > > + > > + decoder->current_std = i; > > + tvp514x_reg_list[REG_VIDEO_STD].val = > > decoder->std_list[i].video_std; + > > + v4l_dbg(1, debug, decoder->client, "Standard set to: %s", > > + decoder->std_list[i].standard.name); > > + return 0; > > +} > > + > > +/** > > + * ioctl_s_routing - V4L2 decoder interface handler for > > VIDIOC_S_INPUT ioctl + * @s: pointer to standard V4L2 device > > structure > > + * @index: number of the input > > + * > > + * If index is valid, selects the requested input. Otherwise, > > returns -EINVAL if + * the input is not supported or there is no > > active signal present in the + * selected input. > > + */ > > +static int ioctl_s_routing(struct v4l2_int_device *s, int index) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err; > > + enum tvp514x_input input_sel; > > + enum tvp514x_std current_std = STD_INVALID; > > + u8 sync_lock_status, lock_mask; > > + int try_count = LOCK_RETRY_COUNT; > > + > > + if ((index >= decoder->pdata->num_inputs) || (index < 0)) > > + return -EINVAL; /* Index out of bound */ > > + > > + /* Get the register value to be written to select the > requested > > input */ + input_sel = decoder->pdata- > >input_list[index].input_sel; > > + err = tvp514x_write_reg(decoder->client, REG_INPUT_SEL, > input_sel); > > + if (err) > > + return err; > > + > > + decoder->inputidx = index; > > + tvp514x_reg_list[REG_INPUT_SEL].val = input_sel; > > + > > + /* Clear status */ > > + msleep(LOCK_RETRY_DELAY); > > + err = > > + tvp514x_write_reg(decoder->client, REG_CLEAR_LOST_LOCK, > 0x01); > > + if (err) > > + return err; > > + > > + switch (input_sel) { > > + case INPUT_CVBS_VI1A: > > + case INPUT_CVBS_VI1B: > > + case INPUT_CVBS_VI1C: > > + case INPUT_CVBS_VI2A: > > + case INPUT_CVBS_VI2B: > > + case INPUT_CVBS_VI2C: > > + case INPUT_CVBS_VI3A: > > + case INPUT_CVBS_VI3B: > > + case INPUT_CVBS_VI3C: > > + case INPUT_CVBS_VI4A: > > + lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | > > + STATUS_HORZ_SYNC_LOCK_BIT | > > + STATUS_VIRT_SYNC_LOCK_BIT; > > + break; > > + > > + case INPUT_SVIDEO_VI2A_VI1A: > > + case INPUT_SVIDEO_VI2B_VI1B: > > + case INPUT_SVIDEO_VI2C_VI1C: > > + case INPUT_SVIDEO_VI2A_VI3A: > > + case INPUT_SVIDEO_VI2B_VI3B: > > + case INPUT_SVIDEO_VI2C_VI3C: > > + case INPUT_SVIDEO_VI4A_VI1A: > > + case INPUT_SVIDEO_VI4A_VI1B: > > + case INPUT_SVIDEO_VI4A_VI1C: > > + case INPUT_SVIDEO_VI4A_VI3A: > > + case INPUT_SVIDEO_VI4A_VI3B: > > + case INPUT_SVIDEO_VI4A_VI3C: > > + lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | > > + STATUS_VIRT_SYNC_LOCK_BIT; > > + break; > > + /*Need to add other interfaces*/ > > + default: > > + return -EINVAL; > > + } > > + > > + while (try_count-- > 0) { > > + /* Allow decoder to sync up with new input */ > > + msleep(LOCK_RETRY_DELAY); > > + > > + /* get the current standard for future reference */ > > + current_std = tvp514x_get_current_std(decoder); > > + if (current_std == STD_INVALID) > > + continue; > > + > > + sync_lock_status = tvp514x_read_reg(decoder->client, > > + REG_STATUS1); > > + if (lock_mask == (sync_lock_status & lock_mask)) > > + break; /* Input detected */ > > + } > > + > > + if ((current_std == STD_INVALID) || (try_count < 0)) > > + return -EINVAL; > > + > > + decoder->current_std = current_std; > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Input set to: index - %d (%s)", > > + decoder->pdata->input_list[index].input.index, > > + decoder->pdata->input_list[index].input.name); > > + return 0; > > +} > > + > > +/** > > + * ioctl_g_routing - V4L2 decoder interface handler for > > VIDIOC_G_INPUT ioctl + * @s: pointer to standard V4L2 device > > structure > > + * @index: returns the current selected input > > + * > > + * Returns the current selected input. Returns -EINVAL if any > error > > occurs + */ > > +static int ioctl_g_routing(struct v4l2_int_device *s, int *index) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err = -EINVAL, i, inputidx; > > + > > + if (index == NULL) > > + return err; > > + > > + /* Search through the input list for active inputs */ > > + inputidx = decoder->inputidx; > > + for (i = 0; i < decoder->pdata->num_inputs; i++) { > > + inputidx++; /* Move to next input */ > > + if (inputidx >= decoder->pdata->num_inputs) > > + inputidx = 0; /* fall back to first input */ > > + > > + err = ioctl_s_routing(s, inputidx); > > + if (!err) { > > + /* Active input found - select it and return > success */ > > + *index = inputidx; > > + return 0; > > + } > > + } > > + > > + return err; > > +} > > + > > +/** > > + * ioctl_queryctrl - V4L2 decoder interface handler for > > VIDIOC_QUERYCTRL ioctl + * @s: pointer to standard V4L2 device > > structure > > + * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure > > + * > > + * If the requested control is supported, returns the control > > information + * from the ctrl_list[] array. Otherwise, returns > > -EINVAL if the + * control is not supported. > > + */ > > +static int > > +ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl > > *qctrl) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int id, index; > > + const struct tvp514x_ctrl_info *control = NULL; > > + > > + if (qctrl == NULL) > > + return -EINVAL; > > + > > + id = qctrl->id; > > + memset(qctrl, 0, sizeof(struct v4l2_queryctrl)); > > + qctrl->id = id; > > + > > + for (index = 0; index < decoder->num_ctrls; index++) { > > + control = &decoder->ctrl_list[index]; > > + if (control->query_ctrl.id == qctrl->id) > > + break; /* Match found */ > > + } > > + if (index == decoder->num_ctrls) > > + return -EINVAL; /* Index out of bound */ > > + > > + memcpy(qctrl, &control->query_ctrl, sizeof(struct > v4l2_queryctrl)); > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Query Control: %s : Min - %d, Max - %d, Def - > %d", > > + control->query_ctrl.name, > > + control->query_ctrl.minimum, > > + control->query_ctrl.maximum, > > + control->query_ctrl.default_value); > > + return 0; > > +} > > + > > +/** > > + * ioctl_g_ctrl - V4L2 decoder interface handler for > VIDIOC_G_CTRL > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure > > + * > > + * If the requested control is supported, returns the control's > > current + * value from the decoder. Otherwise, returns -EINVAL if > the > > control is not + * supported. > > + */ > > +static int > > +ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control > *ctrl) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int index, value; > > + const struct tvp514x_ctrl_info *control = NULL; > > + > > + if (ctrl == NULL) > > + return -EINVAL; > > + > > + for (index = 0; index < decoder->num_ctrls; index++) { > > + control = &decoder->ctrl_list[index]; > > + if (control->query_ctrl.id == ctrl->id) > > + break; /* Match found */ > > + } > > + if (index == decoder->num_ctrls) > > + return -EINVAL; /* Index out of bound */ > > + > > + value = > > + tvp514x_read_reg(decoder->client, control->reg_address); > > + > > + /* cross check */ > > + if (value != tvp514x_reg_list[control->reg_address].val) > > + return -EINVAL; /* Driver & TVP5146/47 setting > mismatch */ > > + > > + if (V4L2_CID_AUTOGAIN == ctrl->id) { > > + if ((value & 0x3) == 3) > > + value = 1; > > + else > > + value = 0; > > + } > > + > > + if (V4L2_CID_HUE == ctrl->id) { > > + if (value == 0x7F) > > + value = 180; > > + else if (value == 0x80) > > + value = -180; > > + else > > + value = 0; > > + } > > + > > + ctrl->value = value; > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Get Cotrol: %s - %d", > > + control->query_ctrl.name, value); > > + return 0; > > +} > > + > > +/** > > + * ioctl_s_ctrl - V4L2 decoder interface handler for > VIDIOC_S_CTRL > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure > > + * > > + * If the requested control is supported, sets the control's > current > > + * value in HW. Otherwise, returns -EINVAL if the control is not > > supported. + */ > > +static int > > +ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control > *ctrl) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err, value, index; > > + const struct tvp514x_ctrl_info *control = NULL; > > + > > + if (ctrl == NULL) > > + return -EINVAL; > > + > > + value = (__s32) ctrl->value; > > + for (index = 0; index < decoder->num_ctrls; index++) { > > + control = &decoder->ctrl_list[index]; > > + if (control->query_ctrl.id == ctrl->id) > > + break; /* Match found */ > > + } > > + if (index == decoder->num_ctrls) > > + return -EINVAL; /* Index out of bound */ > > + > > + if (V4L2_CID_AUTOGAIN == ctrl->id) { > > + if (value == 1) > > + value = 0x0F; > > + else if (value == 0) > > + value = 0x0C; > > + else > > + return -ERANGE; > > + } else if (V4L2_CID_HUE == ctrl->id) { > > + if (value == 180) > > + value = 0x7F; > > + else if (value == -180) > > + value = 0x80; > > + else if (value == 0) > > + value = 0; > > + else > > + return -ERANGE; > > + } else { > > + if ((value < control->query_ctrl.minimum) > > + || (value > control->query_ctrl.maximum)) > > + return -ERANGE; > > + } > > + > > + err = > > + tvp514x_write_reg(decoder->client, control->reg_address, > > + value); > > + if (err) > > + return err; > > + > > + tvp514x_reg_list[control->reg_address].val = value; > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Set Cotrol: %s - %d", > > + control->query_ctrl.name, value); > > + return err; > > +} > > + > > +/** > > + * ioctl_enum_fmt_cap - Implement the CAPTURE buffer > VIDIOC_ENUM_FMT > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure > > + * > > + * Implement the VIDIOC_ENUM_FMT ioctl to enumerate supported > > formats + */ > > +static int > > +ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc > > *fmt) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int index; > > + > > + if (fmt == NULL) > > + return -EINVAL; > > + > > + index = fmt->index; > > + if ((index >= decoder->num_fmts) || (index < 0)) > > + return -EINVAL; /* Index out of bound */ > > + > > + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; /* only capture is supported */ > > + > > + memcpy(fmt, &decoder->fmt_list[index], > > + sizeof(struct v4l2_fmtdesc)); > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Current FMT: index - %d (%s)", > > + decoder->fmt_list[index].index, > > + decoder->fmt_list[index].description); > > + return 0; > > +} > > + > > +/** > > + * ioctl_try_fmt_cap - Implement the CAPTURE buffer > VIDIOC_TRY_FMT > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure > > + * > > + * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer > type. > > This + * ioctl is used to negotiate the image capture size and > pixel > > format + * without actually making it take effect. > > + */ > > +static int > > +ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format > *f) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int ifmt; > > + struct v4l2_pix_format *pix; > > + enum tvp514x_std current_std; > > + > > + if (f == NULL) > > + return -EINVAL; > > + > > + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > > + > > + pix = &f->fmt.pix; > > + > > + /* Calculate height and width based on current standard */ > > + current_std = tvp514x_get_current_std(decoder); > > + if (current_std == STD_INVALID) > > + return -EINVAL; > > + > > + decoder->current_std = current_std; > > + pix->width = decoder->std_list[current_std].width; > > + pix->height = decoder->std_list[current_std].height; > > + > > + for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) { > > + if (pix->pixelformat == > > + decoder->fmt_list[ifmt].pixelformat) > > + break; > > + } > > + if (ifmt == decoder->num_fmts) > > + ifmt = 0; /* None of the format matched, select > default */ > > + pix->pixelformat = decoder->fmt_list[ifmt].pixelformat; > > + > > + pix->field = V4L2_FIELD_INTERLACED; > > + pix->bytesperline = pix->width * 2; > > + pix->sizeimage = pix->bytesperline * pix->height; > > + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; > > + pix->priv = 0; > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Try FMT: pixelformat - %s, bytesperline - %d" > > + "Width - %d, Height - %d", > > + decoder->fmt_list[ifmt].description, pix- > >bytesperline, > > + pix->width, pix->height); > > + return 0; > > +} > > + > > +/** > > + * ioctl_s_fmt_cap - V4L2 decoder interface handler for > VIDIOC_S_FMT > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure > > + * > > + * If the requested format is supported, configures the HW to use > > that + * format, returns error code if format not supported or HW > > can't be + * correctly configured. > > + */ > > +static int > > +ioctl_s_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + struct v4l2_pix_format *pix; > > + int rval; > > + > > + if (f == NULL) > > + return -EINVAL; > > + > > + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; /* only capture is supported */ > > + > > + pix = &f->fmt.pix; > > + rval = ioctl_try_fmt_cap(s, f); > > + if (rval) > > + return rval; > > + else > > + decoder->pix = *pix; > > + > > + return rval; > > +} > > + > > +/** > > + * ioctl_g_fmt_cap - V4L2 decoder interface handler for > > ioctl_g_fmt_cap + * @s: pointer to standard V4L2 device structure > > + * @f: pointer to standard V4L2 v4l2_format structure > > + * > > + * Returns the decoder's current pixel format in the v4l2_format > > + * parameter. > > + */ > > +static int > > +ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + > > + if (f == NULL) > > + return -EINVAL; > > + > > + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; /* only capture is supported */ > > + > > + f->fmt.pix = decoder->pix; > > + > > + v4l_dbg(1, debug, decoder->client, > > + "Current FMT: bytesperline - %d" > > + "Width - %d, Height - %d", > > + decoder->pix.bytesperline, > > + decoder->pix.width, decoder->pix.height); > > + return 0; > > +} > > + > > +/** > > + * ioctl_g_parm - V4L2 decoder interface handler for > VIDIOC_G_PARM > > ioctl + * @s: pointer to standard V4L2 device structure > > + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure > > + * > > + * Returns the decoder's video CAPTURE parameters. > > + */ > > +static int > > +ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm > *a) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + struct v4l2_captureparm *cparm; > > + enum tvp514x_std current_std; > > + > > + if (a == NULL) > > + return -EINVAL; > > + > > + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; /* only capture is supported */ > > + > > + memset(a, 0, sizeof(*a)); > > + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > > + > > + /* get the current standard */ > > + current_std = tvp514x_get_current_std(decoder); > > + if (current_std == STD_INVALID) > > + return -EINVAL; > > + > > + decoder->current_std = current_std; > > + > > + cparm = &a->parm.capture; > > + cparm->capability = V4L2_CAP_TIMEPERFRAME; > > + cparm->timeperframe = > > + decoder->std_list[current_std].standard.frameperiod; > > + > > + return 0; > > +} > > + > > +/** > > + * ioctl_s_parm - V4L2 decoder interface handler for > VIDIOC_S_PARM > > ioctl + * @s: pointer to standard V4L2 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 > > +ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm > *a) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + struct v4l2_fract *timeperframe; > > + enum tvp514x_std current_std; > > + > > + if (a == NULL) > > + return -EINVAL; > > + > > + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; /* only capture is supported */ > > + > > + timeperframe = &a->parm.capture.timeperframe; > > + > > + /* get the current standard */ > > + current_std = tvp514x_get_current_std(decoder); > > + if (current_std == STD_INVALID) > > + return -EINVAL; > > + > > + decoder->current_std = current_std; > > + > > + *timeperframe = > > + decoder->std_list[current_std].standard.frameperiod; > > + > > + return 0; > > +} > > + > > +/** > > + * ioctl_g_ifparm - V4L2 decoder interface handler for > > vidioc_int_g_ifparm_num + * @s: pointer to standard V4L2 device > > structure > > + * @p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl > > structure + * > > + * Gets slave interface parameters. > > + * Calculates the required xclk value to support the requested > > + * clock parameters in p. This value is returned in the p > > + * parameter. > > + */ > > +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct > > v4l2_ifparm *p) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int rval; > > + > > + if (p == NULL) > > + return -EINVAL; > > + > > + if (NULL == decoder->pdata->ifparm) > > + return -EINVAL; > > + > > + rval = decoder->pdata->ifparm(p); > > + if (rval) { > > + v4l_err(decoder->client, "g_ifparm.Err[%d]\n", rval); > > + return rval; > > + } > > + > > + p->u.bt656.clock_curr = TVP514X_XCLK_BT656; > > + > > + return 0; > > +} > > + > > +/** > > + * ioctl_g_priv - V4L2 decoder interface handler for > > vidioc_int_g_priv_num + * @s: pointer to standard V4L2 device > > structure > > + * @p: void pointer to hold decoder's private data address > > + * > > + * Returns device's (decoder's) private data area address in p > > parameter + */ > > +static int ioctl_g_priv(struct v4l2_int_device *s, void *p) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + > > + if (NULL == decoder->pdata->priv_data_set) > > + return -EINVAL; > > + > > + return decoder->pdata->priv_data_set(p); > > +} > > + > > +/** > > + * ioctl_s_power - V4L2 decoder interface handler for > > vidioc_int_s_power_num + * @s: pointer to standard V4L2 device > > structure > > + * @on: power state to which device is to be set > > + * > > + * Sets devices power state to requrested state, if possible. > > + */ > > +static int ioctl_s_power(struct v4l2_int_device *s, enum > v4l2_power > > on) +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err = 0; > > + > > + switch (on) { > > + case V4L2_POWER_OFF: > > + /* Power Down Sequence */ > > + err = > > + tvp514x_write_reg(decoder->client, > REG_OPERATION_MODE, > > + 0x01); > > + /* Disable mux for TVP5146/47 decoder data path */ > > + if (decoder->pdata->power_set) > > + err |= decoder->pdata->power_set(on); > > + decoder->state = STATE_NOT_DETECTED; > > + break; > > + > > + case V4L2_POWER_STANDBY: > > + if (decoder->pdata->power_set) > > + err = decoder->pdata->power_set(on); > > + break; > > + > > + case V4L2_POWER_ON: > > + /* Enable mux for TVP5146/47 decoder data path */ > > + if ((decoder->pdata->power_set) && > > + (decoder->state == STATE_NOT_DETECTED)) { > > + int i; > > + struct tvp514x_init_seq *int_seq = > > + (struct tvp514x_init_seq *) > > + decoder->id->driver_data; > > + > > + err = decoder->pdata->power_set(on); > > + > > + /* Power Up Sequence */ > > + for (i = 0; i < int_seq->no_regs; i++) { > > + err |= tvp514x_write_reg(decoder->client, > > + int_seq->init_reg_seq[i].reg, > > + int_seq->init_reg_seq[i].val); > > + } > > + /* Detect the sensor is not already detected */ > > + err |= tvp514x_detect(decoder); > > + if (err) { > > + v4l_err(decoder->client, > > + "Unable to detect decoder\n"); > > + return err; > > + } > > + } > > + err |= tvp514x_configure(decoder); > > + break; > > + > > + default: > > + err = -ENODEV; > > + break; > > + } > > + > > + return err; > > +} > > + > > +/** > > + * ioctl_init - V4L2 decoder interface handler for > VIDIOC_INT_INIT > > + * @s: pointer to standard V4L2 device structure > > + * > > + * Initialize the decoder device (calls tvp514x_configure()) > > + */ > > +static int ioctl_init(struct v4l2_int_device *s) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + > > + /* Set default standard to auto */ > > + tvp514x_reg_list[REG_VIDEO_STD].val = > > + VIDEO_STD_AUTO_SWITCH_BIT; > > + > > + return tvp514x_configure(decoder); > > +} > > + > > +/** > > + * ioctl_dev_exit - V4L2 decoder interface handler for > > vidioc_int_dev_exit_num + * @s: pointer to standard V4L2 device > > structure > > + * > > + * Delinitialise the dev. at slave detach. The complement of > > ioctl_dev_init. + */ > > +static int ioctl_dev_exit(struct v4l2_int_device *s) > > +{ > > + return 0; > > +} > > + > > +/** > > + * ioctl_dev_init - V4L2 decoder interface handler for > > vidioc_int_dev_init_num + * @s: pointer to standard V4L2 device > > structure > > + * > > + * Initialise the device when slave attaches to the master. > Returns > > 0 if + * TVP5146/47 device could be found, otherwise returns > > appropriate error. + */ > > +static int ioctl_dev_init(struct v4l2_int_device *s) > > +{ > > + struct tvp514x_decoder *decoder = s->priv; > > + int err; > > + > > + err = tvp514x_detect(decoder); > > + if (err < 0) { > > + v4l_err(decoder->client, > > + "Unable to detect decoder\n"); > > + return err; > > + } > > + > > + v4l_info(decoder->client, > > + "chip version 0x%.2x detected\n", decoder->ver); > > + > > + return 0; > > +} > > + > > +static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = { > > + {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*) > ioctl_dev_init}, > > + {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func*) > ioctl_dev_exit}, > > + {vidioc_int_s_power_num, (v4l2_int_ioctl_func*) > ioctl_s_power}, > > + {vidioc_int_g_priv_num, (v4l2_int_ioctl_func*) ioctl_g_priv}, > > + {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) > ioctl_g_ifparm}, > > + {vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init}, > > + {vidioc_int_enum_fmt_cap_num, > > + (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, > > + {vidioc_int_try_fmt_cap_num, > > + (v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, > > + {vidioc_int_g_fmt_cap_num, > > + (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, > > + {vidioc_int_s_fmt_cap_num, > > + (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, > > + {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, > > + {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, > > + {vidioc_int_queryctrl_num, > > + (v4l2_int_ioctl_func *) ioctl_queryctrl}, > > + {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, > > + {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, > > + {vidioc_int_querystd_num, (v4l2_int_ioctl_func *) > ioctl_querystd}, > > + {vidioc_int_s_std_num, (v4l2_int_ioctl_func *) ioctl_s_std}, > > + {vidioc_int_g_video_routing_num, > > + (v4l2_int_ioctl_func *) ioctl_g_routing}, > > + {vidioc_int_s_video_routing_num, > > + (v4l2_int_ioctl_func *) ioctl_s_routing}, > > +}; > > + > > +static struct v4l2_int_slave tvp514x_slave = { > > + .ioctls = tvp514x_ioctl_desc, > > + .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), > > +}; > > + > > +static struct tvp514x_decoder tvp514x_dev = { > > + .state = STATE_NOT_DETECTED, > > + > > + .num_fmts = TVP514X_NUM_FORMATS, > > + .fmt_list = tvp514x_fmt_list, > > + > > + .pix = { /* Default to NTSC 8-bit YUV 422 */ > > + .width = NTSC_NUM_ACTIVE_PIXELS, > > + .height = NTSC_NUM_ACTIVE_LINES, > > + .pixelformat = V4L2_PIX_FMT_UYVY, > > + .field = V4L2_FIELD_INTERLACED, > > + .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, > > + .sizeimage = > > + NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES, > > + .colorspace = V4L2_COLORSPACE_SMPTE170M, > > + }, > > + > > + .current_std = STD_NTSC_MJ, > > + .num_stds = TVP514X_NUM_STANDARDS, > > + .std_list = tvp514x_std_list, > > + > > + .num_ctrls = TVP514X_NUM_CONTROLS, > > + .ctrl_list = tvp514x_ctrl_list, > > + > > +}; > > + > > +static struct v4l2_int_device tvp514x_int_device = { > > + .module = THIS_MODULE, > > + .name = MODULE_NAME, > > + .priv = &tvp514x_dev, > > + .type = v4l2_int_type_slave, > > + .u = { > > + .slave = &tvp514x_slave, > > + }, > > +}; > > + > > +/** > > + * tvp514x_probe - decoder driver i2c probe handler > > + * @client: i2c driver client device structure > > + * > > + * Register decoder as an i2c client device and V4L2 > > + * device. > > + */ > > +static int > > +tvp514x_probe(struct i2c_client *client, const struct > i2c_device_id > > *id) +{ > > + struct tvp514x_decoder *decoder = &tvp514x_dev; > > + int err; > > + > > + /* Check if the adapter supports the needed features */ > > + if (!i2c_check_functionality(client->adapter, > > I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; > > + > > + decoder->pdata = client->dev.platform_data; > > + if (!decoder->pdata) { > > + v4l_err(client, "No platform data\n!!"); > > + return -ENODEV; > > + } > > + /* > > + * Fetch platform specific data, and configure the > > + * tvp514x_reg_list[] accordingly. Since this is one > > + * time configuration, no need to preserve. > > + */ > > + decoder->inputidx = decoder->pdata->default_input; > > + tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |= > > + (decoder->pdata->clk_polarity << 1); > > + tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val |= > > + decoder->pdata->fmt; > > + tvp514x_reg_list[REG_SYNC_CONTROL].val |= > > + ((decoder->pdata->hs_polarity << 2) | > > + (decoder->pdata->vs_polarity << 3)); > > + /* > > + * Save the id data, required for power up sequence > > + */ > > + decoder->id = (struct i2c_device_id *)id; > > + /* Attach to Master */ > > + strcpy(tvp514x_int_device.u.slave->attach_to, > > decoder->pdata->master); + decoder->v4l2_int_device = > > &tvp514x_int_device; > > + decoder->client = client; > > + i2c_set_clientdata(client, decoder); > > + > > + /* Register with V4L2 layer as slave device */ > > + err = v4l2_int_device_register(decoder->v4l2_int_device); > > + if (err) { > > + i2c_set_clientdata(client, NULL); > > + v4l_err(client, > > + "Unable to register to v4l2. Err[%d]\n", err); > > + > > + } else > > + v4l_info(client, "Registered to v4l2 master %s!!\n", > > + decoder->pdata->master); > > + > > + return 0; > > +} > > + > > +/** > > + * tvp514x_remove - decoder driver i2c remove handler > > + * @client: i2c driver client device structure > > + * > > + * Unregister decoder as an i2c client device and V4L2 > > + * device. Complement of tvp514x_probe(). > > + */ > > +static int __exit tvp514x_remove(struct i2c_client *client) > > +{ > > + struct tvp514x_decoder *decoder = i2c_get_clientdata(client); > > + > > + if (!client->adapter) > > + return -ENODEV; /* our client isn't attached */ > > + > > + v4l2_int_device_unregister(decoder->v4l2_int_device); > > + i2c_set_clientdata(client, NULL); > > + > > + return 0; > > +} > > +/* > > + * TVP5146 Init/Power on Sequence > > + */ > > +static struct tvp514x_reg tvp5146_init_reg_seq[] = { > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, > > + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, > > + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, > > +}; > > +static struct tvp514x_init_seq tvp5146_init = { > > + .no_regs = ARRAY_SIZE(tvp5146_init_reg_seq), > > + .init_reg_seq = tvp5146_init_reg_seq, > > +}; > > +/* > > + * TVP5147 Init/Power on Sequence > > + */ > > +static struct tvp514x_reg tvp5147_init_reg_seq[] = { > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x16}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xA0}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x16}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, > > + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, > > + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, > > + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, > > + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, > > +}; > > +static struct tvp514x_init_seq tvp5147_init = { > > + .no_regs = ARRAY_SIZE(tvp5147_init_reg_seq), > > + .init_reg_seq = tvp5147_init_reg_seq, > > +}; > > +/* > > + * TVP5146M2/TVP5147M1 Init/Power on Sequence > > + */ > > +static struct tvp514x_reg tvp514xm_init_reg_seq[] = { > > + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, > > + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, > > +}; > > +static struct tvp514x_init_seq tvp514xm_init = { > > + .no_regs = ARRAY_SIZE(tvp514xm_init_reg_seq), > > + .init_reg_seq = tvp514xm_init_reg_seq, > > +}; > > +/* > > + * I2C Device Table - > > + * > > + * name - Name of the actual device/chip. > > + * driver_data - Driver data > > + */ > > +static const struct i2c_device_id tvp514x_id[] = { > > + {"tvp5146", (unsigned int)&tvp5146_init}, > > + {"tvp5146m2", (unsigned int)&tvp514xm_init}, > > + {"tvp5147", (unsigned int)&tvp5147_init}, > > + {"tvp5147m1", (unsigned int)&tvp514xm_init}, > > + {}, > > +}; > > + > > +MODULE_DEVICE_TABLE(i2c, tvp514x_id); > > + > > +static struct i2c_driver tvp514x_i2c_driver = { > > + .driver = { > > + .name = MODULE_NAME, > > + .owner = THIS_MODULE, > > + }, > > + .probe = tvp514x_probe, > > + .remove = __exit_p(tvp514x_remove), > > + .id_table = tvp514x_id, > > +}; > > + > > +/** > > + * tvp514x_init > > + * > > + * Module init function > > + */ > > +static int __init tvp514x_init(void) > > +{ > > + int err; > > + > > + err = i2c_add_driver(&tvp514x_i2c_driver); > > + if (err) { > > + printk(KERN_ERR "Failed to register " MODULE_NAME > ".\n"); > > + return err; > > + } > > + return 0; > > +} > > + > > +/** > > + * tvp514x_cleanup > > + * > > + * Module exit function > > + */ > > +static void __exit tvp514x_cleanup(void) > > +{ > > + i2c_del_driver(&tvp514x_i2c_driver); > > +} > > + > > +module_init(tvp514x_init); > > +module_exit(tvp514x_cleanup); > > + > > +MODULE_AUTHOR("Texas Instruments"); > > +MODULE_DESCRIPTION("TVP514X linux decoder driver"); > > +MODULE_LICENSE("GPL"); > > diff --git a/drivers/media/video/tvp514x_regs.h > > b/drivers/media/video/tvp514x_regs.h new file mode 100755 > > index 0000000..003a3c1 > > --- /dev/null > > +++ b/drivers/media/video/tvp514x_regs.h > > @@ -0,0 +1,292 @@ > > +/* > > + * drivers/media/video/tvp514x_regs.h > > + * > > + * Copyright (C) 2008 Texas Instruments Inc > > + * Author: Vaibhav Hiremath <hvaibhav@xxxxxx> > > + * > > + * Contributors: > > + * Sivaraj R <sivaraj@xxxxxx> > > + * Brijesh R Jadav <brijesh.j@xxxxxx> > > + * Hardik Shah <hardik.shah@xxxxxx> > > + * Manjunath Hadli <mrh@xxxxxx> > > + * Karicheri Muralidharan <m-karicheri2@xxxxxx> > > + * > > + * This package is free software; you can redistribute it and/or > > modify + * it under the terms of the GNU General Public License > > version 2 as + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be > useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public > License > > + * along with this program; if not, write to the Free Software > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > + * > > + */ > > + > > +#ifndef _TVP514X_REGS_H > > +#define _TVP514X_REGS_H > > + > > +/* > > + * TVP5146/47 registers > > + */ > > +#define REG_INPUT_SEL (0x00) > > +#define REG_AFE_GAIN_CTRL (0x01) > > +#define REG_VIDEO_STD (0x02) > > +#define REG_OPERATION_MODE (0x03) > > +#define REG_AUTOSWITCH_MASK (0x04) > > + > > +#define REG_COLOR_KILLER (0x05) > > +#define REG_LUMA_CONTROL1 (0x06) > > +#define REG_LUMA_CONTROL2 (0x07) > > +#define REG_LUMA_CONTROL3 (0x08) > > + > > +#define REG_BRIGHTNESS (0x09) > > +#define REG_CONTRAST (0x0A) > > +#define REG_SATURATION (0x0B) > > +#define REG_HUE (0x0C) > > + > > +#define REG_CHROMA_CONTROL1 (0x0D) > > +#define REG_CHROMA_CONTROL2 (0x0E) > > + > > +/* 0x0F Reserved */ > > + > > +#define REG_COMP_PR_SATURATION (0x10) > > +#define REG_COMP_Y_CONTRAST (0x11) > > +#define REG_COMP_PB_SATURATION (0x12) > > + > > +/* 0x13 Reserved */ > > + > > +#define REG_COMP_Y_BRIGHTNESS (0x14) > > + > > +/* 0x15 Reserved */ > > + > > +#define REG_AVID_START_PIXEL_LSB (0x16) > > +#define REG_AVID_START_PIXEL_MSB (0x17) > > +#define REG_AVID_STOP_PIXEL_LSB (0x18) > > +#define REG_AVID_STOP_PIXEL_MSB (0x19) > > + > > +#define REG_HSYNC_START_PIXEL_LSB (0x1A) > > +#define REG_HSYNC_START_PIXEL_MSB (0x1B) > > +#define REG_HSYNC_STOP_PIXEL_LSB (0x1C) > > +#define REG_HSYNC_STOP_PIXEL_MSB (0x1D) > > + > > +#define REG_VSYNC_START_LINE_LSB (0x1E) > > +#define REG_VSYNC_START_LINE_MSB (0x1F) > > +#define REG_VSYNC_STOP_LINE_LSB (0x20) > > +#define REG_VSYNC_STOP_LINE_MSB (0x21) > > + > > +#define REG_VBLK_START_LINE_LSB (0x22) > > +#define REG_VBLK_START_LINE_MSB (0x23) > > +#define REG_VBLK_STOP_LINE_LSB (0x24) > > +#define REG_VBLK_STOP_LINE_MSB (0x25) > > + > > +/* 0x26 - 0x27 Reserved */ > > + > > +#define REG_FAST_SWTICH_CONTROL (0x28) > > + > > +/* 0x29 Reserved */ > > + > > +#define REG_FAST_SWTICH_SCART_DELAY (0x2A) > > + > > +/* 0x2B Reserved */ > > + > > +#define REG_SCART_DELAY (0x2C) > > +#define REG_CTI_DELAY (0x2D) > > +#define REG_CTI_CONTROL (0x2E) > > + > > +/* 0x2F - 0x31 Reserved */ > > + > > +#define REG_SYNC_CONTROL (0x32) > > +#define REG_OUTPUT_FORMATTER1 (0x33) > > +#define REG_OUTPUT_FORMATTER2 (0x34) > > +#define REG_OUTPUT_FORMATTER3 (0x35) > > +#define REG_OUTPUT_FORMATTER4 (0x36) > > +#define REG_OUTPUT_FORMATTER5 (0x37) > > +#define REG_OUTPUT_FORMATTER6 (0x38) > > +#define REG_CLEAR_LOST_LOCK (0x39) > > + > > +#define REG_STATUS1 (0x3A) > > +#define REG_STATUS2 (0x3B) > > + > > +#define REG_AGC_GAIN_STATUS_LSB (0x3C) > > +#define REG_AGC_GAIN_STATUS_MSB (0x3D) > > + > > +/* 0x3E Reserved */ > > + > > +#define REG_VIDEO_STD_STATUS (0x3F) > > +#define REG_GPIO_INPUT1 (0x40) > > +#define REG_GPIO_INPUT2 (0x41) > > + > > +/* 0x42 - 0x45 Reserved */ > > + > > +#define REG_AFE_COARSE_GAIN_CH1 (0x46) > > +#define REG_AFE_COARSE_GAIN_CH2 (0x47) > > +#define REG_AFE_COARSE_GAIN_CH3 (0x48) > > +#define REG_AFE_COARSE_GAIN_CH4 (0x49) > > + > > +#define REG_AFE_FINE_GAIN_PB_B_LSB (0x4A) > > +#define REG_AFE_FINE_GAIN_PB_B_MSB (0x4B) > > +#define REG_AFE_FINE_GAIN_Y_G_CHROMA_LSB (0x4C) > > +#define REG_AFE_FINE_GAIN_Y_G_CHROMA_MSB (0x4D) > > +#define REG_AFE_FINE_GAIN_PR_R_LSB (0x4E) > > +#define REG_AFE_FINE_GAIN_PR_R_MSB (0x4F) > > +#define REG_AFE_FINE_GAIN_CVBS_LUMA_LSB (0x50) > > +#define REG_AFE_FINE_GAIN_CVBS_LUMA_MSB (0x51) > > + > > +/* 0x52 - 0x68 Reserved */ > > + > > +#define REG_FBIT_VBIT_CONTROL1 (0x69) > > + > > +/* 0x6A - 0x6B Reserved */ > > + > > +#define REG_BACKEND_AGC_CONTROL (0x6C) > > + > > +/* 0x6D - 0x6E Reserved */ > > + > > +#define REG_AGC_DECREMENT_SPEED_CONTROL (0x6F) > > +#define REG_ROM_VERSION (0x70) > > + > > +/* 0x71 - 0x73 Reserved */ > > + > > +#define REG_AGC_WHITE_PEAK_PROCESSING (0x74) > > +#define REG_FBIT_VBIT_CONTROL2 (0x75) > > +#define REG_VCR_TRICK_MODE_CONTROL (0x76) > > +#define REG_HORIZONTAL_SHAKE_INCREMENT (0x77) > > +#define REG_AGC_INCREMENT_SPEED (0x78) > > +#define REG_AGC_INCREMENT_DELAY (0x79) > > + > > +/* 0x7A - 0x7F Reserved */ > > + > > +#define REG_CHIP_ID_MSB (0x80) > > +#define REG_CHIP_ID_LSB (0x81) > > + > > +/* 0x82 Reserved */ > > + > > +#define REG_CPLL_SPEED_CONTROL (0x83) > > + > > +/* 0x84 - 0x96 Reserved */ > > + > > +#define REG_STATUS_REQUEST (0x97) > > + > > +/* 0x98 - 0x99 Reserved */ > > + > > +#define REG_VERTICAL_LINE_COUNT_LSB (0x9A) > > +#define REG_VERTICAL_LINE_COUNT_MSB (0x9B) > > + > > +/* 0x9C - 0x9D Reserved */ > > + > > +#define REG_AGC_DECREMENT_DELAY (0x9E) > > + > > +/* 0x9F - 0xB0 Reserved */ > > + > > +#define REG_VDP_TTX_FILTER_1_MASK1 (0xB1) > > +#define REG_VDP_TTX_FILTER_1_MASK2 (0xB2) > > +#define REG_VDP_TTX_FILTER_1_MASK3 (0xB3) > > +#define REG_VDP_TTX_FILTER_1_MASK4 (0xB4) > > +#define REG_VDP_TTX_FILTER_1_MASK5 (0xB5) > > +#define REG_VDP_TTX_FILTER_2_MASK1 (0xB6) > > +#define REG_VDP_TTX_FILTER_2_MASK2 (0xB7) > > +#define REG_VDP_TTX_FILTER_2_MASK3 (0xB8) > > +#define REG_VDP_TTX_FILTER_2_MASK4 (0xB9) > > +#define REG_VDP_TTX_FILTER_2_MASK5 (0xBA) > > +#define REG_VDP_TTX_FILTER_CONTROL (0xBB) > > +#define REG_VDP_FIFO_WORD_COUNT (0xBC) > > +#define REG_VDP_FIFO_INTERRUPT_THRLD (0xBD) > > + > > +/* 0xBE Reserved */ > > + > > +#define REG_VDP_FIFO_RESET (0xBF) > > +#define REG_VDP_FIFO_OUTPUT_CONTROL (0xC0) > > +#define REG_VDP_LINE_NUMBER_INTERRUPT (0xC1) > > +#define REG_VDP_PIXEL_ALIGNMENT_LSB (0xC2) > > +#define REG_VDP_PIXEL_ALIGNMENT_MSB (0xC3) > > + > > +/* 0xC4 - 0xD5 Reserved */ > > + > > +#define REG_VDP_LINE_START (0xD6) > > +#define REG_VDP_LINE_STOP (0xD7) > > +#define REG_VDP_GLOBAL_LINE_MODE (0xD8) > > +#define REG_VDP_FULL_FIELD_ENABLE (0xD9) > > +#define REG_VDP_FULL_FIELD_MODE (0xDA) > > + > > +/* 0xDB - 0xDF Reserved */ > > + > > +#define REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR (0xE0) > > +#define REG_VBUS_DATA_ACCESS_VBUS_ADDR_INCR (0xE1) > > +#define REG_FIFO_READ_DATA (0xE2) > > + > > +/* 0xE3 - 0xE7 Reserved */ > > + > > +#define REG_VBUS_ADDRESS_ACCESS1 (0xE8) > > +#define REG_VBUS_ADDRESS_ACCESS2 (0xE9) > > +#define REG_VBUS_ADDRESS_ACCESS3 (0xEA) > > + > > +/* 0xEB - 0xEF Reserved */ > > + > > +#define REG_INTERRUPT_RAW_STATUS0 (0xF0) > > +#define REG_INTERRUPT_RAW_STATUS1 (0xF1) > > +#define REG_INTERRUPT_STATUS0 (0xF2) > > +#define REG_INTERRUPT_STATUS1 (0xF3) > > +#define REG_INTERRUPT_MASK0 (0xF4) > > +#define REG_INTERRUPT_MASK1 (0xF5) > > +#define REG_INTERRUPT_CLEAR0 (0xF6) > > +#define REG_INTERRUPT_CLEAR1 (0xF7) > > + > > +/* 0xF8 - 0xFF Reserved */ > > + > > +/* > > + * Mask and bit definitions of TVP5146/47 registers > > + */ > > +/* The ID values we are looking for */ > > +#define TVP514X_CHIP_ID_MSB (0x51) > > +#define TVP5146_CHIP_ID_LSB (0x46) > > +#define TVP5147_CHIP_ID_LSB (0x47) > > + > > +#define VIDEO_STD_MASK (0x07) > > +#define VIDEO_STD_AUTO_SWITCH_BIT (0x00) > > +#define VIDEO_STD_NTSC_MJ_BIT (0x01) > > +#define VIDEO_STD_PAL_BDGHIN_BIT (0x02) > > +#define VIDEO_STD_PAL_M_BIT (0x03) > > +#define VIDEO_STD_PAL_COMBINATION_N_BIT (0x04) > > +#define VIDEO_STD_NTSC_4_43_BIT (0x05) > > +#define VIDEO_STD_SECAM_BIT (0x06) > > +#define VIDEO_STD_PAL_60_BIT (0x07) > > + > > +/* > > + * Status bit > > + */ > > +#define STATUS_TV_VCR_BIT (1<<0) > > +#define STATUS_HORZ_SYNC_LOCK_BIT (1<<1) > > +#define STATUS_VIRT_SYNC_LOCK_BIT (1<<2) > > +#define STATUS_CLR_SUBCAR_LOCK_BIT (1<<3) > > +#define STATUS_LOST_LOCK_DETECT_BIT (1<<4) > > +#define STATUS_FEILD_RATE_BIT (1<<5) > > +#define STATUS_LINE_ALTERNATING_BIT (1<<6) > > +#define STATUS_PEAK_WHITE_DETECT_BIT (1<<7) > > + > > +/** > > + * struct tvp514x_reg - Structure for TVP5146/47 register > > initialization values + * @token - Token: TOK_WRITE, TOK_TERM > etc.. > > + * @reg - Register offset > > + * @val - Register Value for TOK_WRITE or delay in ms for > TOK_DELAY > > + */ > > +struct tvp514x_reg { > > + u8 token; > > + u8 reg; > > + u32 val; > > +}; > > + > > +/** > > + * struct tvp514x_init_seq - Structure for TVP5146/47/46M2/47M1 > > power up + * Sequence. > > + * @ no_regs - Number of registers to write for power up > sequence. > > + * @ init_reg_seq - Array of registers and respective value to > > write. + */ > > +struct tvp514x_init_seq { > > + unsigned int no_regs; > > + struct tvp514x_reg *init_reg_seq; > > +}; > > +#endif /* ifndef _TVP514X_REGS_H */ > > diff --git a/include/media/tvp514x.h b/include/media/tvp514x.h > > new file mode 100755 > > index 0000000..2fee5e7 > > --- /dev/null > > +++ b/include/media/tvp514x.h > > @@ -0,0 +1,232 @@ > > +/* > > + * drivers/media/video/tvp514x.h > > + * > > + * Copyright (C) 2008 Texas Instruments Inc > > + * Author: Vaibhav Hiremath <hvaibhav@xxxxxx> > > + * > > + * Contributors: > > + * Sivaraj R <sivaraj@xxxxxx> > > + * Brijesh R Jadav <brijesh.j@xxxxxx> > > + * Hardik Shah <hardik.shah@xxxxxx> > > + * Manjunath Hadli <mrh@xxxxxx> > > + * Karicheri Muralidharan <m-karicheri2@xxxxxx> > > + * > > + * This package is free software; you can redistribute it and/or > > modify + * it under the terms of the GNU General Public License > > version 2 as + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be > useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public > License > > + * along with this program; if not, write to the Free Software > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > + * > > + */ > > + > > +#ifndef _TVP514X_H > > +#define _TVP514X_H > > + > > +/* > > + * Other macros > > + */ > > +#define TVP514X_MODULE_NAME "tvp514x" > > +#define TVP514X_I2C_DELAY (3) > > +#define I2C_RETRY_COUNT (5) > > +#define LOCK_RETRY_COUNT (5) > > +#define LOCK_RETRY_DELAY (200) > > + > > +#define TOK_WRITE (0) /* token for write > operation */ > > +#define TOK_TERM (1) /* terminating token */ > > +#define TOK_DELAY (2) /* delay token for reg > list */ > > +#define TOK_SKIP (3) /* token to skip a > register */ > > + > > +#define TVP514X_XCLK_BT656 (27000000) > > + > > +/* Number of pixels and number of lines per frame for different > > standards */ +#define NTSC_NUM_ACTIVE_PIXELS (720) > > +#define NTSC_NUM_ACTIVE_LINES (480) > > +#define PAL_NUM_ACTIVE_PIXELS (720) > > +#define PAL_NUM_ACTIVE_LINES (576) > > + > > +/** > > + * enum tvp514x_std - enum for supported standards > > + */ > > +enum tvp514x_std { > > + STD_NTSC_MJ = 0, > > + STD_PAL_BDGHIN, > > + STD_INVALID > > +}; > > + > > +/** > > + * enum tvp514x_state - enum for different decoder states > > + */ > > +enum tvp514x_state { > > + STATE_NOT_DETECTED, > > + STATE_DETECTED > > +}; > > + > > +/** > > + * enum tvp514x_input - enum for different decoder input pin > > + * configuration. > > + */ > > +enum tvp514x_input { > > + /* > > + * CVBS input selection > > + */ > > + INPUT_CVBS_VI1A = 0x0, > > + INPUT_CVBS_VI1B, > > + INPUT_CVBS_VI1C, > > + INPUT_CVBS_VI2A = 0x04, > > + INPUT_CVBS_VI2B, > > + INPUT_CVBS_VI2C, > > + INPUT_CVBS_VI3A = 0x08, > > + INPUT_CVBS_VI3B, > > + INPUT_CVBS_VI3C, > > + INPUT_CVBS_VI4A = 0x0C, > > + /* > > + * S-Video input selection > > + */ > > + INPUT_SVIDEO_VI2A_VI1A = 0x44, > > + INPUT_SVIDEO_VI2B_VI1B, > > + INPUT_SVIDEO_VI2C_VI1C, > > + INPUT_SVIDEO_VI2A_VI3A = 0x54, > > + INPUT_SVIDEO_VI2B_VI3B, > > + INPUT_SVIDEO_VI2C_VI3C, > > + INPUT_SVIDEO_VI4A_VI1A = 0x4C, > > + INPUT_SVIDEO_VI4A_VI1B, > > + INPUT_SVIDEO_VI4A_VI1C, > > + INPUT_SVIDEO_VI4A_VI3A = 0x5C, > > + INPUT_SVIDEO_VI4A_VI3B, > > + INPUT_SVIDEO_VI4A_VI3C > > + > > + /* Need to add entries for > > + * RGB, YPbPr and SCART. > > + */ > > +}; > > + > > +/** > > + * enum tvp514x_output_fmt - enum for output format > > + * supported. > > + */ > > +enum tvp514x_output_fmt { > > + OUTPUT_10BIT_422_EMBEDDED_SYNC = 0, > > + OUTPUT_20BIT_422_SEPERATE_SYNC, > > + OUTPUT_10BIT_422_SEPERATE_SYNC = 3, > > + OUTPUT_INVALID > > +}; > > + > > +/** > > + * struct tvp514x_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 tvp514x_std_info { > > + unsigned long width; > > + unsigned long height; > > + u8 video_std; > > + struct v4l2_standard standard; > > +}; > > + > > +/** > > + * struct tvp514x_ctrl_info - Information regarding supported > > controls + * @reg_address: Register offset of control register > > + * @query_ctrl: v4l2 query control information > > + */ > > +struct tvp514x_ctrl_info { > > + u8 reg_address; > > + struct v4l2_queryctrl query_ctrl; > > +}; > > + > > +/** > > + * struct tvp514x_input_info - Information regarding supported > > inputs + * @input_sel: Input select register > > + * @lock_mask: lock mask - depends on Svideo/CVBS > > + * @input: v4l2 input information > > + */ > > +struct tvp514x_input_info { > > + enum tvp514x_input input_sel; > > + struct v4l2_input input; > > +}; > > + > > +/** > > + * struct tvp514x_platform_data - Platform data values and access > > functions + * @power_set: Power state access function, zero is > off, > > non-zero is on. + * @ifparm: Interface parameters access function > > + * @priv_data_set: Device private data (pointer) access function > > + * @reg_list: The board dependent driver should fill the default > > value for + * required registers depending on board > > layout. The TVP5146/47 + * driver will update this > > register list for the registers + * whose values should > be > > maintained across open()/close() like + * setting > > brightness as defined in V4L2. > > + * The register list should be in the same order as > > defined in + * TVP5146/47 datasheet including reserved > > registers. As of now + * the driver expects the size of > > this list to be a minimum of + * 57 + 1 (upto regsiter > > REG_CLEAR_LOST_LOCK). > > + * The last member should be of the list should be > > + * {TOK_TERM, 0, 0} to indicate the end of register > list. > > + * @num_inputs: Number of input connection in board > > + * @input_list: Input information list for num_inputs > > + */ > > +struct tvp514x_platform_data { > > + char *master; > > + int (*power_set) (enum v4l2_power on); > > + int (*ifparm) (struct v4l2_ifparm *p); > > + int (*priv_data_set) (void *); > > + /* Input params */ > > + int num_inputs; > > + const struct tvp514x_input_info *input_list; > > + int default_input; > > + /* Interface control params */ > > + enum tvp514x_output_fmt fmt; > > + bool clk_polarity; > > + bool hs_polarity; > > + bool vs_polarity; > > +}; > > + > > +/** > > + * struct tvp514x_decoded - TVP5146/47 decoder object > > + * @v4l2_int_device: Slave handle > > + * @pdata: Board specific > > + * @client: I2C client data > > + * @id: Entry from I2C table > > + * @ver: Chip version > > + * @state: TVP5146/47 decoder state - detected or not-detected > > + * @pix: Current pixel format > > + * @num_fmts: Number of formats > > + * @fmt_list: Format list > > + * @current_std: Current standard > > + * @num_stds: Number of standards > > + * @std_list: Standards list > > + * @num_ctrls: Number of controls > > + * @ctrl_list: Control list > > + */ > > +struct tvp514x_decoder { > > + struct v4l2_int_device *v4l2_int_device; > > + const struct tvp514x_platform_data *pdata; > > + struct i2c_client *client; > > + > > + struct i2c_device_id *id; > > + > > + int ver; > > + enum tvp514x_state state; > > + > > + struct v4l2_pix_format pix; > > + int num_fmts; > > + const struct v4l2_fmtdesc *fmt_list; > > + > > + enum tvp514x_std current_std; > > + int num_stds; > > + struct tvp514x_std_info *std_list; > > + > > + int num_ctrls; > > + const struct tvp514x_ctrl_info *ctrl_list; > > + > > + int inputidx; > > +}; > > + > > +#endif /* ifndef _TVP514X_H */ > > -- > > 1.5.6 > > > > -- > > video4linux-list mailing list > > Unsubscribe > > mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe > > https://www.redhat.com/mailman/listinfo/video4linux-list > > > > -- > Hans Verkuil - video4linux developer - sponsored by TANDBERG -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html