10c0d06caSMauro Carvalho Chehab /*
20c0d06caSMauro Carvalho Chehab    cx231xx-cards.c - driver for Conexant Cx23100/101/102
30c0d06caSMauro Carvalho Chehab 				USB video capture devices
40c0d06caSMauro Carvalho Chehab 
50c0d06caSMauro Carvalho Chehab    Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
60c0d06caSMauro Carvalho Chehab 				Based on em28xx driver
70c0d06caSMauro Carvalho Chehab 
80c0d06caSMauro Carvalho Chehab    This program is free software; you can redistribute it and/or modify
90c0d06caSMauro Carvalho Chehab    it under the terms of the GNU General Public License as published by
100c0d06caSMauro Carvalho Chehab    the Free Software Foundation; either version 2 of the License, or
110c0d06caSMauro Carvalho Chehab    (at your option) any later version.
120c0d06caSMauro Carvalho Chehab 
130c0d06caSMauro Carvalho Chehab    This program is distributed in the hope that it will be useful,
140c0d06caSMauro Carvalho Chehab    but WITHOUT ANY WARRANTY; without even the implied warranty of
150c0d06caSMauro Carvalho Chehab    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160c0d06caSMauro Carvalho Chehab    GNU General Public License for more details.
170c0d06caSMauro Carvalho Chehab 
180c0d06caSMauro Carvalho Chehab    You should have received a copy of the GNU General Public License
190c0d06caSMauro Carvalho Chehab    along with this program; if not, write to the Free Software
200c0d06caSMauro Carvalho Chehab    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
210c0d06caSMauro Carvalho Chehab  */
220c0d06caSMauro Carvalho Chehab 
23589dadf2SMauro Carvalho Chehab #include "cx231xx.h"
240c0d06caSMauro Carvalho Chehab #include <linux/init.h>
250c0d06caSMauro Carvalho Chehab #include <linux/module.h>
260c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
270c0d06caSMauro Carvalho Chehab #include <linux/delay.h>
280c0d06caSMauro Carvalho Chehab #include <linux/i2c.h>
290c0d06caSMauro Carvalho Chehab #include <media/tuner.h>
300c0d06caSMauro Carvalho Chehab #include <media/tveeprom.h>
310c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
320c0d06caSMauro Carvalho Chehab 
33d647f0b7SMauro Carvalho Chehab #include <media/drv-intf/cx25840.h>
34fada1935SMauro Carvalho Chehab #include <media/dvb-usb-ids.h>
350c0d06caSMauro Carvalho Chehab #include "xc5000.h"
360c0d06caSMauro Carvalho Chehab #include "tda18271.h"
370c0d06caSMauro Carvalho Chehab 
380c0d06caSMauro Carvalho Chehab 
390c0d06caSMauro Carvalho Chehab static int tuner = -1;
400c0d06caSMauro Carvalho Chehab module_param(tuner, int, 0444);
410c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(tuner, "tuner type");
420c0d06caSMauro Carvalho Chehab 
430c0d06caSMauro Carvalho Chehab static int transfer_mode = 1;
440c0d06caSMauro Carvalho Chehab module_param(transfer_mode, int, 0444);
450c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)");
460c0d06caSMauro Carvalho Chehab 
470c0d06caSMauro Carvalho Chehab static unsigned int disable_ir;
480c0d06caSMauro Carvalho Chehab module_param(disable_ir, int, 0444);
490c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
500c0d06caSMauro Carvalho Chehab 
510c0d06caSMauro Carvalho Chehab /* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */
520c0d06caSMauro Carvalho Chehab static unsigned long cx231xx_devused;
530c0d06caSMauro Carvalho Chehab 
540c0d06caSMauro Carvalho Chehab /*
550c0d06caSMauro Carvalho Chehab  *  Reset sequences for analog/digital modes
560c0d06caSMauro Carvalho Chehab  */
570c0d06caSMauro Carvalho Chehab 
580c0d06caSMauro Carvalho Chehab static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = {
590c0d06caSMauro Carvalho Chehab 	{0x03, 0x01, 10},
600c0d06caSMauro Carvalho Chehab 	{0x03, 0x00, 30},
610c0d06caSMauro Carvalho Chehab 	{0x03, 0x01, 10},
620c0d06caSMauro Carvalho Chehab 	{-1, -1, -1},
630c0d06caSMauro Carvalho Chehab };
640c0d06caSMauro Carvalho Chehab 
650c0d06caSMauro Carvalho Chehab /*
660c0d06caSMauro Carvalho Chehab  *  Board definitions
670c0d06caSMauro Carvalho Chehab  */
680c0d06caSMauro Carvalho Chehab struct cx231xx_board cx231xx_boards[] = {
690c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_UNKNOWN] = {
700c0d06caSMauro Carvalho Chehab 		.name = "Unknown CX231xx video grabber",
710c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
720c0d06caSMauro Carvalho Chehab 		.input = {{
730c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
740c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
750c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
760c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
770c0d06caSMauro Carvalho Chehab 			}, {
780c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
790c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
800c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
810c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
820c0d06caSMauro Carvalho Chehab 			}, {
830c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
840c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
850c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
860c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
870c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
880c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
890c0d06caSMauro Carvalho Chehab 			}
900c0d06caSMauro Carvalho Chehab 		},
910c0d06caSMauro Carvalho Chehab 	},
920c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_CARRAERA] = {
930c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - CARRAERA",
940c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
950c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
960c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
970c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
980c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
990c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
1000c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
1010c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
1020c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
1030c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
1040c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
1050c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
106b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
107d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
1080c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
1090c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
1100c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
1110c0d06caSMauro Carvalho Chehab 
1120c0d06caSMauro Carvalho Chehab 		.input = {{
1130c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1140c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1150c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1160c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1170c0d06caSMauro Carvalho Chehab 			}, {
1180c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1190c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
1200c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1210c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1220c0d06caSMauro Carvalho Chehab 			}, {
1230c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
1240c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
1250c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
1260c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
1270c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1280c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1290c0d06caSMauro Carvalho Chehab 			}
1300c0d06caSMauro Carvalho Chehab 		},
1310c0d06caSMauro Carvalho Chehab 	},
1320c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_SHELBY] = {
1330c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - SHELBY",
1340c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
1350c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
1360c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
1370c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
1380c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
1390c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
1400c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
1410c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
1420c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
1430c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
1440c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
1450c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
146b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
147d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
1480c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
1490c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x32,
1500c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
1510c0d06caSMauro Carvalho Chehab 
1520c0d06caSMauro Carvalho Chehab 		.input = {{
1530c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1540c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1550c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1560c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1570c0d06caSMauro Carvalho Chehab 			}, {
1580c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1590c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
1600c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1610c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1620c0d06caSMauro Carvalho Chehab 			}, {
1630c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
1640c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
1650c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
1660c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
1670c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1680c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1690c0d06caSMauro Carvalho Chehab 			}
1700c0d06caSMauro Carvalho Chehab 		},
1710c0d06caSMauro Carvalho Chehab 	},
1720c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDE_253S] = {
1730c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDE253S",
1740c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
1750c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
1760c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
1770c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
1780c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
1790c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
1800c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
1810c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
1820c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
1830c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
1840c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
1850c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
186b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
187d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
1880c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
1890c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
1900c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
1910c0d06caSMauro Carvalho Chehab 
1920c0d06caSMauro Carvalho Chehab 		.input = {{
1930c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1940c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1950c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1960c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1970c0d06caSMauro Carvalho Chehab 			}, {
1980c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1990c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2000c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2010c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2020c0d06caSMauro Carvalho Chehab 			}, {
2030c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
2040c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
2050c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
2060c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
2070c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2080c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2090c0d06caSMauro Carvalho Chehab 			}
2100c0d06caSMauro Carvalho Chehab 		},
2110c0d06caSMauro Carvalho Chehab 	},
2120c0d06caSMauro Carvalho Chehab 
2130c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDU_253S] = {
2140c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDU253S",
2150c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
2160c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
2170c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
2180c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
2190c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
2200c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
2210c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2220c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2230c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
2240c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2250c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
2260c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
227b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
228d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
2290c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
2300c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
2310c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
2320c0d06caSMauro Carvalho Chehab 
2330c0d06caSMauro Carvalho Chehab 		.input = {{
2340c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
2350c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
2360c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
2370c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2380c0d06caSMauro Carvalho Chehab 			}, {
2390c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
2400c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2410c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2420c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2430c0d06caSMauro Carvalho Chehab 			}, {
2440c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
2450c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
2460c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
2470c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
2480c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2490c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2500c0d06caSMauro Carvalho Chehab 			}
2510c0d06caSMauro Carvalho Chehab 		},
2520c0d06caSMauro Carvalho Chehab 	},
2530c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_VIDEO_GRABBER] = {
2540c0d06caSMauro Carvalho Chehab 		.name = "Conexant VIDEO GRABBER",
2550c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
2560c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2570c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2580c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2590c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
2600c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
2610c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
2620c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
2630c0d06caSMauro Carvalho Chehab 		.external_av = 1,
264b31077a8SHans Verkuil 		/* Actually, it has a 417, but it isn't working correctly.
265b31077a8SHans Verkuil 		 * So set to 0 for now until someone can manage to get this
266b31077a8SHans Verkuil 		 * to work reliably. */
267b31077a8SHans Verkuil 		.has_417 = 0,
2680c0d06caSMauro Carvalho Chehab 
2690c0d06caSMauro Carvalho Chehab 		.input = {{
2700c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
2710c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2720c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2730c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2740c0d06caSMauro Carvalho Chehab 			}, {
2750c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
2760c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
2770c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
2780c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
2790c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2800c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2810c0d06caSMauro Carvalho Chehab 			}
2820c0d06caSMauro Carvalho Chehab 		},
2830c0d06caSMauro Carvalho Chehab 	},
2840c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDE_250] = {
2850c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - rde 250",
2860c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
2870c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
2880c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
2890c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
2900c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
2910c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
2920c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2930c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2940c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
2950c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2960c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
2970c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
298b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
299d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
3000c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
3010c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
3020c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
3030c0d06caSMauro Carvalho Chehab 
3040c0d06caSMauro Carvalho Chehab 		.input = {{
3050c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
3060c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
3070c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
3080c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
3090c0d06caSMauro Carvalho Chehab 			}
3100c0d06caSMauro Carvalho Chehab 		},
3110c0d06caSMauro Carvalho Chehab 	},
3120c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDU_250] = {
3130c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDU 250",
3140c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
3150c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
3160c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
3170c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
3180c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
3190c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
3200c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3210c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3220c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3230c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3240c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3250c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
326b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
327d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
3280c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
3290c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x32,
3300c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3310c0d06caSMauro Carvalho Chehab 
3320c0d06caSMauro Carvalho Chehab 		.input = {{
3330c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
3340c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
3350c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
3360c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
3370c0d06caSMauro Carvalho Chehab 			}
3380c0d06caSMauro Carvalho Chehab 		},
3390c0d06caSMauro Carvalho Chehab 	},
3400c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_EXETER] = {
3410c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge EXETER",
3420c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
3430c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
3440c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
3450c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
3460c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
3470c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
3480c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3490c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3500c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3510c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3520c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3530c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
354b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_1,
355599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_1,
3560c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
3570c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x0e,
3580c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3590c0d06caSMauro Carvalho Chehab 
3600c0d06caSMauro Carvalho Chehab 		.input = {{
3610c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
3620c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
3630c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
3640c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3650c0d06caSMauro Carvalho Chehab 		}, {
3660c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
3670c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
3680c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3690c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3700c0d06caSMauro Carvalho Chehab 		}, {
3710c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
3720c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
3730c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
3740c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
3750c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3760c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3770c0d06caSMauro Carvalho Chehab 		} },
3780c0d06caSMauro Carvalho Chehab 	},
3790c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = {
3800c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge USB Live 2",
3810c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
3820c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3830c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3840c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3850c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3860c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3870c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
3880c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3890c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
3900c0d06caSMauro Carvalho Chehab 		.external_av = 1,
3910c0d06caSMauro Carvalho Chehab 		.input = {{
3920c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
3930c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
3940c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3950c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3960c0d06caSMauro Carvalho Chehab 		}, {
3970c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
3980c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
3990c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
4000c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
4010c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4020c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4030c0d06caSMauro Carvalho Chehab 		} },
4040c0d06caSMauro Carvalho Chehab 	},
4050c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = {
4060c0d06caSMauro Carvalho Chehab 		.name = "Kworld UB430 USB Hybrid",
4070c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
4080c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
4090c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
4100c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
4110c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
4120c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
4130c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x11,	/* According with PV cxPolaris.inf file */
4140c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = -1,
4150c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = -1,
4160c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = -1,
4170c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
418d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
419b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
420d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4210c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
4220c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x10,
4230c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL_M,
4240c0d06caSMauro Carvalho Chehab 		.input = {{
4250c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
4260c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
4270c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
4280c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4290c0d06caSMauro Carvalho Chehab 		}, {
4300c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
4310c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
4320c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4330c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4340c0d06caSMauro Carvalho Chehab 		}, {
4350c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
4360c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
4370c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
4380c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
4390c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4400c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4410c0d06caSMauro Carvalho Chehab 		} },
4420c0d06caSMauro Carvalho Chehab 	},
4438b1255a2SJohannes Erdfelt 	[CX231XX_BOARD_KWORLD_UB445_USB_HYBRID] = {
4448b1255a2SJohannes Erdfelt 		.name = "Kworld UB445 USB Hybrid",
4458b1255a2SJohannes Erdfelt 		.tuner_type = TUNER_NXP_TDA18271,
4468b1255a2SJohannes Erdfelt 		.tuner_addr = 0x60,
4478b1255a2SJohannes Erdfelt 		.decoder = CX231XX_AVDECODER,
4488b1255a2SJohannes Erdfelt 		.output_mode = OUT_MODE_VIP11,
4498b1255a2SJohannes Erdfelt 		.demod_xfer_mode = 0,
4508b1255a2SJohannes Erdfelt 		.ctl_pin_status_mask = 0xFFFFFFC4,
4518b1255a2SJohannes Erdfelt 		.agc_analog_digital_select_gpio = 0x11,	/* According with PV cxPolaris.inf file */
4528b1255a2SJohannes Erdfelt 		.tuner_sif_gpio = -1,
4538b1255a2SJohannes Erdfelt 		.tuner_scl_gpio = -1,
4548b1255a2SJohannes Erdfelt 		.tuner_sda_gpio = -1,
4558b1255a2SJohannes Erdfelt 		.gpio_pin_status_mask = 0x4001000,
456d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
457b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
458d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4598b1255a2SJohannes Erdfelt 		.has_dvb = 1,
4608b1255a2SJohannes Erdfelt 		.demod_addr = 0x10,
4618b1255a2SJohannes Erdfelt 		.norm = V4L2_STD_NTSC_M,
4628b1255a2SJohannes Erdfelt 		.input = {{
4638b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_TELEVISION,
4648b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_3_1,
4658b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_VIDEO,
4668b1255a2SJohannes Erdfelt 			.gpio = NULL,
4678b1255a2SJohannes Erdfelt 		}, {
4688b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_COMPOSITE1,
4698b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_2_1,
4708b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_LINE_IN,
4718b1255a2SJohannes Erdfelt 			.gpio = NULL,
4728b1255a2SJohannes Erdfelt 		}, {
4738b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_SVIDEO,
4748b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_1_1 |
4758b1255a2SJohannes Erdfelt 				(CX231XX_VIN_1_2 << 8) |
4768b1255a2SJohannes Erdfelt 				CX25840_SVIDEO_ON,
4778b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_LINE_IN,
4788b1255a2SJohannes Erdfelt 			.gpio = NULL,
4798b1255a2SJohannes Erdfelt 		} },
4808b1255a2SJohannes Erdfelt 	},
4810c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
4820c0d06caSMauro Carvalho Chehab 		.name = "Pixelview PlayTV USB Hybrid",
4830c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
4840c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
4850c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
4860c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
4870c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
4880c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
48924b923f0SMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
4900c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = -1,
4910c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = -1,
4920c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = -1,
4930c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
494d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
495b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
496d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4970c0d06caSMauro Carvalho Chehab 		.rc_map_name = RC_MAP_PIXELVIEW_002T,
4980c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
4990c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x10,
5000c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL_M,
5010c0d06caSMauro Carvalho Chehab 		.input = {{
5020c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
5030c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
5040c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
5050c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5060c0d06caSMauro Carvalho Chehab 		}, {
5070c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
5080c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
5090c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5100c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5110c0d06caSMauro Carvalho Chehab 		}, {
5120c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
5130c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
5140c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
5150c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
5160c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5170c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5180c0d06caSMauro Carvalho Chehab 		} },
5190c0d06caSMauro Carvalho Chehab 	},
5200c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_PV_XCAPTURE_USB] = {
5210c0d06caSMauro Carvalho Chehab 		.name = "Pixelview Xcapture USB",
5220c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
5230c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5240c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5250c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
5260c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5270c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
5280c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
5290c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
5300c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
5310c0d06caSMauro Carvalho Chehab 		.external_av = 1,
5320c0d06caSMauro Carvalho Chehab 
5330c0d06caSMauro Carvalho Chehab 		.input = {{
5340c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
5350c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
5360c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
5370c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
5380c0d06caSMauro Carvalho Chehab 			}, {
5390c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
5400c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
5410c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
5420c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
5430c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
5440c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
5450c0d06caSMauro Carvalho Chehab 			}
5460c0d06caSMauro Carvalho Chehab 		},
5470c0d06caSMauro Carvalho Chehab 	},
5480c0d06caSMauro Carvalho Chehab 
5490c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_ICONBIT_U100] = {
5500c0d06caSMauro Carvalho Chehab 		.name = "Iconbit Analog Stick U100 FM",
5510c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
5520c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5530c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5540c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
5550c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5560c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1C,
5570c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
5580c0d06caSMauro Carvalho Chehab 
5590c0d06caSMauro Carvalho Chehab 		.input = {{
5600c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
5610c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
5620c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5630c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5640c0d06caSMauro Carvalho Chehab 		}, {
5650c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
5660c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
5670c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
5680c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
5690c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5700c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5710c0d06caSMauro Carvalho Chehab 		} },
5720c0d06caSMauro Carvalho Chehab 	},
5730c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
5740c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge WinTV USB2 FM (PAL)",
5750c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
5760c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
5770c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
5780c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
5790c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
5800c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
5810c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5820c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5830c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5840c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
5850c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
586b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
5870c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
5880c0d06caSMauro Carvalho Chehab 
5890c0d06caSMauro Carvalho Chehab 		.input = {{
5900c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
5910c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
5920c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
5930c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5940c0d06caSMauro Carvalho Chehab 		}, {
5950c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
5960c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
5970c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5980c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5990c0d06caSMauro Carvalho Chehab 		}, {
6000c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
6010c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
6020c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
6030c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
6040c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
6050c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6060c0d06caSMauro Carvalho Chehab 		} },
6070c0d06caSMauro Carvalho Chehab 	},
6080c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
6090c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge WinTV USB2 FM (NTSC)",
6100c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
6110c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
6120c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
6130c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
6140c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
6150c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
6160c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
6170c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
6180c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
6190c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
6200c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
621b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
6220c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
6230c0d06caSMauro Carvalho Chehab 
6240c0d06caSMauro Carvalho Chehab 		.input = {{
6250c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
6260c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
6270c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
6280c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6290c0d06caSMauro Carvalho Chehab 		}, {
6300c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
6310c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
6320c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
6330c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6340c0d06caSMauro Carvalho Chehab 		}, {
6350c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
6360c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
6370c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
6380c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
6390c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
6400c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6410c0d06caSMauro Carvalho Chehab 		} },
6420c0d06caSMauro Carvalho Chehab 	},
64368c97bf3SAlf Høgemark 	[CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2] = {
64468c97bf3SAlf Høgemark 		.name = "Elgato Video Capture V2",
64568c97bf3SAlf Høgemark 		.tuner_type = TUNER_ABSENT,
64668c97bf3SAlf Høgemark 		.decoder = CX231XX_AVDECODER,
64768c97bf3SAlf Høgemark 		.output_mode = OUT_MODE_VIP11,
64868c97bf3SAlf Høgemark 		.demod_xfer_mode = 0,
64968c97bf3SAlf Høgemark 		.ctl_pin_status_mask = 0xFFFFFFC4,
65068c97bf3SAlf Høgemark 		.agc_analog_digital_select_gpio = 0x0c,
65168c97bf3SAlf Høgemark 		.gpio_pin_status_mask = 0x4001000,
65268c97bf3SAlf Høgemark 		.norm = V4L2_STD_NTSC,
65368c97bf3SAlf Høgemark 		.no_alt_vanc = 1,
65468c97bf3SAlf Høgemark 		.external_av = 1,
65568c97bf3SAlf Høgemark 		.input = {{
65668c97bf3SAlf Høgemark 			.type = CX231XX_VMUX_COMPOSITE1,
65768c97bf3SAlf Høgemark 			.vmux = CX231XX_VIN_2_1,
65868c97bf3SAlf Høgemark 			.amux = CX231XX_AMUX_LINE_IN,
65968c97bf3SAlf Høgemark 			.gpio = NULL,
66068c97bf3SAlf Høgemark 		}, {
66168c97bf3SAlf Høgemark 			.type = CX231XX_VMUX_SVIDEO,
66268c97bf3SAlf Høgemark 			.vmux = CX231XX_VIN_1_1 |
66368c97bf3SAlf Høgemark 				(CX231XX_VIN_1_2 << 8) |
66468c97bf3SAlf Høgemark 				CX25840_SVIDEO_ON,
66568c97bf3SAlf Høgemark 			.amux = CX231XX_AMUX_LINE_IN,
66668c97bf3SAlf Høgemark 			.gpio = NULL,
66768c97bf3SAlf Høgemark 		} },
66868c97bf3SAlf Høgemark 	},
6693ead1ba3SMatt Gomboc 	[CX231XX_BOARD_OTG102] = {
6703ead1ba3SMatt Gomboc 		.name = "Geniatech OTG102",
6713ead1ba3SMatt Gomboc 		.tuner_type = TUNER_ABSENT,
6723ead1ba3SMatt Gomboc 		.decoder = CX231XX_AVDECODER,
6733ead1ba3SMatt Gomboc 		.output_mode = OUT_MODE_VIP11,
6743ead1ba3SMatt Gomboc 		.ctl_pin_status_mask = 0xFFFFFFC4,
6753ead1ba3SMatt Gomboc 		.agc_analog_digital_select_gpio = 0x0c,
6763ead1ba3SMatt Gomboc 			/* According with PV CxPlrCAP.inf file */
6773ead1ba3SMatt Gomboc 		.gpio_pin_status_mask = 0x4001000,
6783ead1ba3SMatt Gomboc 		.norm = V4L2_STD_NTSC,
6793ead1ba3SMatt Gomboc 		.no_alt_vanc = 1,
6803ead1ba3SMatt Gomboc 		.external_av = 1,
6813ead1ba3SMatt Gomboc 		/*.has_417 = 1, */
6823ead1ba3SMatt Gomboc 		/* This board is believed to have a hardware encoding chip
6833ead1ba3SMatt Gomboc 		 * supporting mpeg1/2/4, but as the 417 is apparently not
6843ead1ba3SMatt Gomboc 		 * working for the reference board it is not here either. */
6853ead1ba3SMatt Gomboc 
6863ead1ba3SMatt Gomboc 		.input = {{
6873ead1ba3SMatt Gomboc 				.type = CX231XX_VMUX_COMPOSITE1,
6883ead1ba3SMatt Gomboc 				.vmux = CX231XX_VIN_2_1,
6893ead1ba3SMatt Gomboc 				.amux = CX231XX_AMUX_LINE_IN,
6903ead1ba3SMatt Gomboc 				.gpio = NULL,
6913ead1ba3SMatt Gomboc 			}, {
6923ead1ba3SMatt Gomboc 				.type = CX231XX_VMUX_SVIDEO,
6933ead1ba3SMatt Gomboc 				.vmux = CX231XX_VIN_1_1 |
6943ead1ba3SMatt Gomboc 					(CX231XX_VIN_1_2 << 8) |
6953ead1ba3SMatt Gomboc 					CX25840_SVIDEO_ON,
6963ead1ba3SMatt Gomboc 				.amux = CX231XX_AMUX_LINE_IN,
6973ead1ba3SMatt Gomboc 				.gpio = NULL,
6983ead1ba3SMatt Gomboc 			}
6993ead1ba3SMatt Gomboc 		},
7003ead1ba3SMatt Gomboc 	},
701dd2e7dd2SMatthias Schwarzott 	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx] = {
70257cbf3efSMatthias Schwarzott 		.name = "Hauppauge WinTV 930C-HD (1113xx) / HVR-900H (111xxx) / PCTV QuatroStick 521e",
703dd2e7dd2SMatthias Schwarzott 		.tuner_type = TUNER_NXP_TDA18271,
704dd2e7dd2SMatthias Schwarzott 		.tuner_addr = 0x60,
705dd2e7dd2SMatthias Schwarzott 		.tuner_gpio = RDE250_XCV_TUNER,
706dd2e7dd2SMatthias Schwarzott 		.tuner_sif_gpio = 0x05,
707dd2e7dd2SMatthias Schwarzott 		.tuner_scl_gpio = 0x1a,
708dd2e7dd2SMatthias Schwarzott 		.tuner_sda_gpio = 0x1b,
709dd2e7dd2SMatthias Schwarzott 		.decoder = CX231XX_AVDECODER,
710dd2e7dd2SMatthias Schwarzott 		.output_mode = OUT_MODE_VIP11,
711dd2e7dd2SMatthias Schwarzott 		.demod_xfer_mode = 0,
712dd2e7dd2SMatthias Schwarzott 		.ctl_pin_status_mask = 0xFFFFFFC4,
713dd2e7dd2SMatthias Schwarzott 		.agc_analog_digital_select_gpio = 0x0c,
714dd2e7dd2SMatthias Schwarzott 		.gpio_pin_status_mask = 0x4001000,
715b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
716599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
717dd2e7dd2SMatthias Schwarzott 		.has_dvb = 1,
718dd2e7dd2SMatthias Schwarzott 		.demod_addr = 0x0e,
719dd2e7dd2SMatthias Schwarzott 		.norm = V4L2_STD_PAL,
720dd2e7dd2SMatthias Schwarzott 
721dd2e7dd2SMatthias Schwarzott 		.input = {{
722dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_TELEVISION,
723dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_3_1,
724dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_VIDEO,
725dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
726dd2e7dd2SMatthias Schwarzott 		}, {
727dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_COMPOSITE1,
728dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_2_1,
729dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
730dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
731dd2e7dd2SMatthias Schwarzott 		}, {
732dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_SVIDEO,
733dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_1_1 |
734dd2e7dd2SMatthias Schwarzott 				(CX231XX_VIN_1_2 << 8) |
735dd2e7dd2SMatthias Schwarzott 				CX25840_SVIDEO_ON,
736dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
737dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
738dd2e7dd2SMatthias Schwarzott 		} },
739dd2e7dd2SMatthias Schwarzott 	},
7409e49f7c3SMatthias Schwarzott 	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx] = {
7418618ac4dSMatthias Schwarzott 		.name = "Hauppauge WinTV 930C-HD (1114xx) / HVR-901H (1114xx) / PCTV QuatroStick 522e",
7429e49f7c3SMatthias Schwarzott 		.tuner_type = TUNER_ABSENT,
7439e49f7c3SMatthias Schwarzott 		.tuner_addr = 0x60,
7449e49f7c3SMatthias Schwarzott 		.tuner_gpio = RDE250_XCV_TUNER,
7459e49f7c3SMatthias Schwarzott 		.tuner_sif_gpio = 0x05,
7469e49f7c3SMatthias Schwarzott 		.tuner_scl_gpio = 0x1a,
7479e49f7c3SMatthias Schwarzott 		.tuner_sda_gpio = 0x1b,
7489e49f7c3SMatthias Schwarzott 		.decoder = CX231XX_AVDECODER,
7499e49f7c3SMatthias Schwarzott 		.output_mode = OUT_MODE_VIP11,
7509e49f7c3SMatthias Schwarzott 		.demod_xfer_mode = 0,
7519e49f7c3SMatthias Schwarzott 		.ctl_pin_status_mask = 0xFFFFFFC4,
7529e49f7c3SMatthias Schwarzott 		.agc_analog_digital_select_gpio = 0x0c,
7539e49f7c3SMatthias Schwarzott 		.gpio_pin_status_mask = 0x4001000,
754b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
755599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
7569e49f7c3SMatthias Schwarzott 		.has_dvb = 1,
7579e49f7c3SMatthias Schwarzott 		.demod_addr = 0x0e,
7589e49f7c3SMatthias Schwarzott 		.norm = V4L2_STD_PAL,
7599e49f7c3SMatthias Schwarzott 
7609e49f7c3SMatthias Schwarzott 		.input = {{
7619e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_TELEVISION,
7629e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_3_1,
7639e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_VIDEO,
7649e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7659e49f7c3SMatthias Schwarzott 		}, {
7669e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_COMPOSITE1,
7679e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_2_1,
7689e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
7699e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7709e49f7c3SMatthias Schwarzott 		}, {
7719e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_SVIDEO,
7729e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_1_1 |
7739e49f7c3SMatthias Schwarzott 				(CX231XX_VIN_1_2 << 8) |
7749e49f7c3SMatthias Schwarzott 				CX25840_SVIDEO_ON,
7759e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
7769e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7779e49f7c3SMatthias Schwarzott 		} },
7789e49f7c3SMatthias Schwarzott 	},
779809abdbfSOlli Salonen 	[CX231XX_BOARD_HAUPPAUGE_955Q] = {
780809abdbfSOlli Salonen 		.name = "Hauppauge WinTV-HVR-955Q (111401)",
781809abdbfSOlli Salonen 		.tuner_type = TUNER_ABSENT,
782809abdbfSOlli Salonen 		.tuner_addr = 0x60,
783809abdbfSOlli Salonen 		.tuner_gpio = RDE250_XCV_TUNER,
784809abdbfSOlli Salonen 		.tuner_sif_gpio = 0x05,
785809abdbfSOlli Salonen 		.tuner_scl_gpio = 0x1a,
786809abdbfSOlli Salonen 		.tuner_sda_gpio = 0x1b,
787809abdbfSOlli Salonen 		.decoder = CX231XX_AVDECODER,
788809abdbfSOlli Salonen 		.output_mode = OUT_MODE_VIP11,
789809abdbfSOlli Salonen 		.demod_xfer_mode = 0,
790809abdbfSOlli Salonen 		.ctl_pin_status_mask = 0xFFFFFFC4,
791809abdbfSOlli Salonen 		.agc_analog_digital_select_gpio = 0x0c,
792809abdbfSOlli Salonen 		.gpio_pin_status_mask = 0x4001000,
793809abdbfSOlli Salonen 		.tuner_i2c_master = I2C_1_MUX_3,
794599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
795809abdbfSOlli Salonen 		.has_dvb = 1,
796809abdbfSOlli Salonen 		.demod_addr = 0x0e,
797809abdbfSOlli Salonen 		.norm = V4L2_STD_NTSC,
798809abdbfSOlli Salonen 
799809abdbfSOlli Salonen 		.input = {{
800809abdbfSOlli Salonen 			.type = CX231XX_VMUX_TELEVISION,
801809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_3_1,
802809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_VIDEO,
803809abdbfSOlli Salonen 			.gpio = NULL,
804809abdbfSOlli Salonen 		}, {
805809abdbfSOlli Salonen 			.type = CX231XX_VMUX_COMPOSITE1,
806809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_2_1,
807809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_LINE_IN,
808809abdbfSOlli Salonen 			.gpio = NULL,
809809abdbfSOlli Salonen 		}, {
810809abdbfSOlli Salonen 			.type = CX231XX_VMUX_SVIDEO,
811809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_1_1 |
812809abdbfSOlli Salonen 				(CX231XX_VIN_1_2 << 8) |
813809abdbfSOlli Salonen 				CX25840_SVIDEO_ON,
814809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_LINE_IN,
815809abdbfSOlli Salonen 			.gpio = NULL,
816809abdbfSOlli Salonen 		} },
817809abdbfSOlli Salonen 	},
818eee1d06dSTommi Rantala 	[CX231XX_BOARD_TERRATEC_GRABBY] = {
819eee1d06dSTommi Rantala 		.name = "Terratec Grabby",
820eee1d06dSTommi Rantala 		.tuner_type = TUNER_ABSENT,
821eee1d06dSTommi Rantala 		.decoder = CX231XX_AVDECODER,
822eee1d06dSTommi Rantala 		.output_mode = OUT_MODE_VIP11,
823eee1d06dSTommi Rantala 		.demod_xfer_mode = 0,
824eee1d06dSTommi Rantala 		.ctl_pin_status_mask = 0xFFFFFFC4,
825eee1d06dSTommi Rantala 		.agc_analog_digital_select_gpio = 0x0c,
826eee1d06dSTommi Rantala 		.gpio_pin_status_mask = 0x4001000,
827eee1d06dSTommi Rantala 		.norm = V4L2_STD_PAL,
828eee1d06dSTommi Rantala 		.no_alt_vanc = 1,
829eee1d06dSTommi Rantala 		.external_av = 1,
830eee1d06dSTommi Rantala 		.input = {{
831eee1d06dSTommi Rantala 			.type = CX231XX_VMUX_COMPOSITE1,
832eee1d06dSTommi Rantala 			.vmux = CX231XX_VIN_2_1,
833eee1d06dSTommi Rantala 			.amux = CX231XX_AMUX_LINE_IN,
834eee1d06dSTommi Rantala 			.gpio = NULL,
835eee1d06dSTommi Rantala 		}, {
836eee1d06dSTommi Rantala 			.type = CX231XX_VMUX_SVIDEO,
837eee1d06dSTommi Rantala 			.vmux = CX231XX_VIN_1_1 |
838eee1d06dSTommi Rantala 				(CX231XX_VIN_1_2 << 8) |
839eee1d06dSTommi Rantala 				CX25840_SVIDEO_ON,
840eee1d06dSTommi Rantala 			.amux = CX231XX_AMUX_LINE_IN,
841eee1d06dSTommi Rantala 			.gpio = NULL,
842eee1d06dSTommi Rantala 		} },
843eee1d06dSTommi Rantala 	},
844a096fd64SOleh Kravchenko 	[CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD] = {
845a096fd64SOleh Kravchenko 		.name = "Evromedia USB Full Hybrid Full HD",
846a096fd64SOleh Kravchenko 		.tuner_type = TUNER_ABSENT,
847a096fd64SOleh Kravchenko 		.demod_addr = 0x64, /* 0xc8 >> 1 */
848a096fd64SOleh Kravchenko 		.demod_i2c_master = I2C_1_MUX_3,
849a096fd64SOleh Kravchenko 		.has_dvb = 1,
8509d377daeSOleh Kravchenko 		.decoder = CX231XX_AVDECODER,
851a096fd64SOleh Kravchenko 		.norm = V4L2_STD_PAL,
852a096fd64SOleh Kravchenko 		.output_mode = OUT_MODE_VIP11,
853a096fd64SOleh Kravchenko 		.tuner_addr = 0x60, /* 0xc0 >> 1 */
854a096fd64SOleh Kravchenko 		.tuner_i2c_master = I2C_2,
855a096fd64SOleh Kravchenko 		.input = {{
856a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_TELEVISION,
857a096fd64SOleh Kravchenko 			.vmux = 0,
858a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_VIDEO,
859a096fd64SOleh Kravchenko 		}, {
860a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_COMPOSITE1,
861a096fd64SOleh Kravchenko 			.vmux = CX231XX_VIN_2_1,
862a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_LINE_IN,
863a096fd64SOleh Kravchenko 		}, {
864a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_SVIDEO,
865a096fd64SOleh Kravchenko 			.vmux = CX231XX_VIN_1_1 |
866a096fd64SOleh Kravchenko 				(CX231XX_VIN_1_2 << 8) |
867a096fd64SOleh Kravchenko 				CX25840_SVIDEO_ON,
868a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_LINE_IN,
869a096fd64SOleh Kravchenko 		} },
870a096fd64SOleh Kravchenko 	},
8710f42b331SOleh Kravchenko 	[CX231XX_BOARD_ASTROMETA_T2HYBRID] = {
8720f42b331SOleh Kravchenko 		.name = "Astrometa T2hybrid",
8730f42b331SOleh Kravchenko 		.tuner_type = TUNER_ABSENT,
8740f42b331SOleh Kravchenko 		.has_dvb = 1,
8751bfbb885SOleh Kravchenko 		.decoder = CX231XX_AVDECODER,
8760f42b331SOleh Kravchenko 		.output_mode = OUT_MODE_VIP11,
8770f42b331SOleh Kravchenko 		.agc_analog_digital_select_gpio = 0x01,
8780f42b331SOleh Kravchenko 		.ctl_pin_status_mask = 0xffffffc4,
8790f42b331SOleh Kravchenko 		.demod_addr = 0x18, /* 0x30 >> 1 */
8800f42b331SOleh Kravchenko 		.demod_i2c_master = I2C_1_MUX_1,
8810f42b331SOleh Kravchenko 		.gpio_pin_status_mask = 0xa,
8820f42b331SOleh Kravchenko 		.norm = V4L2_STD_NTSC,
8830f42b331SOleh Kravchenko 		.tuner_addr = 0x3a, /* 0x74 >> 1 */
8840f42b331SOleh Kravchenko 		.tuner_i2c_master = I2C_1_MUX_3,
8850f42b331SOleh Kravchenko 		.tuner_scl_gpio = 0x1a,
8860f42b331SOleh Kravchenko 		.tuner_sda_gpio = 0x1b,
8870f42b331SOleh Kravchenko 		.tuner_sif_gpio = 0x05,
8880f42b331SOleh Kravchenko 		.input = {{
8890f42b331SOleh Kravchenko 				.type = CX231XX_VMUX_TELEVISION,
8900f42b331SOleh Kravchenko 				.vmux = CX231XX_VIN_1_1,
8910f42b331SOleh Kravchenko 				.amux = CX231XX_AMUX_VIDEO,
8920f42b331SOleh Kravchenko 			}, {
8930f42b331SOleh Kravchenko 				.type = CX231XX_VMUX_COMPOSITE1,
8940f42b331SOleh Kravchenko 				.vmux = CX231XX_VIN_2_1,
8950f42b331SOleh Kravchenko 				.amux = CX231XX_AMUX_LINE_IN,
8960f42b331SOleh Kravchenko 			},
8970f42b331SOleh Kravchenko 		},
8980f42b331SOleh Kravchenko 	},
899fdda0109SRomain Reignier 	[CX231XX_BOARD_THE_IMAGING_SOURCE_DFG_USB2_PRO] = {
900fdda0109SRomain Reignier 		.name = "The Imaging Source DFG/USB2pro",
901fdda0109SRomain Reignier 		.tuner_type = TUNER_ABSENT,
902fdda0109SRomain Reignier 		.decoder = CX231XX_AVDECODER,
903fdda0109SRomain Reignier 		.output_mode = OUT_MODE_VIP11,
904fdda0109SRomain Reignier 		.demod_xfer_mode = 0,
905fdda0109SRomain Reignier 		.ctl_pin_status_mask = 0xFFFFFFC4,
906fdda0109SRomain Reignier 		.agc_analog_digital_select_gpio = 0x0c,
907fdda0109SRomain Reignier 		.gpio_pin_status_mask = 0x4001000,
908fdda0109SRomain Reignier 		.norm = V4L2_STD_PAL,
909fdda0109SRomain Reignier 		.no_alt_vanc = 1,
910fdda0109SRomain Reignier 		.external_av = 1,
911fdda0109SRomain Reignier 		.input = {{
912fdda0109SRomain Reignier 			.type = CX231XX_VMUX_COMPOSITE1,
913fdda0109SRomain Reignier 			.vmux = CX231XX_VIN_1_1,
914fdda0109SRomain Reignier 			.amux = CX231XX_AMUX_LINE_IN,
915fdda0109SRomain Reignier 			.gpio = NULL,
916fdda0109SRomain Reignier 		}, {
917fdda0109SRomain Reignier 			.type = CX231XX_VMUX_SVIDEO,
918fdda0109SRomain Reignier 			.vmux = CX231XX_VIN_2_1 |
919fdda0109SRomain Reignier 				(CX231XX_VIN_2_2 << 8) |
920fdda0109SRomain Reignier 				CX25840_SVIDEO_ON,
921fdda0109SRomain Reignier 			.amux = CX231XX_AMUX_LINE_IN,
922fdda0109SRomain Reignier 			.gpio = NULL,
923fdda0109SRomain Reignier 		} },
924fdda0109SRomain Reignier 	},
925c5bef50eSBrad Love 	[CX231XX_BOARD_HAUPPAUGE_935C] = {
926c5bef50eSBrad Love 		.name = "Hauppauge WinTV-HVR-935C",
927c5bef50eSBrad Love 		.tuner_type = TUNER_ABSENT,
928c5bef50eSBrad Love 		.tuner_addr = 0x60,
929c5bef50eSBrad Love 		.tuner_gpio = RDE250_XCV_TUNER,
930c5bef50eSBrad Love 		.tuner_sif_gpio = 0x05,
931c5bef50eSBrad Love 		.tuner_scl_gpio = 0x1a,
932c5bef50eSBrad Love 		.tuner_sda_gpio = 0x1b,
933c5bef50eSBrad Love 		.decoder = CX231XX_AVDECODER,
934c5bef50eSBrad Love 		.output_mode = OUT_MODE_VIP11,
935c5bef50eSBrad Love 		.demod_xfer_mode = 0,
936c5bef50eSBrad Love 		.ctl_pin_status_mask = 0xFFFFFFC4,
937c5bef50eSBrad Love 		.agc_analog_digital_select_gpio = 0x0c,
938c5bef50eSBrad Love 		.gpio_pin_status_mask = 0x4001000,
939c5bef50eSBrad Love 		.tuner_i2c_master = I2C_1_MUX_3,
940c5bef50eSBrad Love 		.demod_i2c_master = I2C_1_MUX_3,
941c5bef50eSBrad Love 		.has_dvb = 1,
942c5bef50eSBrad Love 		.demod_addr = 0x64, /* 0xc8 >> 1 */
943c5bef50eSBrad Love 		.norm = V4L2_STD_PAL,
944c5bef50eSBrad Love 
945c5bef50eSBrad Love 		.input = {{
946c5bef50eSBrad Love 			.type = CX231XX_VMUX_TELEVISION,
947c5bef50eSBrad Love 			.vmux = CX231XX_VIN_3_1,
948c5bef50eSBrad Love 			.amux = CX231XX_AMUX_VIDEO,
949c5bef50eSBrad Love 			.gpio = NULL,
950c5bef50eSBrad Love 		}, {
951c5bef50eSBrad Love 			.type = CX231XX_VMUX_COMPOSITE1,
952c5bef50eSBrad Love 			.vmux = CX231XX_VIN_2_1,
953c5bef50eSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
954c5bef50eSBrad Love 			.gpio = NULL,
955c5bef50eSBrad Love 		}, {
956c5bef50eSBrad Love 			.type = CX231XX_VMUX_SVIDEO,
957c5bef50eSBrad Love 			.vmux = CX231XX_VIN_1_1 |
958c5bef50eSBrad Love 				(CX231XX_VIN_1_2 << 8) |
959c5bef50eSBrad Love 				CX25840_SVIDEO_ON,
960c5bef50eSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
961c5bef50eSBrad Love 			.gpio = NULL,
962c5bef50eSBrad Love 		} },
963c5bef50eSBrad Love 	},
96419fbf1baSBrad Love 	[CX231XX_BOARD_HAUPPAUGE_975] = {
96519fbf1baSBrad Love 		.name = "Hauppauge WinTV-HVR-975",
96619fbf1baSBrad Love 		.tuner_type = TUNER_ABSENT,
96719fbf1baSBrad Love 		.tuner_addr = 0x60,
96819fbf1baSBrad Love 		.tuner_gpio = RDE250_XCV_TUNER,
96919fbf1baSBrad Love 		.tuner_sif_gpio = 0x05,
97019fbf1baSBrad Love 		.tuner_scl_gpio = 0x1a,
97119fbf1baSBrad Love 		.tuner_sda_gpio = 0x1b,
97219fbf1baSBrad Love 		.decoder = CX231XX_AVDECODER,
97319fbf1baSBrad Love 		.output_mode = OUT_MODE_VIP11,
97419fbf1baSBrad Love 		.demod_xfer_mode = 0,
97519fbf1baSBrad Love 		.ctl_pin_status_mask = 0xFFFFFFC4,
97619fbf1baSBrad Love 		.agc_analog_digital_select_gpio = 0x0c,
97719fbf1baSBrad Love 		.gpio_pin_status_mask = 0x4001000,
97819fbf1baSBrad Love 		.tuner_i2c_master = I2C_1_MUX_3,
97919fbf1baSBrad Love 		.demod_i2c_master = I2C_1_MUX_3,
98019fbf1baSBrad Love 		.has_dvb = 1,
98119fbf1baSBrad Love 		.demod_addr = 0x59, /* 0xb2 >> 1 */
982a2c52cd7SBrad Love 		.demod_addr2 = 0x64, /* 0xc8 >> 1 */
98319fbf1baSBrad Love 		.norm = V4L2_STD_ALL,
98419fbf1baSBrad Love 
98519fbf1baSBrad Love 		.input = {{
98619fbf1baSBrad Love 			.type = CX231XX_VMUX_TELEVISION,
98719fbf1baSBrad Love 			.vmux = CX231XX_VIN_3_1,
98819fbf1baSBrad Love 			.amux = CX231XX_AMUX_VIDEO,
98919fbf1baSBrad Love 			.gpio = NULL,
99019fbf1baSBrad Love 		}, {
99119fbf1baSBrad Love 			.type = CX231XX_VMUX_COMPOSITE1,
99219fbf1baSBrad Love 			.vmux = CX231XX_VIN_2_1,
99319fbf1baSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
99419fbf1baSBrad Love 			.gpio = NULL,
99519fbf1baSBrad Love 		}, {
99619fbf1baSBrad Love 			.type = CX231XX_VMUX_SVIDEO,
99719fbf1baSBrad Love 			.vmux = CX231XX_VIN_1_1 |
99819fbf1baSBrad Love 				(CX231XX_VIN_1_2 << 8) |
99919fbf1baSBrad Love 				CX25840_SVIDEO_ON,
100019fbf1baSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
100119fbf1baSBrad Love 			.gpio = NULL,
100219fbf1baSBrad Love 		} },
100319fbf1baSBrad Love 	},
10040c0d06caSMauro Carvalho Chehab };
10050c0d06caSMauro Carvalho Chehab const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
10060c0d06caSMauro Carvalho Chehab 
10070c0d06caSMauro Carvalho Chehab /* table of devices that work with this driver */
10080c0d06caSMauro Carvalho Chehab struct usb_device_id cx231xx_id_table[] = {
1009dad4c418SLinks (Markus) 	{USB_DEVICE(0x1D19, 0x6109),
1010dad4c418SLinks (Markus) 	.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
10110c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x5A3C),
10120c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_UNKNOWN},
10130c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A2),
10140c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
10150c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A1),
10160c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_SHELBY},
10170c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A4),
10180c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_253S},
10190c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A5),
10200c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_253S},
10210c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A6),
10220c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
10230c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x589E),
10240c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_250},
10250c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A0),
10260c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_250},
10270c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb110),
10280c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
10290c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb111),
10300c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
10310c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb120),
10320c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
1033809abdbfSOlli Salonen 	{USB_DEVICE(0x2040, 0xb123),
1034809abdbfSOlli Salonen 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q},
1035c5bef50eSBrad Love 	{USB_DEVICE(0x2040, 0xb151),
1036c5bef50eSBrad Love 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_935C},
103719fbf1baSBrad Love 	{USB_DEVICE(0x2040, 0xb150),
103819fbf1baSBrad Love 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_975},
1039dd2e7dd2SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb130),
1040dd2e7dd2SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
10419e49f7c3SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb131),
10429e49f7c3SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
104357cbf3efSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-900-H */
104457cbf3efSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb138),
104557cbf3efSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
10468618ac4dSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-901-H */
10478618ac4dSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb139),
10488618ac4dSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
10490c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb140),
10500c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
10510c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xc200),
10520c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
1053a141a887SMatthias Schwarzott 	/* PCTV QuatroStick 521e */
1054a141a887SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x0259),
1055a141a887SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
1056140a7987SMatthias Schwarzott 	/* PCTV QuatroStick 522e */
1057140a7987SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x025e),
1058140a7987SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
10590c0d06caSMauro Carvalho Chehab 	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
10600c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
10610c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
10620c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
10630c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1b80, 0xe424),
10640c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID},
10658b1255a2SJohannes Erdfelt 	{USB_DEVICE(0x1b80, 0xe421),
10668b1255a2SJohannes Erdfelt 	 .driver_info = CX231XX_BOARD_KWORLD_UB445_USB_HYBRID},
10670c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1f4d, 0x0237),
10680c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_ICONBIT_U100},
106968c97bf3SAlf Høgemark 	{USB_DEVICE(0x0fd9, 0x0037),
107068c97bf3SAlf Høgemark 	 .driver_info = CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2},
10713ead1ba3SMatt Gomboc 	{USB_DEVICE(0x1f4d, 0x0102),
10723ead1ba3SMatt Gomboc 	 .driver_info = CX231XX_BOARD_OTG102},
1073eee1d06dSTommi Rantala 	{USB_DEVICE(USB_VID_TERRATEC, 0x00a6),
1074eee1d06dSTommi Rantala 	 .driver_info = CX231XX_BOARD_TERRATEC_GRABBY},
1075a096fd64SOleh Kravchenko 	{USB_DEVICE(0x1b80, 0xd3b2),
1076a096fd64SOleh Kravchenko 	.driver_info = CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD},
10770f42b331SOleh Kravchenko 	{USB_DEVICE(0x15f4, 0x0135),
10780f42b331SOleh Kravchenko 	.driver_info = CX231XX_BOARD_ASTROMETA_T2HYBRID},
1079fdda0109SRomain Reignier 	{USB_DEVICE(0x199e, 0x8002),
1080fdda0109SRomain Reignier 	 .driver_info = CX231XX_BOARD_THE_IMAGING_SOURCE_DFG_USB2_PRO},
10810c0d06caSMauro Carvalho Chehab 	{},
10820c0d06caSMauro Carvalho Chehab };
10830c0d06caSMauro Carvalho Chehab 
10840c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
10850c0d06caSMauro Carvalho Chehab 
10860c0d06caSMauro Carvalho Chehab /* cx231xx_tuner_callback
10870c0d06caSMauro Carvalho Chehab  * will be used to reset XC5000 tuner using GPIO pin
10880c0d06caSMauro Carvalho Chehab  */
10890c0d06caSMauro Carvalho Chehab 
10900c0d06caSMauro Carvalho Chehab int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
10910c0d06caSMauro Carvalho Chehab {
10920c0d06caSMauro Carvalho Chehab 	int rc = 0;
10930c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = ptr;
10940c0d06caSMauro Carvalho Chehab 
10950c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_XC5000) {
10960c0d06caSMauro Carvalho Chehab 		if (command == XC5000_TUNER_RESET) {
1097336fea92SMauro Carvalho Chehab 			dev_dbg(dev->dev,
1098b7085c08SMauro Carvalho Chehab 				"Tuner CB: RESET: cmd %d : tuner type %d\n",
10990c0d06caSMauro Carvalho Chehab 				command, dev->tuner_type);
11000c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
11010c0d06caSMauro Carvalho Chehab 					       1);
11020c0d06caSMauro Carvalho Chehab 			msleep(10);
11030c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
11040c0d06caSMauro Carvalho Chehab 					       0);
11050c0d06caSMauro Carvalho Chehab 			msleep(330);
11060c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
11070c0d06caSMauro Carvalho Chehab 					       1);
11080c0d06caSMauro Carvalho Chehab 			msleep(10);
11090c0d06caSMauro Carvalho Chehab 		}
11100c0d06caSMauro Carvalho Chehab 	} else if (dev->tuner_type == TUNER_NXP_TDA18271) {
11110c0d06caSMauro Carvalho Chehab 		switch (command) {
11120c0d06caSMauro Carvalho Chehab 		case TDA18271_CALLBACK_CMD_AGC_ENABLE:
11130c0d06caSMauro Carvalho Chehab 			if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
11140c0d06caSMauro Carvalho Chehab 				rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
11150c0d06caSMauro Carvalho Chehab 			break;
11160c0d06caSMauro Carvalho Chehab 		default:
11170c0d06caSMauro Carvalho Chehab 			rc = -EINVAL;
11180c0d06caSMauro Carvalho Chehab 			break;
11190c0d06caSMauro Carvalho Chehab 		}
11200c0d06caSMauro Carvalho Chehab 	}
11210c0d06caSMauro Carvalho Chehab 	return rc;
11220c0d06caSMauro Carvalho Chehab }
11230c0d06caSMauro Carvalho Chehab EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
11240c0d06caSMauro Carvalho Chehab 
1125d4c06133SMauro Carvalho Chehab static void cx231xx_reset_out(struct cx231xx *dev)
11260c0d06caSMauro Carvalho Chehab {
11270c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
11280c0d06caSMauro Carvalho Chehab 	msleep(200);
11290c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
11300c0d06caSMauro Carvalho Chehab 	msleep(200);
11310c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
11320c0d06caSMauro Carvalho Chehab }
1133d4c06133SMauro Carvalho Chehab 
1134d4c06133SMauro Carvalho Chehab static void cx231xx_enable_OSC(struct cx231xx *dev)
11350c0d06caSMauro Carvalho Chehab {
11360c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
11370c0d06caSMauro Carvalho Chehab }
1138d4c06133SMauro Carvalho Chehab 
1139d4c06133SMauro Carvalho Chehab static void cx231xx_sleep_s5h1432(struct cx231xx *dev)
11400c0d06caSMauro Carvalho Chehab {
11410c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
11420c0d06caSMauro Carvalho Chehab }
11430c0d06caSMauro Carvalho Chehab 
11440c0d06caSMauro Carvalho Chehab static inline void cx231xx_set_model(struct cx231xx *dev)
11450c0d06caSMauro Carvalho Chehab {
11463724dde9SEzequiel Garcia 	dev->board = cx231xx_boards[dev->model];
11470c0d06caSMauro Carvalho Chehab }
11480c0d06caSMauro Carvalho Chehab 
11490c0d06caSMauro Carvalho Chehab /* Since cx231xx_pre_card_setup() requires a proper dev->model,
11500c0d06caSMauro Carvalho Chehab  * this won't work for boards with generic PCI IDs
11510c0d06caSMauro Carvalho Chehab  */
11520c0d06caSMauro Carvalho Chehab void cx231xx_pre_card_setup(struct cx231xx *dev)
11530c0d06caSMauro Carvalho Chehab {
1154336fea92SMauro Carvalho Chehab 	dev_info(dev->dev, "Identified as %s (card=%d)\n",
11550c0d06caSMauro Carvalho Chehab 		dev->board.name, dev->model);
11560c0d06caSMauro Carvalho Chehab 
11570f42b331SOleh Kravchenko 	if (CX231XX_BOARD_ASTROMETA_T2HYBRID == dev->model) {
11580f42b331SOleh Kravchenko 		/* turn on demodulator chip */
11590f42b331SOleh Kravchenko 		cx231xx_set_gpio_value(dev, 0x03, 0x01);
11600f42b331SOleh Kravchenko 	}
11610f42b331SOleh Kravchenko 
11620c0d06caSMauro Carvalho Chehab 	/* set the direction for GPIO pins */
11630c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_gpio) {
11640c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
11650c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
11660c0d06caSMauro Carvalho Chehab 	}
11670c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_sif_gpio >= 0)
11680c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
11690c0d06caSMauro Carvalho Chehab 
11700c0d06caSMauro Carvalho Chehab 	/* request some modules if any required */
11710c0d06caSMauro Carvalho Chehab 
11720c0d06caSMauro Carvalho Chehab 	/* set the mode to Analog mode initially */
11730c0d06caSMauro Carvalho Chehab 	cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
11740c0d06caSMauro Carvalho Chehab 
11750c0d06caSMauro Carvalho Chehab 	/* Unlock device */
11760c0d06caSMauro Carvalho Chehab 	/* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
11770c0d06caSMauro Carvalho Chehab 
11780c0d06caSMauro Carvalho Chehab }
11790c0d06caSMauro Carvalho Chehab 
11800c0d06caSMauro Carvalho Chehab static void cx231xx_config_tuner(struct cx231xx *dev)
11810c0d06caSMauro Carvalho Chehab {
11820c0d06caSMauro Carvalho Chehab 	struct tuner_setup tun_setup;
11830c0d06caSMauro Carvalho Chehab 	struct v4l2_frequency f;
11840c0d06caSMauro Carvalho Chehab 
11850c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_ABSENT)
11860c0d06caSMauro Carvalho Chehab 		return;
11870c0d06caSMauro Carvalho Chehab 
11880c0d06caSMauro Carvalho Chehab 	tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
11890c0d06caSMauro Carvalho Chehab 	tun_setup.type = dev->tuner_type;
11900c0d06caSMauro Carvalho Chehab 	tun_setup.addr = dev->tuner_addr;
11910c0d06caSMauro Carvalho Chehab 	tun_setup.tuner_callback = cx231xx_tuner_callback;
11920c0d06caSMauro Carvalho Chehab 
11930c0d06caSMauro Carvalho Chehab 	tuner_call(dev, tuner, s_type_addr, &tun_setup);
11940c0d06caSMauro Carvalho Chehab 
11950c0d06caSMauro Carvalho Chehab #if 0
11960c0d06caSMauro Carvalho Chehab 	if (tun_setup.type == TUNER_XC5000) {
11970c0d06caSMauro Carvalho Chehab 		static struct xc2028_ctrl ctrl = {
11980c0d06caSMauro Carvalho Chehab 			.fname = XC5000_DEFAULT_FIRMWARE,
11990c0d06caSMauro Carvalho Chehab 			.max_len = 64,
12000c0d06caSMauro Carvalho Chehab 			.demod = 0;
12010c0d06caSMauro Carvalho Chehab 		};
12020c0d06caSMauro Carvalho Chehab 		struct v4l2_priv_tun_config cfg = {
12030c0d06caSMauro Carvalho Chehab 			.tuner = dev->tuner_type,
12040c0d06caSMauro Carvalho Chehab 			.priv = &ctrl,
12050c0d06caSMauro Carvalho Chehab 		};
12060c0d06caSMauro Carvalho Chehab 		tuner_call(dev, tuner, s_config, &cfg);
12070c0d06caSMauro Carvalho Chehab 	}
12080c0d06caSMauro Carvalho Chehab #endif
12090c0d06caSMauro Carvalho Chehab 	/* configure tuner */
12100c0d06caSMauro Carvalho Chehab 	f.tuner = 0;
12110c0d06caSMauro Carvalho Chehab 	f.type = V4L2_TUNER_ANALOG_TV;
12120c0d06caSMauro Carvalho Chehab 	f.frequency = 9076;	/* just a magic number */
12130c0d06caSMauro Carvalho Chehab 	dev->ctl_freq = f.frequency;
12140c0d06caSMauro Carvalho Chehab 	call_all(dev, tuner, s_frequency, &f);
12150c0d06caSMauro Carvalho Chehab 
12160c0d06caSMauro Carvalho Chehab }
12170c0d06caSMauro Carvalho Chehab 
12189c672890SMatthias Schwarzott static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
12199c672890SMatthias Schwarzott 		       u8 *eedata, int len)
1220dd2e7dd2SMatthias Schwarzott {
12219aa4d4eaSMarkus Elfring 	int ret;
1222dd2e7dd2SMatthias Schwarzott 	u8 start_offset = 0;
1223dd2e7dd2SMatthias Schwarzott 	int len_todo = len;
1224dd2e7dd2SMatthias Schwarzott 	u8 *eedata_cur = eedata;
1225dd2e7dd2SMatthias Schwarzott 	int i;
12269c672890SMatthias Schwarzott 	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
1227dd2e7dd2SMatthias Schwarzott 		.buf = &start_offset, .len = 1 };
12289c672890SMatthias Schwarzott 	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
1229dd2e7dd2SMatthias Schwarzott 
1230dd2e7dd2SMatthias Schwarzott 	/* start reading at offset 0 */
12319c672890SMatthias Schwarzott 	ret = i2c_transfer(client->adapter, &msg_write, 1);
12321f97947cSMauro Carvalho Chehab 	if (ret < 0) {
1233336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Can't read eeprom\n");
12341f97947cSMauro Carvalho Chehab 		return ret;
12351f97947cSMauro Carvalho Chehab 	}
1236dd2e7dd2SMatthias Schwarzott 
1237dd2e7dd2SMatthias Schwarzott 	while (len_todo > 0) {
1238dd2e7dd2SMatthias Schwarzott 		msg_read.len = (len_todo > 64) ? 64 : len_todo;
1239dd2e7dd2SMatthias Schwarzott 		msg_read.buf = eedata_cur;
1240dd2e7dd2SMatthias Schwarzott 
12419c672890SMatthias Schwarzott 		ret = i2c_transfer(client->adapter, &msg_read, 1);
12421f97947cSMauro Carvalho Chehab 		if (ret < 0) {
1243336fea92SMauro Carvalho Chehab 			dev_err(dev->dev, "Can't read eeprom\n");
12441f97947cSMauro Carvalho Chehab 			return ret;
12451f97947cSMauro Carvalho Chehab 		}
1246dd2e7dd2SMatthias Schwarzott 		eedata_cur += msg_read.len;
1247dd2e7dd2SMatthias Schwarzott 		len_todo -= msg_read.len;
1248dd2e7dd2SMatthias Schwarzott 	}
1249dd2e7dd2SMatthias Schwarzott 
1250dd2e7dd2SMatthias Schwarzott 	for (i = 0; i + 15 < len; i += 16)
1251336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev, "i2c eeprom %02x: %*ph\n",
1252b7085c08SMauro Carvalho Chehab 			i, 16, &eedata[i]);
1253dd2e7dd2SMatthias Schwarzott 
1254dd2e7dd2SMatthias Schwarzott 	return 0;
1255dd2e7dd2SMatthias Schwarzott }
1256dd2e7dd2SMatthias Schwarzott 
12570c0d06caSMauro Carvalho Chehab void cx231xx_card_setup(struct cx231xx *dev)
12580c0d06caSMauro Carvalho Chehab {
12590c0d06caSMauro Carvalho Chehab 
12600c0d06caSMauro Carvalho Chehab 	cx231xx_set_model(dev);
12610c0d06caSMauro Carvalho Chehab 
12620c0d06caSMauro Carvalho Chehab 	dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
12630c0d06caSMauro Carvalho Chehab 	if (cx231xx_boards[dev->model].tuner_addr)
12640c0d06caSMauro Carvalho Chehab 		dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
12650c0d06caSMauro Carvalho Chehab 
12660c0d06caSMauro Carvalho Chehab 	/* request some modules */
12670c0d06caSMauro Carvalho Chehab 	if (dev->board.decoder == CX231XX_AVDECODER) {
12680c0d06caSMauro Carvalho Chehab 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1269c3c3f1aeSMatthias Schwarzott 					cx231xx_get_i2c_adap(dev, I2C_0),
12700c0d06caSMauro Carvalho Chehab 					"cx25840", 0x88 >> 1, NULL);
12710c0d06caSMauro Carvalho Chehab 		if (dev->sd_cx25840 == NULL)
1272336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1273b7085c08SMauro Carvalho Chehab 				"cx25840 subdev registration failure\n");
12740c0d06caSMauro Carvalho Chehab 		cx25840_call(dev, core, load_fw);
12750c0d06caSMauro Carvalho Chehab 
12760c0d06caSMauro Carvalho Chehab 	}
12770c0d06caSMauro Carvalho Chehab 
12780c0d06caSMauro Carvalho Chehab 	/* Initialize the tuner */
12790c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_type != TUNER_ABSENT) {
1280c3c3f1aeSMatthias Schwarzott 		struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
1281c3c3f1aeSMatthias Schwarzott 						dev->board.tuner_i2c_master);
12820c0d06caSMauro Carvalho Chehab 		dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1283c3c3f1aeSMatthias Schwarzott 						    tuner_i2c,
12840c0d06caSMauro Carvalho Chehab 						    "tuner",
12850c0d06caSMauro Carvalho Chehab 						    dev->tuner_addr, NULL);
12860c0d06caSMauro Carvalho Chehab 		if (dev->sd_tuner == NULL)
1287336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1288b7085c08SMauro Carvalho Chehab 				"tuner subdev registration failure\n");
12890c0d06caSMauro Carvalho Chehab 		else
12900c0d06caSMauro Carvalho Chehab 			cx231xx_config_tuner(dev);
12910c0d06caSMauro Carvalho Chehab 	}
1292dd2e7dd2SMatthias Schwarzott 
1293dd2e7dd2SMatthias Schwarzott 	switch (dev->model) {
1294dd2e7dd2SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
12959e49f7c3SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
1296809abdbfSOlli Salonen 	case CX231XX_BOARD_HAUPPAUGE_955Q:
1297c5bef50eSBrad Love 	case CX231XX_BOARD_HAUPPAUGE_935C:
129819fbf1baSBrad Love 	case CX231XX_BOARD_HAUPPAUGE_975:
1299dd2e7dd2SMatthias Schwarzott 		{
13007f3c2e1dSHans Verkuil 			struct eeprom {
1301dd2e7dd2SMatthias Schwarzott 				struct tveeprom tvee;
13027f3c2e1dSHans Verkuil 				u8 eeprom[256];
13039c672890SMatthias Schwarzott 				struct i2c_client client;
13047f3c2e1dSHans Verkuil 			};
13057f3c2e1dSHans Verkuil 			struct eeprom *e = kzalloc(sizeof(*e), GFP_KERNEL);
1306dd2e7dd2SMatthias Schwarzott 
13077f3c2e1dSHans Verkuil 			if (e == NULL) {
13087f3c2e1dSHans Verkuil 				dev_err(dev->dev,
13097f3c2e1dSHans Verkuil 					"failed to allocate memory to read eeprom\n");
13107f3c2e1dSHans Verkuil 				break;
13117f3c2e1dSHans Verkuil 			}
13127f3c2e1dSHans Verkuil 			e->client.adapter = cx231xx_get_i2c_adap(dev, I2C_1_MUX_1);
13137f3c2e1dSHans Verkuil 			e->client.addr = 0xa0 >> 1;
13149c672890SMatthias Schwarzott 
13157f3c2e1dSHans Verkuil 			read_eeprom(dev, &e->client, e->eeprom, sizeof(e->eeprom));
1316446aba66SMauro Carvalho Chehab 			tveeprom_hauppauge_analog(&e->tvee, e->eeprom + 0xc0);
13177f3c2e1dSHans Verkuil 			kfree(e);
1318dd2e7dd2SMatthias Schwarzott 			break;
1319dd2e7dd2SMatthias Schwarzott 		}
1320dd2e7dd2SMatthias Schwarzott 	}
1321dd2e7dd2SMatthias Schwarzott 
13220c0d06caSMauro Carvalho Chehab }
13230c0d06caSMauro Carvalho Chehab 
13240c0d06caSMauro Carvalho Chehab /*
13250c0d06caSMauro Carvalho Chehab  * cx231xx_config()
13260c0d06caSMauro Carvalho Chehab  * inits registers with sane defaults
13270c0d06caSMauro Carvalho Chehab  */
13280c0d06caSMauro Carvalho Chehab int cx231xx_config(struct cx231xx *dev)
13290c0d06caSMauro Carvalho Chehab {
13300c0d06caSMauro Carvalho Chehab 	/* TBD need to add cx231xx specific code */
13310c0d06caSMauro Carvalho Chehab 
13320c0d06caSMauro Carvalho Chehab 	return 0;
13330c0d06caSMauro Carvalho Chehab }
13340c0d06caSMauro Carvalho Chehab 
13350c0d06caSMauro Carvalho Chehab /*
13360c0d06caSMauro Carvalho Chehab  * cx231xx_config_i2c()
13370c0d06caSMauro Carvalho Chehab  * configure i2c attached devices
13380c0d06caSMauro Carvalho Chehab  */
13390c0d06caSMauro Carvalho Chehab void cx231xx_config_i2c(struct cx231xx *dev)
13400c0d06caSMauro Carvalho Chehab {
13410c0d06caSMauro Carvalho Chehab 	/* u32 input = INPUT(dev->video_input)->vmux; */
13420c0d06caSMauro Carvalho Chehab 
13430c0d06caSMauro Carvalho Chehab 	call_all(dev, video, s_stream, 1);
13440c0d06caSMauro Carvalho Chehab }
13450c0d06caSMauro Carvalho Chehab 
13461d058bdcSMauro Carvalho Chehab static void cx231xx_unregister_media_device(struct cx231xx *dev)
13471d058bdcSMauro Carvalho Chehab {
13481d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
13491d058bdcSMauro Carvalho Chehab 	if (dev->media_dev) {
13501d058bdcSMauro Carvalho Chehab 		media_device_unregister(dev->media_dev);
13519832e155SJavier Martinez Canillas 		media_device_cleanup(dev->media_dev);
13521d058bdcSMauro Carvalho Chehab 		kfree(dev->media_dev);
13531d058bdcSMauro Carvalho Chehab 		dev->media_dev = NULL;
13541d058bdcSMauro Carvalho Chehab 	}
13551d058bdcSMauro Carvalho Chehab #endif
13561d058bdcSMauro Carvalho Chehab }
13571d058bdcSMauro Carvalho Chehab 
13580c0d06caSMauro Carvalho Chehab /*
13590c0d06caSMauro Carvalho Chehab  * cx231xx_realease_resources()
13600c0d06caSMauro Carvalho Chehab  * unregisters the v4l2,i2c and usb devices
13610c0d06caSMauro Carvalho Chehab  * called when the device gets disconected or at module unload
13620c0d06caSMauro Carvalho Chehab */
13630c0d06caSMauro Carvalho Chehab void cx231xx_release_resources(struct cx231xx *dev)
13640c0d06caSMauro Carvalho Chehab {
13653c59bb47SMauro Carvalho Chehab 	cx231xx_ir_exit(dev);
13663c59bb47SMauro Carvalho Chehab 
13670c0d06caSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
13680c0d06caSMauro Carvalho Chehab 
13690c0d06caSMauro Carvalho Chehab 	cx231xx_remove_from_devlist(dev);
13700c0d06caSMauro Carvalho Chehab 
13710c0d06caSMauro Carvalho Chehab 	/* Release I2C buses */
13720c0d06caSMauro Carvalho Chehab 	cx231xx_dev_uninit(dev);
13730c0d06caSMauro Carvalho Chehab 
13740c0d06caSMauro Carvalho Chehab 	/* delete v4l2 device */
13750c0d06caSMauro Carvalho Chehab 	v4l2_device_unregister(&dev->v4l2_dev);
13760c0d06caSMauro Carvalho Chehab 
1377ab232e46SMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
1378ab232e46SMauro Carvalho Chehab 
13790c0d06caSMauro Carvalho Chehab 	usb_put_dev(dev->udev);
13800c0d06caSMauro Carvalho Chehab 
13810c0d06caSMauro Carvalho Chehab 	/* Mark device as unused */
13820c0d06caSMauro Carvalho Chehab 	clear_bit(dev->devno, &cx231xx_devused);
13830c0d06caSMauro Carvalho Chehab }
13840c0d06caSMauro Carvalho Chehab 
13859f806795SMauro Carvalho Chehab static int cx231xx_media_device_init(struct cx231xx *dev,
13861d058bdcSMauro Carvalho Chehab 				      struct usb_device *udev)
13871d058bdcSMauro Carvalho Chehab {
13881d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
13891d058bdcSMauro Carvalho Chehab 	struct media_device *mdev;
13901d058bdcSMauro Carvalho Chehab 
13916cf5dad1SMauro Carvalho Chehab 	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
13921d058bdcSMauro Carvalho Chehab 	if (!mdev)
13939f806795SMauro Carvalho Chehab 		return -ENOMEM;
13941d058bdcSMauro Carvalho Chehab 
13956cf5dad1SMauro Carvalho Chehab 	media_device_usb_init(mdev, udev, dev->board.name);
13966cf5dad1SMauro Carvalho Chehab 
13971d058bdcSMauro Carvalho Chehab 	dev->media_dev = mdev;
13981d058bdcSMauro Carvalho Chehab #endif
13999f806795SMauro Carvalho Chehab 	return 0;
14001d058bdcSMauro Carvalho Chehab }
14011d058bdcSMauro Carvalho Chehab 
14020c0d06caSMauro Carvalho Chehab /*
14030c0d06caSMauro Carvalho Chehab  * cx231xx_init_dev()
14040c0d06caSMauro Carvalho Chehab  * allocates and inits the device structs, registers i2c bus and v4l device
14050c0d06caSMauro Carvalho Chehab  */
14060c0d06caSMauro Carvalho Chehab static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
14070c0d06caSMauro Carvalho Chehab 			    int minor)
14080c0d06caSMauro Carvalho Chehab {
14090c0d06caSMauro Carvalho Chehab 	int retval = -ENOMEM;
14100c0d06caSMauro Carvalho Chehab 	unsigned int maxh, maxw;
14110c0d06caSMauro Carvalho Chehab 
14120c0d06caSMauro Carvalho Chehab 	dev->udev = udev;
14130c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->lock);
14140c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->ctrl_urb_lock);
14150c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->gpio_i2c_lock);
14160c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->i2c_lock);
14170c0d06caSMauro Carvalho Chehab 
14180c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->video_mode.slock);
14190c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->vbi_mode.slock);
14200c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->sliced_cc_mode.slock);
14210c0d06caSMauro Carvalho Chehab 
14220c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->open);
14230c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_frame);
14240c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_stream);
14250c0d06caSMauro Carvalho Chehab 
14260c0d06caSMauro Carvalho Chehab 	dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
14270c0d06caSMauro Carvalho Chehab 	dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
14280c0d06caSMauro Carvalho Chehab 	dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
14290c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
14300c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
14310c0d06caSMauro Carvalho Chehab 
14320c0d06caSMauro Carvalho Chehab 	/* Query cx231xx to find what pcb config it is related to */
143352841e5eSMauro Carvalho Chehab 	retval = initialize_cx231xx(dev);
143452841e5eSMauro Carvalho Chehab 	if (retval < 0) {
1435336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Failed to read PCB config\n");
143652841e5eSMauro Carvalho Chehab 		return retval;
143752841e5eSMauro Carvalho Chehab 	}
14380c0d06caSMauro Carvalho Chehab 
14390c0d06caSMauro Carvalho Chehab 	/*To workaround error number=-71 on EP0 for VideoGrabber,
14400c0d06caSMauro Carvalho Chehab 		 need set alt here.*/
14410c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
14420c0d06caSMauro Carvalho Chehab 	    dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
14430c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
14440c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
14450c0d06caSMauro Carvalho Chehab 	}
14460c0d06caSMauro Carvalho Chehab 	/* Cx231xx pre card setup */
14470c0d06caSMauro Carvalho Chehab 	cx231xx_pre_card_setup(dev);
14480c0d06caSMauro Carvalho Chehab 
1449256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1450256d013aSAlexey Khoroshilov 	if (retval) {
1451336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "error configuring device\n");
14520c0d06caSMauro Carvalho Chehab 		return -ENOMEM;
14530c0d06caSMauro Carvalho Chehab 	}
14540c0d06caSMauro Carvalho Chehab 
14550c0d06caSMauro Carvalho Chehab 	/* set default norm */
14560c0d06caSMauro Carvalho Chehab 	dev->norm = dev->board.norm;
14570c0d06caSMauro Carvalho Chehab 
14580c0d06caSMauro Carvalho Chehab 	/* register i2c bus */
1459256d013aSAlexey Khoroshilov 	retval = cx231xx_dev_init(dev);
1460256d013aSAlexey Khoroshilov 	if (retval) {
1461336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1462b7085c08SMauro Carvalho Chehab 			"%s: cx231xx_i2c_register - errCode [%d]!\n",
1463256d013aSAlexey Khoroshilov 			__func__, retval);
1464256d013aSAlexey Khoroshilov 		goto err_dev_init;
14650c0d06caSMauro Carvalho Chehab 	}
14660c0d06caSMauro Carvalho Chehab 
14670c0d06caSMauro Carvalho Chehab 	/* Do board specific init */
14680c0d06caSMauro Carvalho Chehab 	cx231xx_card_setup(dev);
14690c0d06caSMauro Carvalho Chehab 
14700c0d06caSMauro Carvalho Chehab 	/* configure the device */
14710c0d06caSMauro Carvalho Chehab 	cx231xx_config_i2c(dev);
14720c0d06caSMauro Carvalho Chehab 
14730c0d06caSMauro Carvalho Chehab 	maxw = norm_maxw(dev);
14740c0d06caSMauro Carvalho Chehab 	maxh = norm_maxh(dev);
14750c0d06caSMauro Carvalho Chehab 
14760c0d06caSMauro Carvalho Chehab 	/* set default image size */
14770c0d06caSMauro Carvalho Chehab 	dev->width = maxw;
14780c0d06caSMauro Carvalho Chehab 	dev->height = maxh;
14790c0d06caSMauro Carvalho Chehab 	dev->interlaced = 0;
14800c0d06caSMauro Carvalho Chehab 	dev->video_input = 0;
14810c0d06caSMauro Carvalho Chehab 
1482256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1483256d013aSAlexey Khoroshilov 	if (retval) {
1484336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "%s: cx231xx_config - errCode [%d]!\n",
1485256d013aSAlexey Khoroshilov 			__func__, retval);
1486256d013aSAlexey Khoroshilov 		goto err_dev_init;
14870c0d06caSMauro Carvalho Chehab 	}
14880c0d06caSMauro Carvalho Chehab 
14890c0d06caSMauro Carvalho Chehab 	/* init video dma queues */
14900c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->video_mode.vidq.active);
14910c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
14920c0d06caSMauro Carvalho Chehab 
14930c0d06caSMauro Carvalho Chehab 	/* init vbi dma queues */
14940c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
14950c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
14960c0d06caSMauro Carvalho Chehab 
14970c0d06caSMauro Carvalho Chehab 	/* Reset other chips required if they are tied up with GPIO pins */
14980c0d06caSMauro Carvalho Chehab 	cx231xx_add_into_devlist(dev);
14990c0d06caSMauro Carvalho Chehab 
15000c0d06caSMauro Carvalho Chehab 	if (dev->board.has_417) {
1501336fea92SMauro Carvalho Chehab 		dev_info(dev->dev, "attach 417 %d\n", dev->model);
15020c0d06caSMauro Carvalho Chehab 		if (cx231xx_417_register(dev) < 0) {
1503336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
15040c0d06caSMauro Carvalho Chehab 				"%s() Failed to register 417 on VID_B\n",
15050c0d06caSMauro Carvalho Chehab 				__func__);
15060c0d06caSMauro Carvalho Chehab 		}
15070c0d06caSMauro Carvalho Chehab 	}
15080c0d06caSMauro Carvalho Chehab 
15090c0d06caSMauro Carvalho Chehab 	retval = cx231xx_register_analog_devices(dev);
15101d058bdcSMauro Carvalho Chehab 	if (retval)
1511256d013aSAlexey Khoroshilov 		goto err_analog;
15120c0d06caSMauro Carvalho Chehab 
15130c0d06caSMauro Carvalho Chehab 	cx231xx_ir_init(dev);
15140c0d06caSMauro Carvalho Chehab 
15150c0d06caSMauro Carvalho Chehab 	cx231xx_init_extension(dev);
15160c0d06caSMauro Carvalho Chehab 
15170c0d06caSMauro Carvalho Chehab 	return 0;
1518256d013aSAlexey Khoroshilov err_analog:
15191d058bdcSMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
15201d058bdcSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
1521256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1522256d013aSAlexey Khoroshilov err_dev_init:
1523256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1524256d013aSAlexey Khoroshilov 	return retval;
15250c0d06caSMauro Carvalho Chehab }
15260c0d06caSMauro Carvalho Chehab 
15270c0d06caSMauro Carvalho Chehab #if defined(CONFIG_MODULES) && defined(MODULE)
15280c0d06caSMauro Carvalho Chehab static void request_module_async(struct work_struct *work)
15290c0d06caSMauro Carvalho Chehab {
15300c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = container_of(work,
15310c0d06caSMauro Carvalho Chehab 					   struct cx231xx, request_module_wk);
15320c0d06caSMauro Carvalho Chehab 
15330c0d06caSMauro Carvalho Chehab 	if (dev->has_alsa_audio)
15340c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-alsa");
15350c0d06caSMauro Carvalho Chehab 
15360c0d06caSMauro Carvalho Chehab 	if (dev->board.has_dvb)
15370c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-dvb");
15380c0d06caSMauro Carvalho Chehab 
15390c0d06caSMauro Carvalho Chehab }
15400c0d06caSMauro Carvalho Chehab 
15410c0d06caSMauro Carvalho Chehab static void request_modules(struct cx231xx *dev)
15420c0d06caSMauro Carvalho Chehab {
15430c0d06caSMauro Carvalho Chehab 	INIT_WORK(&dev->request_module_wk, request_module_async);
15440c0d06caSMauro Carvalho Chehab 	schedule_work(&dev->request_module_wk);
15450c0d06caSMauro Carvalho Chehab }
15460c0d06caSMauro Carvalho Chehab 
15470c0d06caSMauro Carvalho Chehab static void flush_request_modules(struct cx231xx *dev)
15480c0d06caSMauro Carvalho Chehab {
15490b8e74c6SLinus Torvalds 	flush_work(&dev->request_module_wk);
15500c0d06caSMauro Carvalho Chehab }
15510c0d06caSMauro Carvalho Chehab #else
15520c0d06caSMauro Carvalho Chehab #define request_modules(dev)
15530c0d06caSMauro Carvalho Chehab #define flush_request_modules(dev)
15540c0d06caSMauro Carvalho Chehab #endif /* CONFIG_MODULES */
15550c0d06caSMauro Carvalho Chehab 
15564d2a7d35SMauro Carvalho Chehab static int cx231xx_init_v4l2(struct cx231xx *dev,
15574d2a7d35SMauro Carvalho Chehab 			     struct usb_device *udev,
15584d2a7d35SMauro Carvalho Chehab 			     struct usb_interface *interface,
15594d2a7d35SMauro Carvalho Chehab 			     int isoc_pipe)
15604d2a7d35SMauro Carvalho Chehab {
15614d2a7d35SMauro Carvalho Chehab 	struct usb_interface *uif;
15624d2a7d35SMauro Carvalho Chehab 	int i, idx;
15634d2a7d35SMauro Carvalho Chehab 
15644d2a7d35SMauro Carvalho Chehab 	/* Video Init */
15654d2a7d35SMauro Carvalho Chehab 
15664d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for video */
15674d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
15684d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1569336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1570b7085c08SMauro Carvalho Chehab 			"Video PCB interface #%d doesn't exist\n", idx);
15714d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
15724d2a7d35SMauro Carvalho Chehab 	}
15734d2a7d35SMauro Carvalho Chehab 
15744d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
15754d2a7d35SMauro Carvalho Chehab 
15760cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
15770cd273bbSJohan Hovold 		return -ENODEV;
15780cd273bbSJohan Hovold 
15794d2a7d35SMauro Carvalho Chehab 	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
15804d2a7d35SMauro Carvalho Chehab 	dev->video_mode.num_alt = uif->num_altsetting;
15814d2a7d35SMauro Carvalho Chehab 
1582336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1583b7085c08SMauro Carvalho Chehab 		 "video EndPoint Addr 0x%x, Alternate settings: %i\n",
15844d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.end_point_addr,
15854d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.num_alt);
15864d2a7d35SMauro Carvalho Chehab 
15874d2a7d35SMauro Carvalho Chehab 	dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
1588ed0e3729SMauro Carvalho Chehab 	if (dev->video_mode.alt_max_pkt_size == NULL)
15894d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
15904d2a7d35SMauro Carvalho Chehab 
15914d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->video_mode.num_alt; i++) {
15920cd273bbSJohan Hovold 		u16 tmp;
15930cd273bbSJohan Hovold 
15940cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
15950cd273bbSJohan Hovold 			return -ENODEV;
15960cd273bbSJohan Hovold 
15970cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
15984d2a7d35SMauro Carvalho Chehab 		dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1599336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1600b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
16014d2a7d35SMauro Carvalho Chehab 			dev->video_mode.alt_max_pkt_size[i]);
16024d2a7d35SMauro Carvalho Chehab 	}
16034d2a7d35SMauro Carvalho Chehab 
16044d2a7d35SMauro Carvalho Chehab 	/* VBI Init */
16054d2a7d35SMauro Carvalho Chehab 
16064d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
16074d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1608336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1609b7085c08SMauro Carvalho Chehab 			"VBI PCB interface #%d doesn't exist\n", idx);
16104d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
16114d2a7d35SMauro Carvalho Chehab 	}
16124d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
16134d2a7d35SMauro Carvalho Chehab 
16140cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
16150cd273bbSJohan Hovold 		return -ENODEV;
16160cd273bbSJohan Hovold 
16174d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.end_point_addr =
16184d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
16194d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
16204d2a7d35SMauro Carvalho Chehab 
16214d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.num_alt = uif->num_altsetting;
1622336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1623b7085c08SMauro Carvalho Chehab 		 "VBI EndPoint Addr 0x%x, Alternate settings: %i\n",
16244d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.end_point_addr,
16254d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.num_alt);
16264d2a7d35SMauro Carvalho Chehab 
16274d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for vbi */
16284d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
1629ed0e3729SMauro Carvalho Chehab 	if (dev->vbi_mode.alt_max_pkt_size == NULL)
16304d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
16314d2a7d35SMauro Carvalho Chehab 
16324d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
16330cd273bbSJohan Hovold 		u16 tmp;
16340cd273bbSJohan Hovold 
16350cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
16360cd273bbSJohan Hovold 			return -ENODEV;
16370cd273bbSJohan Hovold 
16380cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
16394d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
16404d2a7d35SMauro Carvalho Chehab 		dev->vbi_mode.alt_max_pkt_size[i] =
16414d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1642336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1643b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
16444d2a7d35SMauro Carvalho Chehab 			dev->vbi_mode.alt_max_pkt_size[i]);
16454d2a7d35SMauro Carvalho Chehab 	}
16464d2a7d35SMauro Carvalho Chehab 
16474d2a7d35SMauro Carvalho Chehab 	/* Sliced CC VBI init */
16484d2a7d35SMauro Carvalho Chehab 
16494d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for sliced CC */
16504d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
16514d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1652336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1653b7085c08SMauro Carvalho Chehab 			"Sliced CC PCB interface #%d doesn't exist\n", idx);
16544d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
16554d2a7d35SMauro Carvalho Chehab 	}
16564d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
16574d2a7d35SMauro Carvalho Chehab 
16580cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
16590cd273bbSJohan Hovold 		return -ENODEV;
16600cd273bbSJohan Hovold 
16614d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.end_point_addr =
16624d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
16634d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
16644d2a7d35SMauro Carvalho Chehab 
16654d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
1666336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1667b7085c08SMauro Carvalho Chehab 		 "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
16684d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.end_point_addr,
16694d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.num_alt);
16704d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
1671ed0e3729SMauro Carvalho Chehab 	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
16724d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
16734d2a7d35SMauro Carvalho Chehab 
16744d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
16750cd273bbSJohan Hovold 		u16 tmp;
16760cd273bbSJohan Hovold 
16770cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
16780cd273bbSJohan Hovold 			return -ENODEV;
16790cd273bbSJohan Hovold 
16800cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
16814d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
16824d2a7d35SMauro Carvalho Chehab 		dev->sliced_cc_mode.alt_max_pkt_size[i] =
16834d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1684336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1685b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
16864d2a7d35SMauro Carvalho Chehab 			dev->sliced_cc_mode.alt_max_pkt_size[i]);
16874d2a7d35SMauro Carvalho Chehab 	}
16884d2a7d35SMauro Carvalho Chehab 
16894d2a7d35SMauro Carvalho Chehab 	return 0;
16904d2a7d35SMauro Carvalho Chehab }
16914d2a7d35SMauro Carvalho Chehab 
16920c0d06caSMauro Carvalho Chehab /*
16930c0d06caSMauro Carvalho Chehab  * cx231xx_usb_probe()
16940c0d06caSMauro Carvalho Chehab  * checks for supported devices
16950c0d06caSMauro Carvalho Chehab  */
16960c0d06caSMauro Carvalho Chehab static int cx231xx_usb_probe(struct usb_interface *interface,
16970c0d06caSMauro Carvalho Chehab 			     const struct usb_device_id *id)
16980c0d06caSMauro Carvalho Chehab {
16990c0d06caSMauro Carvalho Chehab 	struct usb_device *udev;
1700336fea92SMauro Carvalho Chehab 	struct device *d = &interface->dev;
17010c0d06caSMauro Carvalho Chehab 	struct usb_interface *uif;
17020c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = NULL;
17030c0d06caSMauro Carvalho Chehab 	int retval = -ENODEV;
17040c0d06caSMauro Carvalho Chehab 	int nr = 0, ifnum;
17050c0d06caSMauro Carvalho Chehab 	int i, isoc_pipe = 0;
17060c0d06caSMauro Carvalho Chehab 	char *speed;
1707dcb78ac7SMauro Carvalho Chehab 	u8 idx;
17080c0d06caSMauro Carvalho Chehab 	struct usb_interface_assoc_descriptor *assoc_desc;
17090c0d06caSMauro Carvalho Chehab 
17100c0d06caSMauro Carvalho Chehab 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
17110c0d06caSMauro Carvalho Chehab 
17120c0d06caSMauro Carvalho Chehab 	/*
17130c0d06caSMauro Carvalho Chehab 	 * Interface number 0 - IR interface (handled by mceusb driver)
17140c0d06caSMauro Carvalho Chehab 	 * Interface number 1 - AV interface (handled by this driver)
17150c0d06caSMauro Carvalho Chehab 	 */
17160c0d06caSMauro Carvalho Chehab 	if (ifnum != 1)
17170c0d06caSMauro Carvalho Chehab 		return -ENODEV;
17180c0d06caSMauro Carvalho Chehab 
17190c0d06caSMauro Carvalho Chehab 	/* Check to see next free device and mark as used */
17200c0d06caSMauro Carvalho Chehab 	do {
17210c0d06caSMauro Carvalho Chehab 		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
17220c0d06caSMauro Carvalho Chehab 		if (nr >= CX231XX_MAXBOARDS) {
17230c0d06caSMauro Carvalho Chehab 			/* No free device slots */
1724336fea92SMauro Carvalho Chehab 			dev_err(d,
1725b7085c08SMauro Carvalho Chehab 				"Supports only %i devices.\n",
1726b7085c08SMauro Carvalho Chehab 				CX231XX_MAXBOARDS);
17270c0d06caSMauro Carvalho Chehab 			return -ENOMEM;
17280c0d06caSMauro Carvalho Chehab 		}
17290c0d06caSMauro Carvalho Chehab 	} while (test_and_set_bit(nr, &cx231xx_devused));
17300c0d06caSMauro Carvalho Chehab 
17315eeb3014SAlexey Khoroshilov 	udev = usb_get_dev(interface_to_usbdev(interface));
17325eeb3014SAlexey Khoroshilov 
17330c0d06caSMauro Carvalho Chehab 	/* allocate memory for our device state and initialize it */
1734184a8278SMauro Carvalho Chehab 	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
17350c0d06caSMauro Carvalho Chehab 	if (dev == NULL) {
17365eeb3014SAlexey Khoroshilov 		retval = -ENOMEM;
17375eeb3014SAlexey Khoroshilov 		goto err_if;
17380c0d06caSMauro Carvalho Chehab 	}
17390c0d06caSMauro Carvalho Chehab 
17400c0d06caSMauro Carvalho Chehab 	snprintf(dev->name, 29, "cx231xx #%d", nr);
17410c0d06caSMauro Carvalho Chehab 	dev->devno = nr;
17420c0d06caSMauro Carvalho Chehab 	dev->model = id->driver_info;
17430c0d06caSMauro Carvalho Chehab 	dev->video_mode.alt = -1;
1744336fea92SMauro Carvalho Chehab 	dev->dev = d;
17450c0d06caSMauro Carvalho Chehab 
17461d058bdcSMauro Carvalho Chehab 	cx231xx_set_model(dev);
17471d058bdcSMauro Carvalho Chehab 
17480c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
17490c0d06caSMauro Carvalho Chehab 	/* reset gpio dir and value */
17500c0d06caSMauro Carvalho Chehab 	dev->gpio_dir = 0;
17510c0d06caSMauro Carvalho Chehab 	dev->gpio_val = 0;
17520c0d06caSMauro Carvalho Chehab 	dev->xc_fw_load_done = 0;
17530c0d06caSMauro Carvalho Chehab 	dev->has_alsa_audio = 1;
17540c0d06caSMauro Carvalho Chehab 	dev->power_mode = -1;
17550c0d06caSMauro Carvalho Chehab 	atomic_set(&dev->devlist_count, 0);
17560c0d06caSMauro Carvalho Chehab 
17570c0d06caSMauro Carvalho Chehab 	/* 0 - vbi ; 1 -sliced cc mode */
17580c0d06caSMauro Carvalho Chehab 	dev->vbi_or_sliced_cc_mode = 0;
17590c0d06caSMauro Carvalho Chehab 
17600c0d06caSMauro Carvalho Chehab 	/* get maximum no.of IAD interfaces */
1761139d2882SMauro Carvalho Chehab 	dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
17620c0d06caSMauro Carvalho Chehab 
17630c0d06caSMauro Carvalho Chehab 	/* init CIR module TBD */
17640c0d06caSMauro Carvalho Chehab 
17650c0d06caSMauro Carvalho Chehab 	/*mode_tv: digital=1 or analog=0*/
17660c0d06caSMauro Carvalho Chehab 	dev->mode_tv = 0;
17670c0d06caSMauro Carvalho Chehab 
17680c0d06caSMauro Carvalho Chehab 	dev->USE_ISO = transfer_mode;
17690c0d06caSMauro Carvalho Chehab 
17700c0d06caSMauro Carvalho Chehab 	switch (udev->speed) {
17710c0d06caSMauro Carvalho Chehab 	case USB_SPEED_LOW:
17720c0d06caSMauro Carvalho Chehab 		speed = "1.5";
17730c0d06caSMauro Carvalho Chehab 		break;
17740c0d06caSMauro Carvalho Chehab 	case USB_SPEED_UNKNOWN:
17750c0d06caSMauro Carvalho Chehab 	case USB_SPEED_FULL:
17760c0d06caSMauro Carvalho Chehab 		speed = "12";
17770c0d06caSMauro Carvalho Chehab 		break;
17780c0d06caSMauro Carvalho Chehab 	case USB_SPEED_HIGH:
17790c0d06caSMauro Carvalho Chehab 		speed = "480";
17800c0d06caSMauro Carvalho Chehab 		break;
17810c0d06caSMauro Carvalho Chehab 	default:
17820c0d06caSMauro Carvalho Chehab 		speed = "unknown";
17830c0d06caSMauro Carvalho Chehab 	}
17840c0d06caSMauro Carvalho Chehab 
1785336fea92SMauro Carvalho Chehab 	dev_info(d,
1786b7085c08SMauro Carvalho Chehab 		 "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
17870c0d06caSMauro Carvalho Chehab 		 udev->manufacturer ? udev->manufacturer : "",
17880c0d06caSMauro Carvalho Chehab 		 udev->product ? udev->product : "",
17890c0d06caSMauro Carvalho Chehab 		 speed,
17900c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idVendor),
17910c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idProduct),
17920c0d06caSMauro Carvalho Chehab 		 dev->max_iad_interface_count);
17930c0d06caSMauro Carvalho Chehab 
17940c0d06caSMauro Carvalho Chehab 	/* increment interface count */
17950c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
17960c0d06caSMauro Carvalho Chehab 
17970c0d06caSMauro Carvalho Chehab 	/* get device number */
17980c0d06caSMauro Carvalho Chehab 	nr = dev->devno;
17990c0d06caSMauro Carvalho Chehab 
18000c0d06caSMauro Carvalho Chehab 	assoc_desc = udev->actconfig->intf_assoc[0];
18016c3b047fSJohan Hovold 	if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) {
1802336fea92SMauro Carvalho Chehab 		dev_err(d, "Not found matching IAD interface\n");
1803256d013aSAlexey Khoroshilov 		retval = -ENODEV;
1804256d013aSAlexey Khoroshilov 		goto err_if;
18050c0d06caSMauro Carvalho Chehab 	}
18060c0d06caSMauro Carvalho Chehab 
1807336fea92SMauro Carvalho Chehab 	dev_dbg(d, "registering interface %d\n", ifnum);
18080c0d06caSMauro Carvalho Chehab 
18090c0d06caSMauro Carvalho Chehab 	/* save our data pointer in this interface device */
18100c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, dev);
18110c0d06caSMauro Carvalho Chehab 
18129832e155SJavier Martinez Canillas 	/* Initialize the media controller */
18139f806795SMauro Carvalho Chehab 	retval = cx231xx_media_device_init(dev, udev);
18149f806795SMauro Carvalho Chehab 	if (retval) {
18159f806795SMauro Carvalho Chehab 		dev_err(d, "cx231xx_media_device_init failed\n");
18169f806795SMauro Carvalho Chehab 		goto err_media_init;
18179f806795SMauro Carvalho Chehab 	}
18181d058bdcSMauro Carvalho Chehab 
18190c0d06caSMauro Carvalho Chehab 	/* Create v4l2 device */
182063ba8c75SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
18211d058bdcSMauro Carvalho Chehab 	dev->v4l2_dev.mdev = dev->media_dev;
182263ba8c75SMauro Carvalho Chehab #endif
18230c0d06caSMauro Carvalho Chehab 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
18240c0d06caSMauro Carvalho Chehab 	if (retval) {
1825336fea92SMauro Carvalho Chehab 		dev_err(d, "v4l2_device_register failed\n");
1826256d013aSAlexey Khoroshilov 		goto err_v4l2;
18270c0d06caSMauro Carvalho Chehab 	}
18284d2a7d35SMauro Carvalho Chehab 
18290c0d06caSMauro Carvalho Chehab 	/* allocate device struct */
18300c0d06caSMauro Carvalho Chehab 	retval = cx231xx_init_dev(dev, udev, nr);
1831256d013aSAlexey Khoroshilov 	if (retval)
1832256d013aSAlexey Khoroshilov 		goto err_init;
18330c0d06caSMauro Carvalho Chehab 
18344d2a7d35SMauro Carvalho Chehab 	retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
18354d2a7d35SMauro Carvalho Chehab 	if (retval)
1836dcb78ac7SMauro Carvalho Chehab 		goto err_init;
18370c0d06caSMauro Carvalho Chehab 
18380c0d06caSMauro Carvalho Chehab 	if (dev->current_pcb_config.ts1_source != 0xff) {
18390c0d06caSMauro Carvalho Chehab 		/* compute alternate max packet sizes for TS1 */
1840dcb78ac7SMauro Carvalho Chehab 		idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
1841dcb78ac7SMauro Carvalho Chehab 		if (idx >= dev->max_iad_interface_count) {
1842336fea92SMauro Carvalho Chehab 			dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
1843336fea92SMauro Carvalho Chehab 				idx);
1844dcb78ac7SMauro Carvalho Chehab 			retval = -ENODEV;
1845184a8278SMauro Carvalho Chehab 			goto err_video_alt;
1846dcb78ac7SMauro Carvalho Chehab 		}
1847dcb78ac7SMauro Carvalho Chehab 		uif = udev->actconfig->interface[idx];
18480c0d06caSMauro Carvalho Chehab 
18490cd273bbSJohan Hovold 		if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
18500cd273bbSJohan Hovold 			retval = -ENODEV;
18510cd273bbSJohan Hovold 			goto err_video_alt;
18520cd273bbSJohan Hovold 		}
18530cd273bbSJohan Hovold 
18540c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.end_point_addr =
185569a11a32SHans Verkuil 		    uif->altsetting[0].endpoint[isoc_pipe].
185669a11a32SHans Verkuil 				desc.bEndpointAddress;
18570c0d06caSMauro Carvalho Chehab 
18580c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.num_alt = uif->num_altsetting;
1859336fea92SMauro Carvalho Chehab 		dev_info(d,
1860b7085c08SMauro Carvalho Chehab 			 "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
18610c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.end_point_addr,
18620c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.num_alt);
18630c0d06caSMauro Carvalho Chehab 
1864184a8278SMauro Carvalho Chehab 		dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
18650c0d06caSMauro Carvalho Chehab 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
1866256d013aSAlexey Khoroshilov 			retval = -ENOMEM;
1867184a8278SMauro Carvalho Chehab 			goto err_video_alt;
18680c0d06caSMauro Carvalho Chehab 		}
18690c0d06caSMauro Carvalho Chehab 
18700c0d06caSMauro Carvalho Chehab 		for (i = 0; i < dev->ts1_mode.num_alt; i++) {
18710cd273bbSJohan Hovold 			u16 tmp;
18720cd273bbSJohan Hovold 
18730cd273bbSJohan Hovold 			if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
18740cd273bbSJohan Hovold 				retval = -ENODEV;
18750cd273bbSJohan Hovold 				goto err_video_alt;
18760cd273bbSJohan Hovold 			}
18770cd273bbSJohan Hovold 
18780cd273bbSJohan Hovold 			tmp = le16_to_cpu(uif->altsetting[i].
18790c0d06caSMauro Carvalho Chehab 						endpoint[isoc_pipe].desc.
18800c0d06caSMauro Carvalho Chehab 						wMaxPacketSize);
18810c0d06caSMauro Carvalho Chehab 			dev->ts1_mode.alt_max_pkt_size[i] =
18820c0d06caSMauro Carvalho Chehab 			    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1883336fea92SMauro Carvalho Chehab 			dev_dbg(d, "Alternate setting %i, max size= %i\n",
1884336fea92SMauro Carvalho Chehab 				i, dev->ts1_mode.alt_max_pkt_size[i]);
18850c0d06caSMauro Carvalho Chehab 		}
18860c0d06caSMauro Carvalho Chehab 	}
18870c0d06caSMauro Carvalho Chehab 
18880c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
18890c0d06caSMauro Carvalho Chehab 		cx231xx_enable_OSC(dev);
18900c0d06caSMauro Carvalho Chehab 		cx231xx_reset_out(dev);
18910c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
18920c0d06caSMauro Carvalho Chehab 	}
18930c0d06caSMauro Carvalho Chehab 
18940c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
18950c0d06caSMauro Carvalho Chehab 		cx231xx_sleep_s5h1432(dev);
18960c0d06caSMauro Carvalho Chehab 
18970c0d06caSMauro Carvalho Chehab 	/* load other modules required */
18980c0d06caSMauro Carvalho Chehab 	request_modules(dev);
18990c0d06caSMauro Carvalho Chehab 
19009832e155SJavier Martinez Canillas #ifdef CONFIG_MEDIA_CONTROLLER
19016168309aSMauro Carvalho Chehab 	/* Init entities at the Media Controller */
19026168309aSMauro Carvalho Chehab 	cx231xx_v4l2_create_entities(dev);
19036168309aSMauro Carvalho Chehab 
190408f49200SMauro Carvalho Chehab 	retval = v4l2_mc_create_media_graph(dev->media_dev);
190508f49200SMauro Carvalho Chehab 	if (!retval)
19069832e155SJavier Martinez Canillas 		retval = media_device_register(dev->media_dev);
19079832e155SJavier Martinez Canillas #endif
19089832e155SJavier Martinez Canillas 	if (retval < 0)
19099832e155SJavier Martinez Canillas 		cx231xx_release_resources(dev);
1910ab232e46SMauro Carvalho Chehab 	return retval;
19119832e155SJavier Martinez Canillas 
1912256d013aSAlexey Khoroshilov err_video_alt:
1913256d013aSAlexey Khoroshilov 	/* cx231xx_uninit_dev: */
1914256d013aSAlexey Khoroshilov 	cx231xx_close_extension(dev);
1915256d013aSAlexey Khoroshilov 	cx231xx_ir_exit(dev);
1916256d013aSAlexey Khoroshilov 	cx231xx_release_analog_resources(dev);
1917256d013aSAlexey Khoroshilov 	cx231xx_417_unregister(dev);
1918256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1919256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1920256d013aSAlexey Khoroshilov err_init:
1921256d013aSAlexey Khoroshilov 	v4l2_device_unregister(&dev->v4l2_dev);
1922256d013aSAlexey Khoroshilov err_v4l2:
19239f806795SMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
19249f806795SMauro Carvalho Chehab err_media_init:
1925256d013aSAlexey Khoroshilov 	usb_set_intfdata(interface, NULL);
1926256d013aSAlexey Khoroshilov err_if:
1927256d013aSAlexey Khoroshilov 	usb_put_dev(udev);
1928b5603a94SMauro Carvalho Chehab 	clear_bit(nr, &cx231xx_devused);
1929256d013aSAlexey Khoroshilov 	return retval;
19300c0d06caSMauro Carvalho Chehab }
19310c0d06caSMauro Carvalho Chehab 
19320c0d06caSMauro Carvalho Chehab /*
19330c0d06caSMauro Carvalho Chehab  * cx231xx_usb_disconnect()
19340c0d06caSMauro Carvalho Chehab  * called when the device gets diconencted
19350c0d06caSMauro Carvalho Chehab  * video device will be unregistered on v4l2_close in case it is still open
19360c0d06caSMauro Carvalho Chehab  */
19370c0d06caSMauro Carvalho Chehab static void cx231xx_usb_disconnect(struct usb_interface *interface)
19380c0d06caSMauro Carvalho Chehab {
19390c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev;
19400c0d06caSMauro Carvalho Chehab 
19410c0d06caSMauro Carvalho Chehab 	dev = usb_get_intfdata(interface);
19420c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, NULL);
19430c0d06caSMauro Carvalho Chehab 
19440c0d06caSMauro Carvalho Chehab 	if (!dev)
19450c0d06caSMauro Carvalho Chehab 		return;
19460c0d06caSMauro Carvalho Chehab 
19470c0d06caSMauro Carvalho Chehab 	if (!dev->udev)
19480c0d06caSMauro Carvalho Chehab 		return;
19490c0d06caSMauro Carvalho Chehab 
19500c0d06caSMauro Carvalho Chehab 	dev->state |= DEV_DISCONNECTED;
19510c0d06caSMauro Carvalho Chehab 
19520c0d06caSMauro Carvalho Chehab 	flush_request_modules(dev);
19530c0d06caSMauro Carvalho Chehab 
19540c0d06caSMauro Carvalho Chehab 	/* wait until all current v4l2 io is finished then deallocate
19550c0d06caSMauro Carvalho Chehab 	   resources */
19560c0d06caSMauro Carvalho Chehab 	mutex_lock(&dev->lock);
19570c0d06caSMauro Carvalho Chehab 
19580c0d06caSMauro Carvalho Chehab 	wake_up_interruptible_all(&dev->open);
19590c0d06caSMauro Carvalho Chehab 
19600c0d06caSMauro Carvalho Chehab 	if (dev->users) {
1961336fea92SMauro Carvalho Chehab 		dev_warn(dev->dev,
1962b7085c08SMauro Carvalho Chehab 			 "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
196360acf187SHans Verkuil 			 video_device_node_name(&dev->vdev));
19640c0d06caSMauro Carvalho Chehab 
19650c0d06caSMauro Carvalho Chehab 		/* Even having users, it is safe to remove the RC i2c driver */
19660c0d06caSMauro Carvalho Chehab 		cx231xx_ir_exit(dev);
19670c0d06caSMauro Carvalho Chehab 
19680c0d06caSMauro Carvalho Chehab 		if (dev->USE_ISO)
19690c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_isoc(dev);
19700c0d06caSMauro Carvalho Chehab 		else
19710c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_bulk(dev);
19720c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_frame);
19730c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_stream);
19740c0d06caSMauro Carvalho Chehab 	} else {
19750c0d06caSMauro Carvalho Chehab 	}
19760c0d06caSMauro Carvalho Chehab 
19770c0d06caSMauro Carvalho Chehab 	cx231xx_close_extension(dev);
19780c0d06caSMauro Carvalho Chehab 
19790c0d06caSMauro Carvalho Chehab 	mutex_unlock(&dev->lock);
19800c0d06caSMauro Carvalho Chehab 
19810c0d06caSMauro Carvalho Chehab 	if (!dev->users)
19820c0d06caSMauro Carvalho Chehab 		cx231xx_release_resources(dev);
19830c0d06caSMauro Carvalho Chehab }
19840c0d06caSMauro Carvalho Chehab 
19850c0d06caSMauro Carvalho Chehab static struct usb_driver cx231xx_usb_driver = {
19860c0d06caSMauro Carvalho Chehab 	.name = "cx231xx",
19870c0d06caSMauro Carvalho Chehab 	.probe = cx231xx_usb_probe,
19880c0d06caSMauro Carvalho Chehab 	.disconnect = cx231xx_usb_disconnect,
19890c0d06caSMauro Carvalho Chehab 	.id_table = cx231xx_id_table,
19900c0d06caSMauro Carvalho Chehab };
19910c0d06caSMauro Carvalho Chehab 
19920c0d06caSMauro Carvalho Chehab module_usb_driver(cx231xx_usb_driver);
1993