1cb7a01acSMauro Carvalho Chehab /* 2cb7a01acSMauro Carvalho Chehab * drivers/media/i2c/tvp514x.c 3cb7a01acSMauro Carvalho Chehab * 4cb7a01acSMauro Carvalho Chehab * TI TVP5146/47 decoder driver 5cb7a01acSMauro Carvalho Chehab * 6cb7a01acSMauro Carvalho Chehab * Copyright (C) 2008 Texas Instruments Inc 7cb7a01acSMauro Carvalho Chehab * Author: Vaibhav Hiremath <hvaibhav@ti.com> 8cb7a01acSMauro Carvalho Chehab * 9cb7a01acSMauro Carvalho Chehab * Contributors: 10cb7a01acSMauro Carvalho Chehab * Sivaraj R <sivaraj@ti.com> 11cb7a01acSMauro Carvalho Chehab * Brijesh R Jadav <brijesh.j@ti.com> 12cb7a01acSMauro Carvalho Chehab * Hardik Shah <hardik.shah@ti.com> 13cb7a01acSMauro Carvalho Chehab * Manjunath Hadli <mrh@ti.com> 14cb7a01acSMauro Carvalho Chehab * Karicheri Muralidharan <m-karicheri2@ti.com> 155b38b0f8SManjunath Hadli * Prabhakar Lad <prabhakar.lad@ti.com> 16cb7a01acSMauro Carvalho Chehab * 17cb7a01acSMauro Carvalho Chehab * This package is free software; you can redistribute it and/or modify 18cb7a01acSMauro Carvalho Chehab * it under the terms of the GNU General Public License version 2 as 19cb7a01acSMauro Carvalho Chehab * published by the Free Software Foundation. 20cb7a01acSMauro Carvalho Chehab * 21cb7a01acSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 22cb7a01acSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 23cb7a01acSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24cb7a01acSMauro Carvalho Chehab * GNU General Public License for more details. 25cb7a01acSMauro Carvalho Chehab * 26cb7a01acSMauro Carvalho Chehab */ 27cb7a01acSMauro Carvalho Chehab 28cb7a01acSMauro Carvalho Chehab #include <linux/i2c.h> 29cb7a01acSMauro Carvalho Chehab #include <linux/slab.h> 30cb7a01acSMauro Carvalho Chehab #include <linux/delay.h> 31cb7a01acSMauro Carvalho Chehab #include <linux/videodev2.h> 32cb7a01acSMauro Carvalho Chehab #include <linux/module.h> 335b38b0f8SManjunath Hadli #include <linux/v4l2-mediabus.h> 34098bcba3SSachin Kamat #include <linux/of.h> 35fd9fdb78SPhilipp Zabel #include <linux/of_graph.h> 36cb7a01acSMauro Carvalho Chehab 378f23acb5SLad, Prabhakar #include <media/v4l2-async.h> 38cb7a01acSMauro Carvalho Chehab #include <media/v4l2-device.h> 39cb7a01acSMauro Carvalho Chehab #include <media/v4l2-common.h> 40cb7a01acSMauro Carvalho Chehab #include <media/v4l2-mediabus.h> 41859969b3SSakari Ailus #include <media/v4l2-fwnode.h> 42cb7a01acSMauro Carvalho Chehab #include <media/v4l2-ctrls.h> 43b5dcee22SMauro Carvalho Chehab #include <media/i2c/tvp514x.h> 445b38b0f8SManjunath Hadli #include <media/media-entity.h> 45cb7a01acSMauro Carvalho Chehab 46cb7a01acSMauro Carvalho Chehab #include "tvp514x_regs.h" 47cb7a01acSMauro Carvalho Chehab 48cb7a01acSMauro Carvalho Chehab /* Private macros for TVP */ 49cb7a01acSMauro Carvalho Chehab #define I2C_RETRY_COUNT (5) 50cb7a01acSMauro Carvalho Chehab #define LOCK_RETRY_COUNT (5) 51cb7a01acSMauro Carvalho Chehab #define LOCK_RETRY_DELAY (200) 52cb7a01acSMauro Carvalho Chehab 53cb7a01acSMauro Carvalho Chehab /* Debug functions */ 54cb7a01acSMauro Carvalho Chehab static bool debug; 55cb7a01acSMauro Carvalho Chehab module_param(debug, bool, 0644); 56cb7a01acSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Debug level (0-1)"); 57cb7a01acSMauro Carvalho Chehab 58cb7a01acSMauro Carvalho Chehab MODULE_AUTHOR("Texas Instruments"); 59cb7a01acSMauro Carvalho Chehab MODULE_DESCRIPTION("TVP514X linux decoder driver"); 60cb7a01acSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 61cb7a01acSMauro Carvalho Chehab 62cb7a01acSMauro Carvalho Chehab /* enum tvp514x_std - enum for supported standards */ 63cb7a01acSMauro Carvalho Chehab enum tvp514x_std { 64cb7a01acSMauro Carvalho Chehab STD_NTSC_MJ = 0, 65cb7a01acSMauro Carvalho Chehab STD_PAL_BDGHIN, 66cb7a01acSMauro Carvalho Chehab STD_INVALID 67cb7a01acSMauro Carvalho Chehab }; 68cb7a01acSMauro Carvalho Chehab 69cb7a01acSMauro Carvalho Chehab /** 70cb7a01acSMauro Carvalho Chehab * struct tvp514x_std_info - Structure to store standard informations 71cb7a01acSMauro Carvalho Chehab * @width: Line width in pixels 72cb7a01acSMauro Carvalho Chehab * @height:Number of active lines 73cb7a01acSMauro Carvalho Chehab * @video_std: Value to write in REG_VIDEO_STD register 74cb7a01acSMauro Carvalho Chehab * @standard: v4l2 standard structure information 75cb7a01acSMauro Carvalho Chehab */ 76cb7a01acSMauro Carvalho Chehab struct tvp514x_std_info { 77cb7a01acSMauro Carvalho Chehab unsigned long width; 78cb7a01acSMauro Carvalho Chehab unsigned long height; 79cb7a01acSMauro Carvalho Chehab u8 video_std; 80cb7a01acSMauro Carvalho Chehab struct v4l2_standard standard; 81cb7a01acSMauro Carvalho Chehab }; 82cb7a01acSMauro Carvalho Chehab 83cb7a01acSMauro Carvalho Chehab static struct tvp514x_reg tvp514x_reg_list_default[0x40]; 84cb7a01acSMauro Carvalho Chehab 85cb7a01acSMauro Carvalho Chehab static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); 86cb7a01acSMauro Carvalho Chehab /** 87cb7a01acSMauro Carvalho Chehab * struct tvp514x_decoder - TVP5146/47 decoder object 88cb7a01acSMauro Carvalho Chehab * @sd: Subdevice Slave handle 89c5bb8318SMauro Carvalho Chehab * @hdl: embedded &struct v4l2_ctrl_handler 90cb7a01acSMauro Carvalho Chehab * @tvp514x_regs: copy of hw's regs with preset values. 91cb7a01acSMauro Carvalho Chehab * @pdata: Board specific 92cb7a01acSMauro Carvalho Chehab * @ver: Chip version 93cb7a01acSMauro Carvalho Chehab * @streaming: TVP5146/47 decoder streaming - enabled or disabled. 945b38b0f8SManjunath Hadli * @pix: Current pixel format 955b38b0f8SManjunath Hadli * @num_fmts: Number of formats 965b38b0f8SManjunath Hadli * @fmt_list: Format list 97cb7a01acSMauro Carvalho Chehab * @current_std: Current standard 98cb7a01acSMauro Carvalho Chehab * @num_stds: Number of standards 99cb7a01acSMauro Carvalho Chehab * @std_list: Standards list 100cb7a01acSMauro Carvalho Chehab * @input: Input routing at chip level 101cb7a01acSMauro Carvalho Chehab * @output: Output routing at chip level 102c5bb8318SMauro Carvalho Chehab * @pad: subdev media pad associated with the decoder 103c5bb8318SMauro Carvalho Chehab * @format: media bus frame format 104c5bb8318SMauro Carvalho Chehab * @int_seq: driver's register init sequence 105cb7a01acSMauro Carvalho Chehab */ 106cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder { 107cb7a01acSMauro Carvalho Chehab struct v4l2_subdev sd; 108cb7a01acSMauro Carvalho Chehab struct v4l2_ctrl_handler hdl; 109cb7a01acSMauro Carvalho Chehab struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; 110cb7a01acSMauro Carvalho Chehab const struct tvp514x_platform_data *pdata; 111cb7a01acSMauro Carvalho Chehab 112cb7a01acSMauro Carvalho Chehab int ver; 113cb7a01acSMauro Carvalho Chehab int streaming; 114cb7a01acSMauro Carvalho Chehab 1155b38b0f8SManjunath Hadli struct v4l2_pix_format pix; 1165b38b0f8SManjunath Hadli int num_fmts; 1175b38b0f8SManjunath Hadli const struct v4l2_fmtdesc *fmt_list; 1185b38b0f8SManjunath Hadli 119cb7a01acSMauro Carvalho Chehab enum tvp514x_std current_std; 120cb7a01acSMauro Carvalho Chehab int num_stds; 121cb7a01acSMauro Carvalho Chehab const struct tvp514x_std_info *std_list; 122cb7a01acSMauro Carvalho Chehab /* Input and Output Routing parameters */ 123cb7a01acSMauro Carvalho Chehab u32 input; 124cb7a01acSMauro Carvalho Chehab u32 output; 1255b38b0f8SManjunath Hadli 1265b38b0f8SManjunath Hadli /* mc related members */ 1275b38b0f8SManjunath Hadli struct media_pad pad; 1285b38b0f8SManjunath Hadli struct v4l2_mbus_framefmt format; 129f0a12d0cSLars-Peter Clausen 130f0a12d0cSLars-Peter Clausen struct tvp514x_reg *int_seq; 131cb7a01acSMauro Carvalho Chehab }; 132cb7a01acSMauro Carvalho Chehab 133cb7a01acSMauro Carvalho Chehab /* TVP514x default register values */ 134cb7a01acSMauro Carvalho Chehab static struct tvp514x_reg tvp514x_reg_list_default[] = { 135cb7a01acSMauro Carvalho Chehab /* Composite selected */ 136cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_INPUT_SEL, 0x05}, 137cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, 138cb7a01acSMauro Carvalho Chehab /* Auto mode */ 139cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VIDEO_STD, 0x00}, 140cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x00}, 141cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F}, 142cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_COLOR_KILLER, 0x10}, 143cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_LUMA_CONTROL1, 0x00}, 144cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_LUMA_CONTROL2, 0x00}, 145cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_LUMA_CONTROL3, 0x02}, 146cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_BRIGHTNESS, 0x80}, 147cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_CONTRAST, 0x80}, 148cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_SATURATION, 0x80}, 149cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_HUE, 0x00}, 150cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_CHROMA_CONTROL1, 0x00}, 151cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E}, 152cb7a01acSMauro Carvalho Chehab /* Reserved */ 153cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x0F, 0x00}, 154cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_COMP_PR_SATURATION, 0x80}, 155cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80}, 156cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_COMP_PB_SATURATION, 0x80}, 157cb7a01acSMauro Carvalho Chehab /* Reserved */ 158cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x13, 0x00}, 159cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80}, 160cb7a01acSMauro Carvalho Chehab /* Reserved */ 161cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x15, 0x00}, 162cb7a01acSMauro Carvalho Chehab /* NTSC timing */ 163cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, 164cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00}, 165cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25}, 166cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03}, 167cb7a01acSMauro Carvalho Chehab /* NTSC timing */ 168cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, 169cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00}, 170cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40}, 171cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00}, 172cb7a01acSMauro Carvalho Chehab /* NTSC timing */ 173cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, 174cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00}, 175cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07}, 176cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00}, 177cb7a01acSMauro Carvalho Chehab /* NTSC timing */ 178cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, 179cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00}, 180cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15}, 181cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00}, 182cb7a01acSMauro Carvalho Chehab /* Reserved */ 183cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x26, 0x00}, 184cb7a01acSMauro Carvalho Chehab /* Reserved */ 185cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x27, 0x00}, 186cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC}, 187cb7a01acSMauro Carvalho Chehab /* Reserved */ 188cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x29, 0x00}, 189cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00}, 190cb7a01acSMauro Carvalho Chehab /* Reserved */ 191cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x2B, 0x00}, 192cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_SCART_DELAY, 0x00}, 193cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_CTI_DELAY, 0x00}, 194cb7a01acSMauro Carvalho Chehab {TOK_SKIP, REG_CTI_CONTROL, 0x00}, 195cb7a01acSMauro Carvalho Chehab /* Reserved */ 196cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x2F, 0x00}, 197cb7a01acSMauro Carvalho Chehab /* Reserved */ 198cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x30, 0x00}, 199cb7a01acSMauro Carvalho Chehab /* Reserved */ 200cb7a01acSMauro Carvalho Chehab {TOK_SKIP, 0x31, 0x00}, 201cb7a01acSMauro Carvalho Chehab /* HS, VS active high */ 202cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, 203cb7a01acSMauro Carvalho Chehab /* 10-bit BT.656 */ 204cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, 205cb7a01acSMauro Carvalho Chehab /* Enable clk & data */ 206cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, 207cb7a01acSMauro Carvalho Chehab /* Enable AVID & FLD */ 208cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, 209cb7a01acSMauro Carvalho Chehab /* Enable VS & HS */ 210cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, 211cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF}, 212cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF}, 213cb7a01acSMauro Carvalho Chehab /* Clear status */ 214cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, 215cb7a01acSMauro Carvalho Chehab {TOK_TERM, 0, 0}, 216cb7a01acSMauro Carvalho Chehab }; 217cb7a01acSMauro Carvalho Chehab 218c5bb8318SMauro Carvalho Chehab /* 2195b38b0f8SManjunath Hadli * List of image formats supported by TVP5146/47 decoder 2205b38b0f8SManjunath Hadli * Currently we are using 8 bit mode only, but can be 2215b38b0f8SManjunath Hadli * extended to 10/20 bit mode. 2225b38b0f8SManjunath Hadli */ 2235b38b0f8SManjunath Hadli static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { 2245b38b0f8SManjunath Hadli { 2255b38b0f8SManjunath Hadli .index = 0, 2265b38b0f8SManjunath Hadli .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 2275b38b0f8SManjunath Hadli .flags = 0, 2285b38b0f8SManjunath Hadli .description = "8-bit UYVY 4:2:2 Format", 2295b38b0f8SManjunath Hadli .pixelformat = V4L2_PIX_FMT_UYVY, 2305b38b0f8SManjunath Hadli }, 2315b38b0f8SManjunath Hadli }; 2325b38b0f8SManjunath Hadli 233c5bb8318SMauro Carvalho Chehab /* 234cb7a01acSMauro Carvalho Chehab * Supported standards - 235cb7a01acSMauro Carvalho Chehab * 236cb7a01acSMauro Carvalho Chehab * Currently supports two standards only, need to add support for rest of the 237cb7a01acSMauro Carvalho Chehab * modes, like SECAM, etc... 238cb7a01acSMauro Carvalho Chehab */ 239cb7a01acSMauro Carvalho Chehab static const struct tvp514x_std_info tvp514x_std_list[] = { 240cb7a01acSMauro Carvalho Chehab /* Standard: STD_NTSC_MJ */ 241cb7a01acSMauro Carvalho Chehab [STD_NTSC_MJ] = { 242cb7a01acSMauro Carvalho Chehab .width = NTSC_NUM_ACTIVE_PIXELS, 243cb7a01acSMauro Carvalho Chehab .height = NTSC_NUM_ACTIVE_LINES, 244cb7a01acSMauro Carvalho Chehab .video_std = VIDEO_STD_NTSC_MJ_BIT, 245cb7a01acSMauro Carvalho Chehab .standard = { 246cb7a01acSMauro Carvalho Chehab .index = 0, 247cb7a01acSMauro Carvalho Chehab .id = V4L2_STD_NTSC, 248cb7a01acSMauro Carvalho Chehab .name = "NTSC", 249cb7a01acSMauro Carvalho Chehab .frameperiod = {1001, 30000}, 250cb7a01acSMauro Carvalho Chehab .framelines = 525 251cb7a01acSMauro Carvalho Chehab }, 252cb7a01acSMauro Carvalho Chehab /* Standard: STD_PAL_BDGHIN */ 253cb7a01acSMauro Carvalho Chehab }, 254cb7a01acSMauro Carvalho Chehab [STD_PAL_BDGHIN] = { 255cb7a01acSMauro Carvalho Chehab .width = PAL_NUM_ACTIVE_PIXELS, 256cb7a01acSMauro Carvalho Chehab .height = PAL_NUM_ACTIVE_LINES, 257cb7a01acSMauro Carvalho Chehab .video_std = VIDEO_STD_PAL_BDGHIN_BIT, 258cb7a01acSMauro Carvalho Chehab .standard = { 259cb7a01acSMauro Carvalho Chehab .index = 1, 260cb7a01acSMauro Carvalho Chehab .id = V4L2_STD_PAL, 261cb7a01acSMauro Carvalho Chehab .name = "PAL", 262cb7a01acSMauro Carvalho Chehab .frameperiod = {1, 25}, 263cb7a01acSMauro Carvalho Chehab .framelines = 625 264cb7a01acSMauro Carvalho Chehab }, 265cb7a01acSMauro Carvalho Chehab }, 266cb7a01acSMauro Carvalho Chehab /* Standard: need to add for additional standard */ 267cb7a01acSMauro Carvalho Chehab }; 268cb7a01acSMauro Carvalho Chehab 269cb7a01acSMauro Carvalho Chehab 270cb7a01acSMauro Carvalho Chehab static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) 271cb7a01acSMauro Carvalho Chehab { 272cb7a01acSMauro Carvalho Chehab return container_of(sd, struct tvp514x_decoder, sd); 273cb7a01acSMauro Carvalho Chehab } 274cb7a01acSMauro Carvalho Chehab 275cb7a01acSMauro Carvalho Chehab static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 276cb7a01acSMauro Carvalho Chehab { 277cb7a01acSMauro Carvalho Chehab return &container_of(ctrl->handler, struct tvp514x_decoder, hdl)->sd; 278cb7a01acSMauro Carvalho Chehab } 279cb7a01acSMauro Carvalho Chehab 280cb7a01acSMauro Carvalho Chehab 281cb7a01acSMauro Carvalho Chehab /** 282cb7a01acSMauro Carvalho Chehab * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. 283cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 284cb7a01acSMauro Carvalho Chehab * @reg: TVP5146/47 register address 285cb7a01acSMauro Carvalho Chehab * 286cb7a01acSMauro Carvalho Chehab * Returns value read if successful, or non-zero (-1) otherwise. 287cb7a01acSMauro Carvalho Chehab */ 288cb7a01acSMauro Carvalho Chehab static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) 289cb7a01acSMauro Carvalho Chehab { 290cb7a01acSMauro Carvalho Chehab int err, retry = 0; 291cb7a01acSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 292cb7a01acSMauro Carvalho Chehab 293cb7a01acSMauro Carvalho Chehab read_again: 294cb7a01acSMauro Carvalho Chehab 295cb7a01acSMauro Carvalho Chehab err = i2c_smbus_read_byte_data(client, reg); 296cb7a01acSMauro Carvalho Chehab if (err < 0) { 297cb7a01acSMauro Carvalho Chehab if (retry <= I2C_RETRY_COUNT) { 298cb7a01acSMauro Carvalho Chehab v4l2_warn(sd, "Read: retry ... %d\n", retry); 299cb7a01acSMauro Carvalho Chehab retry++; 300cb7a01acSMauro Carvalho Chehab msleep_interruptible(10); 301cb7a01acSMauro Carvalho Chehab goto read_again; 302cb7a01acSMauro Carvalho Chehab } 303cb7a01acSMauro Carvalho Chehab } 304cb7a01acSMauro Carvalho Chehab 305cb7a01acSMauro Carvalho Chehab return err; 306cb7a01acSMauro Carvalho Chehab } 307cb7a01acSMauro Carvalho Chehab 308cb7a01acSMauro Carvalho Chehab /** 309cb7a01acSMauro Carvalho Chehab * dump_reg() - dump the register content of TVP5146/47. 310cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 311cb7a01acSMauro Carvalho Chehab * @reg: TVP5146/47 register address 312cb7a01acSMauro Carvalho Chehab */ 313cb7a01acSMauro Carvalho Chehab static void dump_reg(struct v4l2_subdev *sd, u8 reg) 314cb7a01acSMauro Carvalho Chehab { 315cb7a01acSMauro Carvalho Chehab u32 val; 316cb7a01acSMauro Carvalho Chehab 317cb7a01acSMauro Carvalho Chehab val = tvp514x_read_reg(sd, reg); 318cb7a01acSMauro Carvalho Chehab v4l2_info(sd, "Reg(0x%.2X): 0x%.2X\n", reg, val); 319cb7a01acSMauro Carvalho Chehab } 320cb7a01acSMauro Carvalho Chehab 321cb7a01acSMauro Carvalho Chehab /** 322cb7a01acSMauro Carvalho Chehab * tvp514x_write_reg() - Write a value to a register in TVP5146/47 323cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 324cb7a01acSMauro Carvalho Chehab * @reg: TVP5146/47 register address 325cb7a01acSMauro Carvalho Chehab * @val: value to be written to the register 326cb7a01acSMauro Carvalho Chehab * 327cb7a01acSMauro Carvalho Chehab * Write a value to a register in an TVP5146/47 decoder device. 328cb7a01acSMauro Carvalho Chehab * Returns zero if successful, or non-zero otherwise. 329cb7a01acSMauro Carvalho Chehab */ 330cb7a01acSMauro Carvalho Chehab static int tvp514x_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val) 331cb7a01acSMauro Carvalho Chehab { 332cb7a01acSMauro Carvalho Chehab int err, retry = 0; 333cb7a01acSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 334cb7a01acSMauro Carvalho Chehab 335cb7a01acSMauro Carvalho Chehab write_again: 336cb7a01acSMauro Carvalho Chehab 337cb7a01acSMauro Carvalho Chehab err = i2c_smbus_write_byte_data(client, reg, val); 338cb7a01acSMauro Carvalho Chehab if (err) { 339cb7a01acSMauro Carvalho Chehab if (retry <= I2C_RETRY_COUNT) { 340cb7a01acSMauro Carvalho Chehab v4l2_warn(sd, "Write: retry ... %d\n", retry); 341cb7a01acSMauro Carvalho Chehab retry++; 342cb7a01acSMauro Carvalho Chehab msleep_interruptible(10); 343cb7a01acSMauro Carvalho Chehab goto write_again; 344cb7a01acSMauro Carvalho Chehab } 345cb7a01acSMauro Carvalho Chehab } 346cb7a01acSMauro Carvalho Chehab 347cb7a01acSMauro Carvalho Chehab return err; 348cb7a01acSMauro Carvalho Chehab } 349cb7a01acSMauro Carvalho Chehab 350cb7a01acSMauro Carvalho Chehab /** 351cb7a01acSMauro Carvalho Chehab * tvp514x_write_regs() : Initializes a list of TVP5146/47 registers 352cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 353cb7a01acSMauro Carvalho Chehab * @reglist: list of TVP5146/47 registers and values 354cb7a01acSMauro Carvalho Chehab * 355cb7a01acSMauro Carvalho Chehab * Initializes a list of TVP5146/47 registers:- 356cb7a01acSMauro Carvalho Chehab * if token is TOK_TERM, then entire write operation terminates 357cb7a01acSMauro Carvalho Chehab * if token is TOK_DELAY, then a delay of 'val' msec is introduced 358cb7a01acSMauro Carvalho Chehab * if token is TOK_SKIP, then the register write is skipped 359cb7a01acSMauro Carvalho Chehab * if token is TOK_WRITE, then the register write is performed 360cb7a01acSMauro Carvalho Chehab * Returns zero if successful, or non-zero otherwise. 361cb7a01acSMauro Carvalho Chehab */ 362cb7a01acSMauro Carvalho Chehab static int tvp514x_write_regs(struct v4l2_subdev *sd, 363cb7a01acSMauro Carvalho Chehab const struct tvp514x_reg reglist[]) 364cb7a01acSMauro Carvalho Chehab { 365cb7a01acSMauro Carvalho Chehab int err; 366cb7a01acSMauro Carvalho Chehab const struct tvp514x_reg *next = reglist; 367cb7a01acSMauro Carvalho Chehab 368cb7a01acSMauro Carvalho Chehab for (; next->token != TOK_TERM; next++) { 369cb7a01acSMauro Carvalho Chehab if (next->token == TOK_DELAY) { 370cb7a01acSMauro Carvalho Chehab msleep(next->val); 371cb7a01acSMauro Carvalho Chehab continue; 372cb7a01acSMauro Carvalho Chehab } 373cb7a01acSMauro Carvalho Chehab 374cb7a01acSMauro Carvalho Chehab if (next->token == TOK_SKIP) 375cb7a01acSMauro Carvalho Chehab continue; 376cb7a01acSMauro Carvalho Chehab 377cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, next->reg, (u8) next->val); 378cb7a01acSMauro Carvalho Chehab if (err) { 379cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "Write failed. Err[%d]\n", err); 380cb7a01acSMauro Carvalho Chehab return err; 381cb7a01acSMauro Carvalho Chehab } 382cb7a01acSMauro Carvalho Chehab } 383cb7a01acSMauro Carvalho Chehab return 0; 384cb7a01acSMauro Carvalho Chehab } 385cb7a01acSMauro Carvalho Chehab 386cb7a01acSMauro Carvalho Chehab /** 387cb7a01acSMauro Carvalho Chehab * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47 388cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 389cb7a01acSMauro Carvalho Chehab * 390cb7a01acSMauro Carvalho Chehab * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no 391cb7a01acSMauro Carvalho Chehab * standard detected. 392cb7a01acSMauro Carvalho Chehab */ 393cb7a01acSMauro Carvalho Chehab static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd) 394cb7a01acSMauro Carvalho Chehab { 395cb7a01acSMauro Carvalho Chehab u8 std, std_status; 396cb7a01acSMauro Carvalho Chehab 397cb7a01acSMauro Carvalho Chehab std = tvp514x_read_reg(sd, REG_VIDEO_STD); 398cb7a01acSMauro Carvalho Chehab if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) 399cb7a01acSMauro Carvalho Chehab /* use the standard status register */ 400cb7a01acSMauro Carvalho Chehab std_status = tvp514x_read_reg(sd, REG_VIDEO_STD_STATUS); 401cb7a01acSMauro Carvalho Chehab else 402cb7a01acSMauro Carvalho Chehab /* use the standard register itself */ 403cb7a01acSMauro Carvalho Chehab std_status = std; 404cb7a01acSMauro Carvalho Chehab 405cb7a01acSMauro Carvalho Chehab switch (std_status & VIDEO_STD_MASK) { 406cb7a01acSMauro Carvalho Chehab case VIDEO_STD_NTSC_MJ_BIT: 407cb7a01acSMauro Carvalho Chehab return STD_NTSC_MJ; 408cb7a01acSMauro Carvalho Chehab 409cb7a01acSMauro Carvalho Chehab case VIDEO_STD_PAL_BDGHIN_BIT: 410cb7a01acSMauro Carvalho Chehab return STD_PAL_BDGHIN; 411cb7a01acSMauro Carvalho Chehab 412cb7a01acSMauro Carvalho Chehab default: 413cb7a01acSMauro Carvalho Chehab return STD_INVALID; 414cb7a01acSMauro Carvalho Chehab } 415cb7a01acSMauro Carvalho Chehab 416cb7a01acSMauro Carvalho Chehab return STD_INVALID; 417cb7a01acSMauro Carvalho Chehab } 418cb7a01acSMauro Carvalho Chehab 419cb7a01acSMauro Carvalho Chehab /* TVP5146/47 register dump function */ 420cb7a01acSMauro Carvalho Chehab static void tvp514x_reg_dump(struct v4l2_subdev *sd) 421cb7a01acSMauro Carvalho Chehab { 422cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_INPUT_SEL); 423cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_AFE_GAIN_CTRL); 424cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VIDEO_STD); 425cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OPERATION_MODE); 426cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_COLOR_KILLER); 427cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_LUMA_CONTROL1); 428cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_LUMA_CONTROL2); 429cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_LUMA_CONTROL3); 430cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_BRIGHTNESS); 431cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_CONTRAST); 432cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_SATURATION); 433cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_HUE); 434cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_CHROMA_CONTROL1); 435cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_CHROMA_CONTROL2); 436cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_COMP_PR_SATURATION); 437cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_COMP_Y_CONTRAST); 438cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_COMP_PB_SATURATION); 439cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_COMP_Y_BRIGHTNESS); 440cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_AVID_START_PIXEL_LSB); 441cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_AVID_START_PIXEL_MSB); 442cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_AVID_STOP_PIXEL_LSB); 443cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_AVID_STOP_PIXEL_MSB); 444cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_HSYNC_START_PIXEL_LSB); 445cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_HSYNC_START_PIXEL_MSB); 446cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_HSYNC_STOP_PIXEL_LSB); 447cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_HSYNC_STOP_PIXEL_MSB); 448cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VSYNC_START_LINE_LSB); 449cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VSYNC_START_LINE_MSB); 450cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VSYNC_STOP_LINE_LSB); 451cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VSYNC_STOP_LINE_MSB); 452cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VBLK_START_LINE_LSB); 453cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VBLK_START_LINE_MSB); 454cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VBLK_STOP_LINE_LSB); 455cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_VBLK_STOP_LINE_MSB); 456cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_SYNC_CONTROL); 457cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER1); 458cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER2); 459cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER3); 460cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER4); 461cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER5); 462cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_OUTPUT_FORMATTER6); 463cb7a01acSMauro Carvalho Chehab dump_reg(sd, REG_CLEAR_LOST_LOCK); 464cb7a01acSMauro Carvalho Chehab } 465cb7a01acSMauro Carvalho Chehab 466cb7a01acSMauro Carvalho Chehab /** 467cb7a01acSMauro Carvalho Chehab * tvp514x_configure() - Configure the TVP5146/47 registers 468cb7a01acSMauro Carvalho Chehab * @sd: ptr to v4l2_subdev struct 469cb7a01acSMauro Carvalho Chehab * @decoder: ptr to tvp514x_decoder structure 470cb7a01acSMauro Carvalho Chehab * 471cb7a01acSMauro Carvalho Chehab * Returns zero if successful, or non-zero otherwise. 472cb7a01acSMauro Carvalho Chehab */ 473cb7a01acSMauro Carvalho Chehab static int tvp514x_configure(struct v4l2_subdev *sd, 474cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder) 475cb7a01acSMauro Carvalho Chehab { 476cb7a01acSMauro Carvalho Chehab int err; 477cb7a01acSMauro Carvalho Chehab 478cb7a01acSMauro Carvalho Chehab /* common register initialization */ 479cb7a01acSMauro Carvalho Chehab err = 480cb7a01acSMauro Carvalho Chehab tvp514x_write_regs(sd, decoder->tvp514x_regs); 481cb7a01acSMauro Carvalho Chehab if (err) 482cb7a01acSMauro Carvalho Chehab return err; 483cb7a01acSMauro Carvalho Chehab 484cb7a01acSMauro Carvalho Chehab if (debug) 485cb7a01acSMauro Carvalho Chehab tvp514x_reg_dump(sd); 486cb7a01acSMauro Carvalho Chehab 487cb7a01acSMauro Carvalho Chehab return 0; 488cb7a01acSMauro Carvalho Chehab } 489cb7a01acSMauro Carvalho Chehab 490cb7a01acSMauro Carvalho Chehab /** 491cb7a01acSMauro Carvalho Chehab * tvp514x_detect() - Detect if an tvp514x is present, and if so which revision. 492cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 493cb7a01acSMauro Carvalho Chehab * @decoder: pointer to tvp514x_decoder structure 494cb7a01acSMauro Carvalho Chehab * 495cb7a01acSMauro Carvalho Chehab * A device is considered to be detected if the chip ID (LSB and MSB) 496cb7a01acSMauro Carvalho Chehab * registers match the expected values. 497cb7a01acSMauro Carvalho Chehab * Any value of the rom version register is accepted. 498cb7a01acSMauro Carvalho Chehab * Returns ENODEV error number if no device is detected, or zero 499cb7a01acSMauro Carvalho Chehab * if a device is detected. 500cb7a01acSMauro Carvalho Chehab */ 501cb7a01acSMauro Carvalho Chehab static int tvp514x_detect(struct v4l2_subdev *sd, 502cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder) 503cb7a01acSMauro Carvalho Chehab { 504cb7a01acSMauro Carvalho Chehab u8 chip_id_msb, chip_id_lsb, rom_ver; 505cb7a01acSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 506cb7a01acSMauro Carvalho Chehab 507cb7a01acSMauro Carvalho Chehab chip_id_msb = tvp514x_read_reg(sd, REG_CHIP_ID_MSB); 508cb7a01acSMauro Carvalho Chehab chip_id_lsb = tvp514x_read_reg(sd, REG_CHIP_ID_LSB); 509cb7a01acSMauro Carvalho Chehab rom_ver = tvp514x_read_reg(sd, REG_ROM_VERSION); 510cb7a01acSMauro Carvalho Chehab 511cb7a01acSMauro Carvalho Chehab v4l2_dbg(1, debug, sd, 512cb7a01acSMauro Carvalho Chehab "chip id detected msb:0x%x lsb:0x%x rom version:0x%x\n", 513cb7a01acSMauro Carvalho Chehab chip_id_msb, chip_id_lsb, rom_ver); 514cb7a01acSMauro Carvalho Chehab if ((chip_id_msb != TVP514X_CHIP_ID_MSB) 515cb7a01acSMauro Carvalho Chehab || ((chip_id_lsb != TVP5146_CHIP_ID_LSB) 516cb7a01acSMauro Carvalho Chehab && (chip_id_lsb != TVP5147_CHIP_ID_LSB))) { 517cb7a01acSMauro Carvalho Chehab /* We didn't read the values we expected, so this must not be 518cb7a01acSMauro Carvalho Chehab * an TVP5146/47. 519cb7a01acSMauro Carvalho Chehab */ 520cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "chip id mismatch msb:0x%x lsb:0x%x\n", 521cb7a01acSMauro Carvalho Chehab chip_id_msb, chip_id_lsb); 522cb7a01acSMauro Carvalho Chehab return -ENODEV; 523cb7a01acSMauro Carvalho Chehab } 524cb7a01acSMauro Carvalho Chehab 525cb7a01acSMauro Carvalho Chehab decoder->ver = rom_ver; 526cb7a01acSMauro Carvalho Chehab 527cb7a01acSMauro Carvalho Chehab v4l2_info(sd, "%s (Version - 0x%.2x) found at 0x%x (%s)\n", 528cb7a01acSMauro Carvalho Chehab client->name, decoder->ver, 529cb7a01acSMauro Carvalho Chehab client->addr << 1, client->adapter->name); 530cb7a01acSMauro Carvalho Chehab return 0; 531cb7a01acSMauro Carvalho Chehab } 532cb7a01acSMauro Carvalho Chehab 533cb7a01acSMauro Carvalho Chehab /** 534cb7a01acSMauro Carvalho Chehab * tvp514x_querystd() - V4L2 decoder interface handler for querystd 535cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 536cb7a01acSMauro Carvalho Chehab * @std_id: standard V4L2 std_id ioctl enum 537cb7a01acSMauro Carvalho Chehab * 538cb7a01acSMauro Carvalho Chehab * Returns the current standard detected by TVP5146/47. If no active input is 539cb7a01acSMauro Carvalho Chehab * detected then *std_id is set to 0 and the function returns 0. 540cb7a01acSMauro Carvalho Chehab */ 541cb7a01acSMauro Carvalho Chehab static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) 542cb7a01acSMauro Carvalho Chehab { 543cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 544cb7a01acSMauro Carvalho Chehab enum tvp514x_std current_std; 545cb7a01acSMauro Carvalho Chehab enum tvp514x_input input_sel; 546cb7a01acSMauro Carvalho Chehab u8 sync_lock_status, lock_mask; 547cb7a01acSMauro Carvalho Chehab 548cb7a01acSMauro Carvalho Chehab if (std_id == NULL) 549cb7a01acSMauro Carvalho Chehab return -EINVAL; 550cb7a01acSMauro Carvalho Chehab 551c389648aSHans Verkuil /* To query the standard the TVP514x must power on the ADCs. */ 552c389648aSHans Verkuil if (!decoder->streaming) { 553c389648aSHans Verkuil tvp514x_s_stream(sd, 1); 554c389648aSHans Verkuil msleep(LOCK_RETRY_DELAY); 555c389648aSHans Verkuil } 556c389648aSHans Verkuil 557cb7a01acSMauro Carvalho Chehab /* query the current standard */ 558cb7a01acSMauro Carvalho Chehab current_std = tvp514x_query_current_std(sd); 55955852cbbSHans Verkuil if (current_std == STD_INVALID) { 56055852cbbSHans Verkuil *std_id = V4L2_STD_UNKNOWN; 561cb7a01acSMauro Carvalho Chehab return 0; 56255852cbbSHans Verkuil } 563cb7a01acSMauro Carvalho Chehab 564cb7a01acSMauro Carvalho Chehab input_sel = decoder->input; 565cb7a01acSMauro Carvalho Chehab 566cb7a01acSMauro Carvalho Chehab switch (input_sel) { 567cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI1A: 568cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI1B: 569cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI1C: 570cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI2A: 571cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI2B: 572cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI2C: 573cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI3A: 574cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI3B: 575cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI3C: 576cb7a01acSMauro Carvalho Chehab case INPUT_CVBS_VI4A: 577cb7a01acSMauro Carvalho Chehab lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | 578cb7a01acSMauro Carvalho Chehab STATUS_HORZ_SYNC_LOCK_BIT | 579cb7a01acSMauro Carvalho Chehab STATUS_VIRT_SYNC_LOCK_BIT; 580cb7a01acSMauro Carvalho Chehab break; 581cb7a01acSMauro Carvalho Chehab 582cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2A_VI1A: 583cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2B_VI1B: 584cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2C_VI1C: 585cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2A_VI3A: 586cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2B_VI3B: 587cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI2C_VI3C: 588cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI1A: 589cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI1B: 590cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI1C: 591cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI3A: 592cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI3B: 593cb7a01acSMauro Carvalho Chehab case INPUT_SVIDEO_VI4A_VI3C: 594cb7a01acSMauro Carvalho Chehab lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | 595cb7a01acSMauro Carvalho Chehab STATUS_VIRT_SYNC_LOCK_BIT; 596cb7a01acSMauro Carvalho Chehab break; 597cb7a01acSMauro Carvalho Chehab /*Need to add other interfaces*/ 598cb7a01acSMauro Carvalho Chehab default: 599cb7a01acSMauro Carvalho Chehab return -EINVAL; 600cb7a01acSMauro Carvalho Chehab } 601cb7a01acSMauro Carvalho Chehab /* check whether signal is locked */ 602cb7a01acSMauro Carvalho Chehab sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); 60355852cbbSHans Verkuil if (lock_mask != (sync_lock_status & lock_mask)) { 60455852cbbSHans Verkuil *std_id = V4L2_STD_UNKNOWN; 605cb7a01acSMauro Carvalho Chehab return 0; /* No input detected */ 60655852cbbSHans Verkuil } 607cb7a01acSMauro Carvalho Chehab 60855852cbbSHans Verkuil *std_id &= decoder->std_list[current_std].standard.id; 609cb7a01acSMauro Carvalho Chehab 610cb7a01acSMauro Carvalho Chehab v4l2_dbg(1, debug, sd, "Current STD: %s\n", 611cb7a01acSMauro Carvalho Chehab decoder->std_list[current_std].standard.name); 612cb7a01acSMauro Carvalho Chehab return 0; 613cb7a01acSMauro Carvalho Chehab } 614cb7a01acSMauro Carvalho Chehab 615cb7a01acSMauro Carvalho Chehab /** 616cb7a01acSMauro Carvalho Chehab * tvp514x_s_std() - V4L2 decoder interface handler for s_std 617cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 618cb7a01acSMauro Carvalho Chehab * @std_id: standard V4L2 v4l2_std_id ioctl enum 619cb7a01acSMauro Carvalho Chehab * 620cb7a01acSMauro Carvalho Chehab * If std_id is supported, sets the requested standard. Otherwise, returns 621cb7a01acSMauro Carvalho Chehab * -EINVAL 622cb7a01acSMauro Carvalho Chehab */ 623cb7a01acSMauro Carvalho Chehab static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) 624cb7a01acSMauro Carvalho Chehab { 625cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 626cb7a01acSMauro Carvalho Chehab int err, i; 627cb7a01acSMauro Carvalho Chehab 628cb7a01acSMauro Carvalho Chehab for (i = 0; i < decoder->num_stds; i++) 629cb7a01acSMauro Carvalho Chehab if (std_id & decoder->std_list[i].standard.id) 630cb7a01acSMauro Carvalho Chehab break; 631cb7a01acSMauro Carvalho Chehab 632cb7a01acSMauro Carvalho Chehab if ((i == decoder->num_stds) || (i == STD_INVALID)) 633cb7a01acSMauro Carvalho Chehab return -EINVAL; 634cb7a01acSMauro Carvalho Chehab 635cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_VIDEO_STD, 636cb7a01acSMauro Carvalho Chehab decoder->std_list[i].video_std); 637cb7a01acSMauro Carvalho Chehab if (err) 638cb7a01acSMauro Carvalho Chehab return err; 639cb7a01acSMauro Carvalho Chehab 640cb7a01acSMauro Carvalho Chehab decoder->current_std = i; 641cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_VIDEO_STD].val = 642cb7a01acSMauro Carvalho Chehab decoder->std_list[i].video_std; 643cb7a01acSMauro Carvalho Chehab 644cb7a01acSMauro Carvalho Chehab v4l2_dbg(1, debug, sd, "Standard set to: %s\n", 645cb7a01acSMauro Carvalho Chehab decoder->std_list[i].standard.name); 646cb7a01acSMauro Carvalho Chehab return 0; 647cb7a01acSMauro Carvalho Chehab } 648cb7a01acSMauro Carvalho Chehab 649cb7a01acSMauro Carvalho Chehab /** 650cb7a01acSMauro Carvalho Chehab * tvp514x_s_routing() - V4L2 decoder interface handler for s_routing 651cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 652cb7a01acSMauro Carvalho Chehab * @input: input selector for routing the signal 653cb7a01acSMauro Carvalho Chehab * @output: output selector for routing the signal 654cb7a01acSMauro Carvalho Chehab * @config: config value. Not used 655cb7a01acSMauro Carvalho Chehab * 656cb7a01acSMauro Carvalho Chehab * If index is valid, selects the requested input. Otherwise, returns -EINVAL if 657cb7a01acSMauro Carvalho Chehab * the input is not supported or there is no active signal present in the 658cb7a01acSMauro Carvalho Chehab * selected input. 659cb7a01acSMauro Carvalho Chehab */ 660cb7a01acSMauro Carvalho Chehab static int tvp514x_s_routing(struct v4l2_subdev *sd, 661cb7a01acSMauro Carvalho Chehab u32 input, u32 output, u32 config) 662cb7a01acSMauro Carvalho Chehab { 663cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 664cb7a01acSMauro Carvalho Chehab int err; 665cb7a01acSMauro Carvalho Chehab enum tvp514x_input input_sel; 666cb7a01acSMauro Carvalho Chehab enum tvp514x_output output_sel; 667cb7a01acSMauro Carvalho Chehab 668cb7a01acSMauro Carvalho Chehab if ((input >= INPUT_INVALID) || 669cb7a01acSMauro Carvalho Chehab (output >= OUTPUT_INVALID)) 670cb7a01acSMauro Carvalho Chehab /* Index out of bound */ 671cb7a01acSMauro Carvalho Chehab return -EINVAL; 672cb7a01acSMauro Carvalho Chehab 673cb7a01acSMauro Carvalho Chehab input_sel = input; 674cb7a01acSMauro Carvalho Chehab output_sel = output; 675cb7a01acSMauro Carvalho Chehab 676cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_INPUT_SEL, input_sel); 677cb7a01acSMauro Carvalho Chehab if (err) 678cb7a01acSMauro Carvalho Chehab return err; 679cb7a01acSMauro Carvalho Chehab 680cb7a01acSMauro Carvalho Chehab output_sel |= tvp514x_read_reg(sd, 681cb7a01acSMauro Carvalho Chehab REG_OUTPUT_FORMATTER1) & 0x7; 682cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_OUTPUT_FORMATTER1, 683cb7a01acSMauro Carvalho Chehab output_sel); 684cb7a01acSMauro Carvalho Chehab if (err) 685cb7a01acSMauro Carvalho Chehab return err; 686cb7a01acSMauro Carvalho Chehab 687cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; 688cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; 689cb7a01acSMauro Carvalho Chehab decoder->input = input; 690cb7a01acSMauro Carvalho Chehab decoder->output = output; 691cb7a01acSMauro Carvalho Chehab 692cb7a01acSMauro Carvalho Chehab v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel); 693cb7a01acSMauro Carvalho Chehab 694cb7a01acSMauro Carvalho Chehab return 0; 695cb7a01acSMauro Carvalho Chehab } 696cb7a01acSMauro Carvalho Chehab 697cb7a01acSMauro Carvalho Chehab /** 698cb7a01acSMauro Carvalho Chehab * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl 699cb7a01acSMauro Carvalho Chehab * @ctrl: pointer to v4l2_ctrl structure 700cb7a01acSMauro Carvalho Chehab * 701cb7a01acSMauro Carvalho Chehab * If the requested control is supported, sets the control's current 702cb7a01acSMauro Carvalho Chehab * value in HW. Otherwise, returns -EINVAL if the control is not supported. 703cb7a01acSMauro Carvalho Chehab */ 704cb7a01acSMauro Carvalho Chehab static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl) 705cb7a01acSMauro Carvalho Chehab { 706cb7a01acSMauro Carvalho Chehab struct v4l2_subdev *sd = to_sd(ctrl); 707cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 708cb7a01acSMauro Carvalho Chehab int err = -EINVAL, value; 709cb7a01acSMauro Carvalho Chehab 710cb7a01acSMauro Carvalho Chehab value = ctrl->val; 711cb7a01acSMauro Carvalho Chehab 712cb7a01acSMauro Carvalho Chehab switch (ctrl->id) { 713cb7a01acSMauro Carvalho Chehab case V4L2_CID_BRIGHTNESS: 714cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_BRIGHTNESS, value); 715cb7a01acSMauro Carvalho Chehab if (!err) 716cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; 717cb7a01acSMauro Carvalho Chehab break; 718cb7a01acSMauro Carvalho Chehab case V4L2_CID_CONTRAST: 719cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_CONTRAST, value); 720cb7a01acSMauro Carvalho Chehab if (!err) 721cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_CONTRAST].val = value; 722cb7a01acSMauro Carvalho Chehab break; 723cb7a01acSMauro Carvalho Chehab case V4L2_CID_SATURATION: 724cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_SATURATION, value); 725cb7a01acSMauro Carvalho Chehab if (!err) 726cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_SATURATION].val = value; 727cb7a01acSMauro Carvalho Chehab break; 728cb7a01acSMauro Carvalho Chehab case V4L2_CID_HUE: 729cb7a01acSMauro Carvalho Chehab if (value == 180) 730cb7a01acSMauro Carvalho Chehab value = 0x7F; 731cb7a01acSMauro Carvalho Chehab else if (value == -180) 732cb7a01acSMauro Carvalho Chehab value = 0x80; 733cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_HUE, value); 734cb7a01acSMauro Carvalho Chehab if (!err) 735cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_HUE].val = value; 736cb7a01acSMauro Carvalho Chehab break; 737cb7a01acSMauro Carvalho Chehab case V4L2_CID_AUTOGAIN: 738cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value ? 0x0f : 0x0c); 739cb7a01acSMauro Carvalho Chehab if (!err) 740cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; 741cb7a01acSMauro Carvalho Chehab break; 742cb7a01acSMauro Carvalho Chehab } 743cb7a01acSMauro Carvalho Chehab 744cb7a01acSMauro Carvalho Chehab v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n", 745cb7a01acSMauro Carvalho Chehab ctrl->id, ctrl->val); 746cb7a01acSMauro Carvalho Chehab return err; 747cb7a01acSMauro Carvalho Chehab } 748cb7a01acSMauro Carvalho Chehab 749cb7a01acSMauro Carvalho Chehab /** 750cb7a01acSMauro Carvalho Chehab * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm 751cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 752cb7a01acSMauro Carvalho Chehab * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure 753cb7a01acSMauro Carvalho Chehab * 754cb7a01acSMauro Carvalho Chehab * Returns the decoder's video CAPTURE parameters. 755cb7a01acSMauro Carvalho Chehab */ 756cb7a01acSMauro Carvalho Chehab static int 757cb7a01acSMauro Carvalho Chehab tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) 758cb7a01acSMauro Carvalho Chehab { 759cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 760cb7a01acSMauro Carvalho Chehab struct v4l2_captureparm *cparm; 761cb7a01acSMauro Carvalho Chehab enum tvp514x_std current_std; 762cb7a01acSMauro Carvalho Chehab 763cb7a01acSMauro Carvalho Chehab if (a == NULL) 764cb7a01acSMauro Carvalho Chehab return -EINVAL; 765cb7a01acSMauro Carvalho Chehab 766cb7a01acSMauro Carvalho Chehab if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 767cb7a01acSMauro Carvalho Chehab /* only capture is supported */ 768cb7a01acSMauro Carvalho Chehab return -EINVAL; 769cb7a01acSMauro Carvalho Chehab 770cb7a01acSMauro Carvalho Chehab /* get the current standard */ 771cb7a01acSMauro Carvalho Chehab current_std = decoder->current_std; 772cb7a01acSMauro Carvalho Chehab 773cb7a01acSMauro Carvalho Chehab cparm = &a->parm.capture; 774cb7a01acSMauro Carvalho Chehab cparm->capability = V4L2_CAP_TIMEPERFRAME; 775cb7a01acSMauro Carvalho Chehab cparm->timeperframe = 776cb7a01acSMauro Carvalho Chehab decoder->std_list[current_std].standard.frameperiod; 777cb7a01acSMauro Carvalho Chehab 778cb7a01acSMauro Carvalho Chehab return 0; 779cb7a01acSMauro Carvalho Chehab } 780cb7a01acSMauro Carvalho Chehab 781cb7a01acSMauro Carvalho Chehab /** 782cb7a01acSMauro Carvalho Chehab * tvp514x_s_parm() - V4L2 decoder interface handler for s_parm 783cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 784cb7a01acSMauro Carvalho Chehab * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure 785cb7a01acSMauro Carvalho Chehab * 786cb7a01acSMauro Carvalho Chehab * Configures the decoder to use the input parameters, if possible. If 787cb7a01acSMauro Carvalho Chehab * not possible, returns the appropriate error code. 788cb7a01acSMauro Carvalho Chehab */ 789cb7a01acSMauro Carvalho Chehab static int 790cb7a01acSMauro Carvalho Chehab tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) 791cb7a01acSMauro Carvalho Chehab { 792cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 793cb7a01acSMauro Carvalho Chehab struct v4l2_fract *timeperframe; 794cb7a01acSMauro Carvalho Chehab enum tvp514x_std current_std; 795cb7a01acSMauro Carvalho Chehab 796cb7a01acSMauro Carvalho Chehab if (a == NULL) 797cb7a01acSMauro Carvalho Chehab return -EINVAL; 798cb7a01acSMauro Carvalho Chehab 799cb7a01acSMauro Carvalho Chehab if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 800cb7a01acSMauro Carvalho Chehab /* only capture is supported */ 801cb7a01acSMauro Carvalho Chehab return -EINVAL; 802cb7a01acSMauro Carvalho Chehab 803cb7a01acSMauro Carvalho Chehab timeperframe = &a->parm.capture.timeperframe; 804cb7a01acSMauro Carvalho Chehab 805cb7a01acSMauro Carvalho Chehab /* get the current standard */ 806cb7a01acSMauro Carvalho Chehab current_std = decoder->current_std; 807cb7a01acSMauro Carvalho Chehab 808cb7a01acSMauro Carvalho Chehab *timeperframe = 809cb7a01acSMauro Carvalho Chehab decoder->std_list[current_std].standard.frameperiod; 810cb7a01acSMauro Carvalho Chehab 811cb7a01acSMauro Carvalho Chehab return 0; 812cb7a01acSMauro Carvalho Chehab } 813cb7a01acSMauro Carvalho Chehab 814cb7a01acSMauro Carvalho Chehab /** 815cb7a01acSMauro Carvalho Chehab * tvp514x_s_stream() - V4L2 decoder i/f handler for s_stream 816cb7a01acSMauro Carvalho Chehab * @sd: pointer to standard V4L2 sub-device structure 817cb7a01acSMauro Carvalho Chehab * @enable: streaming enable or disable 818cb7a01acSMauro Carvalho Chehab * 819cb7a01acSMauro Carvalho Chehab * Sets streaming to enable or disable, if possible. 820cb7a01acSMauro Carvalho Chehab */ 821cb7a01acSMauro Carvalho Chehab static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) 822cb7a01acSMauro Carvalho Chehab { 823cb7a01acSMauro Carvalho Chehab int err = 0; 824cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 825cb7a01acSMauro Carvalho Chehab 826cb7a01acSMauro Carvalho Chehab if (decoder->streaming == enable) 827cb7a01acSMauro Carvalho Chehab return 0; 828cb7a01acSMauro Carvalho Chehab 829cb7a01acSMauro Carvalho Chehab switch (enable) { 830cb7a01acSMauro Carvalho Chehab case 0: 831cb7a01acSMauro Carvalho Chehab { 832cb7a01acSMauro Carvalho Chehab /* Power Down Sequence */ 833cb7a01acSMauro Carvalho Chehab err = tvp514x_write_reg(sd, REG_OPERATION_MODE, 0x01); 834cb7a01acSMauro Carvalho Chehab if (err) { 835cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "Unable to turn off decoder\n"); 836cb7a01acSMauro Carvalho Chehab return err; 837cb7a01acSMauro Carvalho Chehab } 838cb7a01acSMauro Carvalho Chehab decoder->streaming = enable; 839cb7a01acSMauro Carvalho Chehab break; 840cb7a01acSMauro Carvalho Chehab } 841cb7a01acSMauro Carvalho Chehab case 1: 842cb7a01acSMauro Carvalho Chehab { 843cb7a01acSMauro Carvalho Chehab /* Power Up Sequence */ 844f0a12d0cSLars-Peter Clausen err = tvp514x_write_regs(sd, decoder->int_seq); 845cb7a01acSMauro Carvalho Chehab if (err) { 846cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "Unable to turn on decoder\n"); 847cb7a01acSMauro Carvalho Chehab return err; 848cb7a01acSMauro Carvalho Chehab } 849cb7a01acSMauro Carvalho Chehab /* Detect if not already detected */ 850cb7a01acSMauro Carvalho Chehab err = tvp514x_detect(sd, decoder); 851cb7a01acSMauro Carvalho Chehab if (err) { 852cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "Unable to detect decoder\n"); 853cb7a01acSMauro Carvalho Chehab return err; 854cb7a01acSMauro Carvalho Chehab } 855cb7a01acSMauro Carvalho Chehab err = tvp514x_configure(sd, decoder); 856cb7a01acSMauro Carvalho Chehab if (err) { 857cb7a01acSMauro Carvalho Chehab v4l2_err(sd, "Unable to configure decoder\n"); 858cb7a01acSMauro Carvalho Chehab return err; 859cb7a01acSMauro Carvalho Chehab } 860cb7a01acSMauro Carvalho Chehab decoder->streaming = enable; 861cb7a01acSMauro Carvalho Chehab break; 862cb7a01acSMauro Carvalho Chehab } 863cb7a01acSMauro Carvalho Chehab default: 864cb7a01acSMauro Carvalho Chehab err = -ENODEV; 865cb7a01acSMauro Carvalho Chehab break; 866cb7a01acSMauro Carvalho Chehab } 867cb7a01acSMauro Carvalho Chehab 868cb7a01acSMauro Carvalho Chehab return err; 869cb7a01acSMauro Carvalho Chehab } 870cb7a01acSMauro Carvalho Chehab 871cb7a01acSMauro Carvalho Chehab static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = { 872cb7a01acSMauro Carvalho Chehab .s_ctrl = tvp514x_s_ctrl, 873cb7a01acSMauro Carvalho Chehab }; 874cb7a01acSMauro Carvalho Chehab 8755b38b0f8SManjunath Hadli /** 8765b38b0f8SManjunath Hadli * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code 8775b38b0f8SManjunath Hadli * @sd: pointer to standard V4L2 sub-device structure 878f7234138SHans Verkuil * @cfg: pad configuration 8795b38b0f8SManjunath Hadli * @code: pointer to v4l2_subdev_mbus_code_enum structure 8805b38b0f8SManjunath Hadli * 8815b38b0f8SManjunath Hadli * Enumertaes mbus codes supported 8825b38b0f8SManjunath Hadli */ 8835b38b0f8SManjunath Hadli static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd, 884f7234138SHans Verkuil struct v4l2_subdev_pad_config *cfg, 8855b38b0f8SManjunath Hadli struct v4l2_subdev_mbus_code_enum *code) 8865b38b0f8SManjunath Hadli { 8875b38b0f8SManjunath Hadli u32 pad = code->pad; 8885b38b0f8SManjunath Hadli u32 index = code->index; 8895b38b0f8SManjunath Hadli 8905b38b0f8SManjunath Hadli memset(code, 0, sizeof(*code)); 8915b38b0f8SManjunath Hadli code->index = index; 8925b38b0f8SManjunath Hadli code->pad = pad; 8935b38b0f8SManjunath Hadli 8945b38b0f8SManjunath Hadli if (index != 0) 8955b38b0f8SManjunath Hadli return -EINVAL; 8965b38b0f8SManjunath Hadli 8971a33ac00SBenoit Parrot code->code = MEDIA_BUS_FMT_UYVY8_2X8; 8985b38b0f8SManjunath Hadli 8995b38b0f8SManjunath Hadli return 0; 9005b38b0f8SManjunath Hadli } 9015b38b0f8SManjunath Hadli 9025b38b0f8SManjunath Hadli /** 9035b38b0f8SManjunath Hadli * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format 9045b38b0f8SManjunath Hadli * @sd: pointer to standard V4L2 sub-device structure 905f7234138SHans Verkuil * @cfg: pad configuration 9065b38b0f8SManjunath Hadli * @format: pointer to v4l2_subdev_format structure 9075b38b0f8SManjunath Hadli * 9085b38b0f8SManjunath Hadli * Retrieves pad format which is active or tried based on requirement 9095b38b0f8SManjunath Hadli */ 9105b38b0f8SManjunath Hadli static int tvp514x_get_pad_format(struct v4l2_subdev *sd, 911f7234138SHans Verkuil struct v4l2_subdev_pad_config *cfg, 9125b38b0f8SManjunath Hadli struct v4l2_subdev_format *format) 9135b38b0f8SManjunath Hadli { 9145b38b0f8SManjunath Hadli struct tvp514x_decoder *decoder = to_decoder(sd); 9155b38b0f8SManjunath Hadli __u32 which = format->which; 9165b38b0f8SManjunath Hadli 917da298c6dSHans Verkuil if (format->pad) 918da298c6dSHans Verkuil return -EINVAL; 919da298c6dSHans Verkuil 9205b38b0f8SManjunath Hadli if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { 9215b38b0f8SManjunath Hadli format->format = decoder->format; 9225b38b0f8SManjunath Hadli return 0; 9235b38b0f8SManjunath Hadli } 9245b38b0f8SManjunath Hadli 9251a33ac00SBenoit Parrot format->format.code = MEDIA_BUS_FMT_UYVY8_2X8; 9265b38b0f8SManjunath Hadli format->format.width = tvp514x_std_list[decoder->current_std].width; 9275b38b0f8SManjunath Hadli format->format.height = tvp514x_std_list[decoder->current_std].height; 9285b38b0f8SManjunath Hadli format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; 9295b38b0f8SManjunath Hadli format->format.field = V4L2_FIELD_INTERLACED; 9305b38b0f8SManjunath Hadli 9315b38b0f8SManjunath Hadli return 0; 9325b38b0f8SManjunath Hadli } 9335b38b0f8SManjunath Hadli 9345b38b0f8SManjunath Hadli /** 9355b38b0f8SManjunath Hadli * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format 9365b38b0f8SManjunath Hadli * @sd: pointer to standard V4L2 sub-device structure 937f7234138SHans Verkuil * @cfg: pad configuration 938c5bb8318SMauro Carvalho Chehab * @fmt: pointer to v4l2_subdev_format structure 9395b38b0f8SManjunath Hadli * 9405b38b0f8SManjunath Hadli * Set pad format for the output pad 9415b38b0f8SManjunath Hadli */ 9425b38b0f8SManjunath Hadli static int tvp514x_set_pad_format(struct v4l2_subdev *sd, 943f7234138SHans Verkuil struct v4l2_subdev_pad_config *cfg, 9445b38b0f8SManjunath Hadli struct v4l2_subdev_format *fmt) 9455b38b0f8SManjunath Hadli { 9465b38b0f8SManjunath Hadli struct tvp514x_decoder *decoder = to_decoder(sd); 9475b38b0f8SManjunath Hadli 9485b38b0f8SManjunath Hadli if (fmt->format.field != V4L2_FIELD_INTERLACED || 9491a33ac00SBenoit Parrot fmt->format.code != MEDIA_BUS_FMT_UYVY8_2X8 || 9505b38b0f8SManjunath Hadli fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M || 9515b38b0f8SManjunath Hadli fmt->format.width != tvp514x_std_list[decoder->current_std].width || 9525b38b0f8SManjunath Hadli fmt->format.height != tvp514x_std_list[decoder->current_std].height) 9535b38b0f8SManjunath Hadli return -EINVAL; 9545b38b0f8SManjunath Hadli 9555b38b0f8SManjunath Hadli decoder->format = fmt->format; 9565b38b0f8SManjunath Hadli 9575b38b0f8SManjunath Hadli return 0; 9585b38b0f8SManjunath Hadli } 9595b38b0f8SManjunath Hadli 960cb7a01acSMauro Carvalho Chehab static const struct v4l2_subdev_video_ops tvp514x_video_ops = { 9618774bed9SLaurent Pinchart .s_std = tvp514x_s_std, 962cb7a01acSMauro Carvalho Chehab .s_routing = tvp514x_s_routing, 963cb7a01acSMauro Carvalho Chehab .querystd = tvp514x_querystd, 964cb7a01acSMauro Carvalho Chehab .g_parm = tvp514x_g_parm, 965cb7a01acSMauro Carvalho Chehab .s_parm = tvp514x_s_parm, 966cb7a01acSMauro Carvalho Chehab .s_stream = tvp514x_s_stream, 967cb7a01acSMauro Carvalho Chehab }; 968cb7a01acSMauro Carvalho Chehab 9695b38b0f8SManjunath Hadli static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = { 9705b38b0f8SManjunath Hadli .enum_mbus_code = tvp514x_enum_mbus_code, 9715b38b0f8SManjunath Hadli .get_fmt = tvp514x_get_pad_format, 9725b38b0f8SManjunath Hadli .set_fmt = tvp514x_set_pad_format, 9735b38b0f8SManjunath Hadli }; 9745b38b0f8SManjunath Hadli 975cb7a01acSMauro Carvalho Chehab static const struct v4l2_subdev_ops tvp514x_ops = { 976cb7a01acSMauro Carvalho Chehab .video = &tvp514x_video_ops, 9775b38b0f8SManjunath Hadli .pad = &tvp514x_pad_ops, 978cb7a01acSMauro Carvalho Chehab }; 979cb7a01acSMauro Carvalho Chehab 980db83d08dSJulia Lawall static const struct tvp514x_decoder tvp514x_dev = { 981cb7a01acSMauro Carvalho Chehab .streaming = 0, 9825b38b0f8SManjunath Hadli .fmt_list = tvp514x_fmt_list, 9835b38b0f8SManjunath Hadli .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), 9845b38b0f8SManjunath Hadli .pix = { 9855b38b0f8SManjunath Hadli /* Default to NTSC 8-bit YUV 422 */ 9865b38b0f8SManjunath Hadli .width = NTSC_NUM_ACTIVE_PIXELS, 9875b38b0f8SManjunath Hadli .height = NTSC_NUM_ACTIVE_LINES, 9885b38b0f8SManjunath Hadli .pixelformat = V4L2_PIX_FMT_UYVY, 9895b38b0f8SManjunath Hadli .field = V4L2_FIELD_INTERLACED, 9905b38b0f8SManjunath Hadli .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, 9915b38b0f8SManjunath Hadli .sizeimage = NTSC_NUM_ACTIVE_PIXELS * 2 * 9925b38b0f8SManjunath Hadli NTSC_NUM_ACTIVE_LINES, 9935b38b0f8SManjunath Hadli .colorspace = V4L2_COLORSPACE_SMPTE170M, 9945b38b0f8SManjunath Hadli }, 995cb7a01acSMauro Carvalho Chehab .current_std = STD_NTSC_MJ, 996cb7a01acSMauro Carvalho Chehab .std_list = tvp514x_std_list, 997cb7a01acSMauro Carvalho Chehab .num_stds = ARRAY_SIZE(tvp514x_std_list), 998cb7a01acSMauro Carvalho Chehab 999cb7a01acSMauro Carvalho Chehab }; 1000cb7a01acSMauro Carvalho Chehab 1001b610b592SLad, Prabhakar static struct tvp514x_platform_data * 1002b610b592SLad, Prabhakar tvp514x_get_pdata(struct i2c_client *client) 1003b610b592SLad, Prabhakar { 1004fe1e6ac6SJavier Martinez Canillas struct tvp514x_platform_data *pdata = NULL; 1005859969b3SSakari Ailus struct v4l2_fwnode_endpoint bus_cfg; 1006b610b592SLad, Prabhakar struct device_node *endpoint; 1007b610b592SLad, Prabhakar unsigned int flags; 1008b610b592SLad, Prabhakar 1009b610b592SLad, Prabhakar if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) 1010b610b592SLad, Prabhakar return client->dev.platform_data; 1011b610b592SLad, Prabhakar 1012fd9fdb78SPhilipp Zabel endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); 1013b610b592SLad, Prabhakar if (!endpoint) 1014b610b592SLad, Prabhakar return NULL; 1015b610b592SLad, Prabhakar 1016859969b3SSakari Ailus if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg)) 1017fe1e6ac6SJavier Martinez Canillas goto done; 1018fe1e6ac6SJavier Martinez Canillas 1019b610b592SLad, Prabhakar pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); 1020b610b592SLad, Prabhakar if (!pdata) 1021b610b592SLad, Prabhakar goto done; 1022b610b592SLad, Prabhakar 1023b610b592SLad, Prabhakar flags = bus_cfg.bus.parallel.flags; 1024b610b592SLad, Prabhakar 1025b610b592SLad, Prabhakar if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) 1026b610b592SLad, Prabhakar pdata->hs_polarity = 1; 1027b610b592SLad, Prabhakar 1028b610b592SLad, Prabhakar if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) 1029b610b592SLad, Prabhakar pdata->vs_polarity = 1; 1030b610b592SLad, Prabhakar 1031b610b592SLad, Prabhakar if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) 1032b610b592SLad, Prabhakar pdata->clk_polarity = 1; 1033b610b592SLad, Prabhakar 1034b610b592SLad, Prabhakar done: 1035b610b592SLad, Prabhakar of_node_put(endpoint); 1036b610b592SLad, Prabhakar return pdata; 1037b610b592SLad, Prabhakar } 1038b610b592SLad, Prabhakar 1039cb7a01acSMauro Carvalho Chehab /** 1040cb7a01acSMauro Carvalho Chehab * tvp514x_probe() - decoder driver i2c probe handler 1041cb7a01acSMauro Carvalho Chehab * @client: i2c driver client device structure 1042cb7a01acSMauro Carvalho Chehab * @id: i2c driver id table 1043cb7a01acSMauro Carvalho Chehab * 1044cb7a01acSMauro Carvalho Chehab * Register decoder as an i2c client device and V4L2 1045cb7a01acSMauro Carvalho Chehab * device. 1046cb7a01acSMauro Carvalho Chehab */ 1047cb7a01acSMauro Carvalho Chehab static int 1048cb7a01acSMauro Carvalho Chehab tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) 1049cb7a01acSMauro Carvalho Chehab { 1050b610b592SLad, Prabhakar struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); 1051cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder; 1052cb7a01acSMauro Carvalho Chehab struct v4l2_subdev *sd; 10535b38b0f8SManjunath Hadli int ret; 1054cb7a01acSMauro Carvalho Chehab 1055b610b592SLad, Prabhakar if (pdata == NULL) { 1056b610b592SLad, Prabhakar dev_err(&client->dev, "No platform data\n"); 1057b610b592SLad, Prabhakar return -EINVAL; 1058b610b592SLad, Prabhakar } 1059b610b592SLad, Prabhakar 1060cb7a01acSMauro Carvalho Chehab /* Check if the adapter supports the needed features */ 1061cb7a01acSMauro Carvalho Chehab if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1062cb7a01acSMauro Carvalho Chehab return -EIO; 1063cb7a01acSMauro Carvalho Chehab 106408754d31SLad, Prabhakar decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); 1065cb7a01acSMauro Carvalho Chehab if (!decoder) 1066cb7a01acSMauro Carvalho Chehab return -ENOMEM; 1067cb7a01acSMauro Carvalho Chehab 1068cb7a01acSMauro Carvalho Chehab /* Initialize the tvp514x_decoder with default configuration */ 1069cb7a01acSMauro Carvalho Chehab *decoder = tvp514x_dev; 1070cb7a01acSMauro Carvalho Chehab /* Copy default register configuration */ 1071cb7a01acSMauro Carvalho Chehab memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, 1072cb7a01acSMauro Carvalho Chehab sizeof(tvp514x_reg_list_default)); 1073cb7a01acSMauro Carvalho Chehab 1074f0a12d0cSLars-Peter Clausen decoder->int_seq = (struct tvp514x_reg *)id->driver_data; 1075f0a12d0cSLars-Peter Clausen 1076cb7a01acSMauro Carvalho Chehab /* Copy board specific information here */ 1077b610b592SLad, Prabhakar decoder->pdata = pdata; 1078cb7a01acSMauro Carvalho Chehab 1079cb7a01acSMauro Carvalho Chehab /** 1080cb7a01acSMauro Carvalho Chehab * Fetch platform specific data, and configure the 1081cb7a01acSMauro Carvalho Chehab * tvp514x_reg_list[] accordingly. Since this is one 1082cb7a01acSMauro Carvalho Chehab * time configuration, no need to preserve. 1083cb7a01acSMauro Carvalho Chehab */ 1084cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |= 1085cb7a01acSMauro Carvalho Chehab (decoder->pdata->clk_polarity << 1); 1086cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_SYNC_CONTROL].val |= 1087cb7a01acSMauro Carvalho Chehab ((decoder->pdata->hs_polarity << 2) | 1088cb7a01acSMauro Carvalho Chehab (decoder->pdata->vs_polarity << 3)); 1089cb7a01acSMauro Carvalho Chehab /* Set default standard to auto */ 1090cb7a01acSMauro Carvalho Chehab decoder->tvp514x_regs[REG_VIDEO_STD].val = 1091cb7a01acSMauro Carvalho Chehab VIDEO_STD_AUTO_SWITCH_BIT; 1092cb7a01acSMauro Carvalho Chehab 1093cb7a01acSMauro Carvalho Chehab /* Register with V4L2 layer as slave device */ 1094cb7a01acSMauro Carvalho Chehab sd = &decoder->sd; 1095cb7a01acSMauro Carvalho Chehab v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); 1096cb7a01acSMauro Carvalho Chehab 10975b38b0f8SManjunath Hadli #if defined(CONFIG_MEDIA_CONTROLLER) 10985b38b0f8SManjunath Hadli decoder->pad.flags = MEDIA_PAD_FL_SOURCE; 10995b38b0f8SManjunath Hadli decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 11004ca72efaSMauro Carvalho Chehab decoder->sd.entity.flags |= MEDIA_ENT_F_ATV_DECODER; 11015b38b0f8SManjunath Hadli 1102ab22e77cSMauro Carvalho Chehab ret = media_entity_pads_init(&decoder->sd.entity, 1, &decoder->pad); 11035b38b0f8SManjunath Hadli if (ret < 0) { 11045b38b0f8SManjunath Hadli v4l2_err(sd, "%s decoder driver failed to register !!\n", 11055b38b0f8SManjunath Hadli sd->name); 11065b38b0f8SManjunath Hadli return ret; 11075b38b0f8SManjunath Hadli } 11085b38b0f8SManjunath Hadli #endif 1109cb7a01acSMauro Carvalho Chehab v4l2_ctrl_handler_init(&decoder->hdl, 5); 1110cb7a01acSMauro Carvalho Chehab v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, 1111cb7a01acSMauro Carvalho Chehab V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 1112cb7a01acSMauro Carvalho Chehab v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, 1113cb7a01acSMauro Carvalho Chehab V4L2_CID_CONTRAST, 0, 255, 1, 128); 1114cb7a01acSMauro Carvalho Chehab v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, 1115cb7a01acSMauro Carvalho Chehab V4L2_CID_SATURATION, 0, 255, 1, 128); 1116cb7a01acSMauro Carvalho Chehab v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, 1117cb7a01acSMauro Carvalho Chehab V4L2_CID_HUE, -180, 180, 180, 0); 1118cb7a01acSMauro Carvalho Chehab v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, 1119cb7a01acSMauro Carvalho Chehab V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 1120cb7a01acSMauro Carvalho Chehab sd->ctrl_handler = &decoder->hdl; 1121cb7a01acSMauro Carvalho Chehab if (decoder->hdl.error) { 11225b38b0f8SManjunath Hadli ret = decoder->hdl.error; 11238f23acb5SLad, Prabhakar goto done; 1124cb7a01acSMauro Carvalho Chehab } 1125cb7a01acSMauro Carvalho Chehab v4l2_ctrl_handler_setup(&decoder->hdl); 1126cb7a01acSMauro Carvalho Chehab 11278f23acb5SLad, Prabhakar ret = v4l2_async_register_subdev(&decoder->sd); 11288f23acb5SLad, Prabhakar if (!ret) 1129cb7a01acSMauro Carvalho Chehab v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); 1130cb7a01acSMauro Carvalho Chehab 11318f23acb5SLad, Prabhakar done: 11328f23acb5SLad, Prabhakar if (ret < 0) { 11338f23acb5SLad, Prabhakar v4l2_ctrl_handler_free(&decoder->hdl); 11348f23acb5SLad, Prabhakar #if defined(CONFIG_MEDIA_CONTROLLER) 11358f23acb5SLad, Prabhakar media_entity_cleanup(&decoder->sd.entity); 11368f23acb5SLad, Prabhakar #endif 11378f23acb5SLad, Prabhakar } 11388f23acb5SLad, Prabhakar return ret; 1139cb7a01acSMauro Carvalho Chehab } 1140cb7a01acSMauro Carvalho Chehab 1141cb7a01acSMauro Carvalho Chehab /** 1142cb7a01acSMauro Carvalho Chehab * tvp514x_remove() - decoder driver i2c remove handler 1143cb7a01acSMauro Carvalho Chehab * @client: i2c driver client device structure 1144cb7a01acSMauro Carvalho Chehab * 1145cb7a01acSMauro Carvalho Chehab * Unregister decoder as an i2c client device and V4L2 1146cb7a01acSMauro Carvalho Chehab * device. Complement of tvp514x_probe(). 1147cb7a01acSMauro Carvalho Chehab */ 1148cb7a01acSMauro Carvalho Chehab static int tvp514x_remove(struct i2c_client *client) 1149cb7a01acSMauro Carvalho Chehab { 1150cb7a01acSMauro Carvalho Chehab struct v4l2_subdev *sd = i2c_get_clientdata(client); 1151cb7a01acSMauro Carvalho Chehab struct tvp514x_decoder *decoder = to_decoder(sd); 1152cb7a01acSMauro Carvalho Chehab 11538f23acb5SLad, Prabhakar v4l2_async_unregister_subdev(&decoder->sd); 11545b38b0f8SManjunath Hadli #if defined(CONFIG_MEDIA_CONTROLLER) 11555b38b0f8SManjunath Hadli media_entity_cleanup(&decoder->sd.entity); 11565b38b0f8SManjunath Hadli #endif 1157cb7a01acSMauro Carvalho Chehab v4l2_ctrl_handler_free(&decoder->hdl); 1158cb7a01acSMauro Carvalho Chehab return 0; 1159cb7a01acSMauro Carvalho Chehab } 1160cb7a01acSMauro Carvalho Chehab /* TVP5146 Init/Power on Sequence */ 1161cb7a01acSMauro Carvalho Chehab static const struct tvp514x_reg tvp5146_init_reg_seq[] = { 1162cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, 1163cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1164cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, 1165cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, 1166cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, 1167cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1168cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, 1169cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, 1170cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, 1171cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x01}, 1172cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x00}, 1173cb7a01acSMauro Carvalho Chehab {TOK_TERM, 0, 0}, 1174cb7a01acSMauro Carvalho Chehab }; 1175cb7a01acSMauro Carvalho Chehab 1176cb7a01acSMauro Carvalho Chehab /* TVP5147 Init/Power on Sequence */ 1177cb7a01acSMauro Carvalho Chehab static const struct tvp514x_reg tvp5147_init_reg_seq[] = { 1178cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, 1179cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1180cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, 1181cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, 1182cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, 1183cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1184cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, 1185cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, 1186cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x16}, 1187cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1188cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xA0}, 1189cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x16}, 1190cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, 1191cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, 1192cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, 1193cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, 1194cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x01}, 1195cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x00}, 1196cb7a01acSMauro Carvalho Chehab {TOK_TERM, 0, 0}, 1197cb7a01acSMauro Carvalho Chehab }; 1198cb7a01acSMauro Carvalho Chehab 1199cb7a01acSMauro Carvalho Chehab /* TVP5146M2/TVP5147M1 Init/Power on Sequence */ 1200cb7a01acSMauro Carvalho Chehab static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { 1201cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x01}, 1202cb7a01acSMauro Carvalho Chehab {TOK_WRITE, REG_OPERATION_MODE, 0x00}, 1203cb7a01acSMauro Carvalho Chehab {TOK_TERM, 0, 0}, 1204cb7a01acSMauro Carvalho Chehab }; 1205cb7a01acSMauro Carvalho Chehab 1206c5bb8318SMauro Carvalho Chehab /* 1207cb7a01acSMauro Carvalho Chehab * I2C Device Table - 1208cb7a01acSMauro Carvalho Chehab * 1209cb7a01acSMauro Carvalho Chehab * name - Name of the actual device/chip. 1210cb7a01acSMauro Carvalho Chehab * driver_data - Driver data 1211cb7a01acSMauro Carvalho Chehab */ 1212cb7a01acSMauro Carvalho Chehab static const struct i2c_device_id tvp514x_id[] = { 1213cb7a01acSMauro Carvalho Chehab {"tvp5146", (unsigned long)tvp5146_init_reg_seq}, 1214cb7a01acSMauro Carvalho Chehab {"tvp5146m2", (unsigned long)tvp514xm_init_reg_seq}, 1215cb7a01acSMauro Carvalho Chehab {"tvp5147", (unsigned long)tvp5147_init_reg_seq}, 1216cb7a01acSMauro Carvalho Chehab {"tvp5147m1", (unsigned long)tvp514xm_init_reg_seq}, 1217cb7a01acSMauro Carvalho Chehab {}, 1218cb7a01acSMauro Carvalho Chehab }; 1219cb7a01acSMauro Carvalho Chehab 1220cb7a01acSMauro Carvalho Chehab MODULE_DEVICE_TABLE(i2c, tvp514x_id); 1221cb7a01acSMauro Carvalho Chehab 1222b610b592SLad, Prabhakar #if IS_ENABLED(CONFIG_OF) 1223b610b592SLad, Prabhakar static const struct of_device_id tvp514x_of_match[] = { 1224b610b592SLad, Prabhakar { .compatible = "ti,tvp5146", }, 1225b610b592SLad, Prabhakar { .compatible = "ti,tvp5146m2", }, 1226b610b592SLad, Prabhakar { .compatible = "ti,tvp5147", }, 1227b610b592SLad, Prabhakar { .compatible = "ti,tvp5147m1", }, 1228b610b592SLad, Prabhakar { /* sentinel */ }, 1229b610b592SLad, Prabhakar }; 1230b610b592SLad, Prabhakar MODULE_DEVICE_TABLE(of, tvp514x_of_match); 1231b610b592SLad, Prabhakar #endif 1232b610b592SLad, Prabhakar 1233cb7a01acSMauro Carvalho Chehab static struct i2c_driver tvp514x_driver = { 1234cb7a01acSMauro Carvalho Chehab .driver = { 1235b610b592SLad, Prabhakar .of_match_table = of_match_ptr(tvp514x_of_match), 1236cb7a01acSMauro Carvalho Chehab .name = TVP514X_MODULE_NAME, 1237cb7a01acSMauro Carvalho Chehab }, 1238cb7a01acSMauro Carvalho Chehab .probe = tvp514x_probe, 1239cb7a01acSMauro Carvalho Chehab .remove = tvp514x_remove, 1240cb7a01acSMauro Carvalho Chehab .id_table = tvp514x_id, 1241cb7a01acSMauro Carvalho Chehab }; 1242cb7a01acSMauro Carvalho Chehab 1243cb7a01acSMauro Carvalho Chehab module_i2c_driver(tvp514x_driver); 1244