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. 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