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 
330c0d06caSMauro Carvalho Chehab #include <media/cx25840.h>
340c0d06caSMauro Carvalho Chehab #include "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,
355d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
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,
4890c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x00,	/* According with PV cxPolaris.inf file */
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,
716d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
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,
755d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
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,
794809abdbfSOlli Salonen 		.demod_i2c_master = I2C_2,
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 	},
8180c0d06caSMauro Carvalho Chehab };
8190c0d06caSMauro Carvalho Chehab const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
8200c0d06caSMauro Carvalho Chehab 
8210c0d06caSMauro Carvalho Chehab /* table of devices that work with this driver */
8220c0d06caSMauro Carvalho Chehab struct usb_device_id cx231xx_id_table[] = {
823dad4c418SLinks (Markus) 	{USB_DEVICE(0x1D19, 0x6109),
824dad4c418SLinks (Markus) 	.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
8250c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x5A3C),
8260c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_UNKNOWN},
8270c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A2),
8280c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
8290c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A1),
8300c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_SHELBY},
8310c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A4),
8320c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_253S},
8330c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A5),
8340c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_253S},
8350c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A6),
8360c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
8370c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x589E),
8380c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_250},
8390c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A0),
8400c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_250},
8410c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb110),
8420c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
8430c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb111),
8440c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
8450c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb120),
8460c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
847809abdbfSOlli Salonen 	{USB_DEVICE(0x2040, 0xb123),
848809abdbfSOlli Salonen 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q},
849dd2e7dd2SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb130),
850dd2e7dd2SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
8519e49f7c3SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb131),
8529e49f7c3SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
85357cbf3efSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-900-H */
85457cbf3efSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb138),
85557cbf3efSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
8568618ac4dSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-901-H */
8578618ac4dSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb139),
8588618ac4dSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
8590c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb140),
8600c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
8610c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xc200),
8620c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
863a141a887SMatthias Schwarzott 	/* PCTV QuatroStick 521e */
864a141a887SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x0259),
865a141a887SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
866140a7987SMatthias Schwarzott 	/* PCTV QuatroStick 522e */
867140a7987SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x025e),
868140a7987SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
8690c0d06caSMauro Carvalho Chehab 	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
8700c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
8710c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
8720c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
8730c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1b80, 0xe424),
8740c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID},
8758b1255a2SJohannes Erdfelt 	{USB_DEVICE(0x1b80, 0xe421),
8768b1255a2SJohannes Erdfelt 	 .driver_info = CX231XX_BOARD_KWORLD_UB445_USB_HYBRID},
8770c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1f4d, 0x0237),
8780c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_ICONBIT_U100},
87968c97bf3SAlf Høgemark 	{USB_DEVICE(0x0fd9, 0x0037),
88068c97bf3SAlf Høgemark 	 .driver_info = CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2},
8813ead1ba3SMatt Gomboc 	{USB_DEVICE(0x1f4d, 0x0102),
8823ead1ba3SMatt Gomboc 	 .driver_info = CX231XX_BOARD_OTG102},
8830c0d06caSMauro Carvalho Chehab 	{},
8840c0d06caSMauro Carvalho Chehab };
8850c0d06caSMauro Carvalho Chehab 
8860c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
8870c0d06caSMauro Carvalho Chehab 
8880c0d06caSMauro Carvalho Chehab /* cx231xx_tuner_callback
8890c0d06caSMauro Carvalho Chehab  * will be used to reset XC5000 tuner using GPIO pin
8900c0d06caSMauro Carvalho Chehab  */
8910c0d06caSMauro Carvalho Chehab 
8920c0d06caSMauro Carvalho Chehab int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
8930c0d06caSMauro Carvalho Chehab {
8940c0d06caSMauro Carvalho Chehab 	int rc = 0;
8950c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = ptr;
8960c0d06caSMauro Carvalho Chehab 
8970c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_XC5000) {
8980c0d06caSMauro Carvalho Chehab 		if (command == XC5000_TUNER_RESET) {
899336fea92SMauro Carvalho Chehab 			dev_dbg(dev->dev,
900b7085c08SMauro Carvalho Chehab 				"Tuner CB: RESET: cmd %d : tuner type %d\n",
9010c0d06caSMauro Carvalho Chehab 				command, dev->tuner_type);
9020c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
9030c0d06caSMauro Carvalho Chehab 					       1);
9040c0d06caSMauro Carvalho Chehab 			msleep(10);
9050c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
9060c0d06caSMauro Carvalho Chehab 					       0);
9070c0d06caSMauro Carvalho Chehab 			msleep(330);
9080c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
9090c0d06caSMauro Carvalho Chehab 					       1);
9100c0d06caSMauro Carvalho Chehab 			msleep(10);
9110c0d06caSMauro Carvalho Chehab 		}
9120c0d06caSMauro Carvalho Chehab 	} else if (dev->tuner_type == TUNER_NXP_TDA18271) {
9130c0d06caSMauro Carvalho Chehab 		switch (command) {
9140c0d06caSMauro Carvalho Chehab 		case TDA18271_CALLBACK_CMD_AGC_ENABLE:
9150c0d06caSMauro Carvalho Chehab 			if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
9160c0d06caSMauro Carvalho Chehab 				rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
9170c0d06caSMauro Carvalho Chehab 			break;
9180c0d06caSMauro Carvalho Chehab 		default:
9190c0d06caSMauro Carvalho Chehab 			rc = -EINVAL;
9200c0d06caSMauro Carvalho Chehab 			break;
9210c0d06caSMauro Carvalho Chehab 		}
9220c0d06caSMauro Carvalho Chehab 	}
9230c0d06caSMauro Carvalho Chehab 	return rc;
9240c0d06caSMauro Carvalho Chehab }
9250c0d06caSMauro Carvalho Chehab EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
9260c0d06caSMauro Carvalho Chehab 
927d4c06133SMauro Carvalho Chehab static void cx231xx_reset_out(struct cx231xx *dev)
9280c0d06caSMauro Carvalho Chehab {
9290c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
9300c0d06caSMauro Carvalho Chehab 	msleep(200);
9310c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
9320c0d06caSMauro Carvalho Chehab 	msleep(200);
9330c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
9340c0d06caSMauro Carvalho Chehab }
935d4c06133SMauro Carvalho Chehab 
936d4c06133SMauro Carvalho Chehab static void cx231xx_enable_OSC(struct cx231xx *dev)
9370c0d06caSMauro Carvalho Chehab {
9380c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
9390c0d06caSMauro Carvalho Chehab }
940d4c06133SMauro Carvalho Chehab 
941d4c06133SMauro Carvalho Chehab static void cx231xx_sleep_s5h1432(struct cx231xx *dev)
9420c0d06caSMauro Carvalho Chehab {
9430c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
9440c0d06caSMauro Carvalho Chehab }
9450c0d06caSMauro Carvalho Chehab 
9460c0d06caSMauro Carvalho Chehab static inline void cx231xx_set_model(struct cx231xx *dev)
9470c0d06caSMauro Carvalho Chehab {
9483724dde9SEzequiel Garcia 	dev->board = cx231xx_boards[dev->model];
9490c0d06caSMauro Carvalho Chehab }
9500c0d06caSMauro Carvalho Chehab 
9510c0d06caSMauro Carvalho Chehab /* Since cx231xx_pre_card_setup() requires a proper dev->model,
9520c0d06caSMauro Carvalho Chehab  * this won't work for boards with generic PCI IDs
9530c0d06caSMauro Carvalho Chehab  */
9540c0d06caSMauro Carvalho Chehab void cx231xx_pre_card_setup(struct cx231xx *dev)
9550c0d06caSMauro Carvalho Chehab {
956336fea92SMauro Carvalho Chehab 	dev_info(dev->dev, "Identified as %s (card=%d)\n",
9570c0d06caSMauro Carvalho Chehab 		dev->board.name, dev->model);
9580c0d06caSMauro Carvalho Chehab 
9590c0d06caSMauro Carvalho Chehab 	/* set the direction for GPIO pins */
9600c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_gpio) {
9610c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
9620c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
9630c0d06caSMauro Carvalho Chehab 	}
9640c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_sif_gpio >= 0)
9650c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
9660c0d06caSMauro Carvalho Chehab 
9670c0d06caSMauro Carvalho Chehab 	/* request some modules if any required */
9680c0d06caSMauro Carvalho Chehab 
9690c0d06caSMauro Carvalho Chehab 	/* set the mode to Analog mode initially */
9700c0d06caSMauro Carvalho Chehab 	cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
9710c0d06caSMauro Carvalho Chehab 
9720c0d06caSMauro Carvalho Chehab 	/* Unlock device */
9730c0d06caSMauro Carvalho Chehab 	/* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
9740c0d06caSMauro Carvalho Chehab 
9750c0d06caSMauro Carvalho Chehab }
9760c0d06caSMauro Carvalho Chehab 
9770c0d06caSMauro Carvalho Chehab static void cx231xx_config_tuner(struct cx231xx *dev)
9780c0d06caSMauro Carvalho Chehab {
9790c0d06caSMauro Carvalho Chehab 	struct tuner_setup tun_setup;
9800c0d06caSMauro Carvalho Chehab 	struct v4l2_frequency f;
9810c0d06caSMauro Carvalho Chehab 
9820c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_ABSENT)
9830c0d06caSMauro Carvalho Chehab 		return;
9840c0d06caSMauro Carvalho Chehab 
9850c0d06caSMauro Carvalho Chehab 	tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
9860c0d06caSMauro Carvalho Chehab 	tun_setup.type = dev->tuner_type;
9870c0d06caSMauro Carvalho Chehab 	tun_setup.addr = dev->tuner_addr;
9880c0d06caSMauro Carvalho Chehab 	tun_setup.tuner_callback = cx231xx_tuner_callback;
9890c0d06caSMauro Carvalho Chehab 
9900c0d06caSMauro Carvalho Chehab 	tuner_call(dev, tuner, s_type_addr, &tun_setup);
9910c0d06caSMauro Carvalho Chehab 
9920c0d06caSMauro Carvalho Chehab #if 0
9930c0d06caSMauro Carvalho Chehab 	if (tun_setup.type == TUNER_XC5000) {
9940c0d06caSMauro Carvalho Chehab 		static struct xc2028_ctrl ctrl = {
9950c0d06caSMauro Carvalho Chehab 			.fname = XC5000_DEFAULT_FIRMWARE,
9960c0d06caSMauro Carvalho Chehab 			.max_len = 64,
9970c0d06caSMauro Carvalho Chehab 			.demod = 0;
9980c0d06caSMauro Carvalho Chehab 		};
9990c0d06caSMauro Carvalho Chehab 		struct v4l2_priv_tun_config cfg = {
10000c0d06caSMauro Carvalho Chehab 			.tuner = dev->tuner_type,
10010c0d06caSMauro Carvalho Chehab 			.priv = &ctrl,
10020c0d06caSMauro Carvalho Chehab 		};
10030c0d06caSMauro Carvalho Chehab 		tuner_call(dev, tuner, s_config, &cfg);
10040c0d06caSMauro Carvalho Chehab 	}
10050c0d06caSMauro Carvalho Chehab #endif
10060c0d06caSMauro Carvalho Chehab 	/* configure tuner */
10070c0d06caSMauro Carvalho Chehab 	f.tuner = 0;
10080c0d06caSMauro Carvalho Chehab 	f.type = V4L2_TUNER_ANALOG_TV;
10090c0d06caSMauro Carvalho Chehab 	f.frequency = 9076;	/* just a magic number */
10100c0d06caSMauro Carvalho Chehab 	dev->ctl_freq = f.frequency;
10110c0d06caSMauro Carvalho Chehab 	call_all(dev, tuner, s_frequency, &f);
10120c0d06caSMauro Carvalho Chehab 
10130c0d06caSMauro Carvalho Chehab }
10140c0d06caSMauro Carvalho Chehab 
10159c672890SMatthias Schwarzott static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
10169c672890SMatthias Schwarzott 		       u8 *eedata, int len)
1017dd2e7dd2SMatthias Schwarzott {
1018dd2e7dd2SMatthias Schwarzott 	int ret = 0;
1019dd2e7dd2SMatthias Schwarzott 	u8 start_offset = 0;
1020dd2e7dd2SMatthias Schwarzott 	int len_todo = len;
1021dd2e7dd2SMatthias Schwarzott 	u8 *eedata_cur = eedata;
1022dd2e7dd2SMatthias Schwarzott 	int i;
10239c672890SMatthias Schwarzott 	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
1024dd2e7dd2SMatthias Schwarzott 		.buf = &start_offset, .len = 1 };
10259c672890SMatthias Schwarzott 	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
1026dd2e7dd2SMatthias Schwarzott 
1027dd2e7dd2SMatthias Schwarzott 	/* start reading at offset 0 */
10289c672890SMatthias Schwarzott 	ret = i2c_transfer(client->adapter, &msg_write, 1);
10291f97947cSMauro Carvalho Chehab 	if (ret < 0) {
1030336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Can't read eeprom\n");
10311f97947cSMauro Carvalho Chehab 		return ret;
10321f97947cSMauro Carvalho Chehab 	}
1033dd2e7dd2SMatthias Schwarzott 
1034dd2e7dd2SMatthias Schwarzott 	while (len_todo > 0) {
1035dd2e7dd2SMatthias Schwarzott 		msg_read.len = (len_todo > 64) ? 64 : len_todo;
1036dd2e7dd2SMatthias Schwarzott 		msg_read.buf = eedata_cur;
1037dd2e7dd2SMatthias Schwarzott 
10389c672890SMatthias Schwarzott 		ret = i2c_transfer(client->adapter, &msg_read, 1);
10391f97947cSMauro Carvalho Chehab 		if (ret < 0) {
1040336fea92SMauro Carvalho Chehab 			dev_err(dev->dev, "Can't read eeprom\n");
10411f97947cSMauro Carvalho Chehab 			return ret;
10421f97947cSMauro Carvalho Chehab 		}
1043dd2e7dd2SMatthias Schwarzott 		eedata_cur += msg_read.len;
1044dd2e7dd2SMatthias Schwarzott 		len_todo -= msg_read.len;
1045dd2e7dd2SMatthias Schwarzott 	}
1046dd2e7dd2SMatthias Schwarzott 
1047dd2e7dd2SMatthias Schwarzott 	for (i = 0; i + 15 < len; i += 16)
1048336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev, "i2c eeprom %02x: %*ph\n",
1049b7085c08SMauro Carvalho Chehab 			i, 16, &eedata[i]);
1050dd2e7dd2SMatthias Schwarzott 
1051dd2e7dd2SMatthias Schwarzott 	return 0;
1052dd2e7dd2SMatthias Schwarzott }
1053dd2e7dd2SMatthias Schwarzott 
10540c0d06caSMauro Carvalho Chehab void cx231xx_card_setup(struct cx231xx *dev)
10550c0d06caSMauro Carvalho Chehab {
10560c0d06caSMauro Carvalho Chehab 
10570c0d06caSMauro Carvalho Chehab 	cx231xx_set_model(dev);
10580c0d06caSMauro Carvalho Chehab 
10590c0d06caSMauro Carvalho Chehab 	dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
10600c0d06caSMauro Carvalho Chehab 	if (cx231xx_boards[dev->model].tuner_addr)
10610c0d06caSMauro Carvalho Chehab 		dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
10620c0d06caSMauro Carvalho Chehab 
10630c0d06caSMauro Carvalho Chehab 	/* request some modules */
10640c0d06caSMauro Carvalho Chehab 	if (dev->board.decoder == CX231XX_AVDECODER) {
10650c0d06caSMauro Carvalho Chehab 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1066c3c3f1aeSMatthias Schwarzott 					cx231xx_get_i2c_adap(dev, I2C_0),
10670c0d06caSMauro Carvalho Chehab 					"cx25840", 0x88 >> 1, NULL);
10680c0d06caSMauro Carvalho Chehab 		if (dev->sd_cx25840 == NULL)
1069336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1070b7085c08SMauro Carvalho Chehab 				"cx25840 subdev registration failure\n");
10710c0d06caSMauro Carvalho Chehab 		cx25840_call(dev, core, load_fw);
10720c0d06caSMauro Carvalho Chehab 
10730c0d06caSMauro Carvalho Chehab 	}
10740c0d06caSMauro Carvalho Chehab 
10750c0d06caSMauro Carvalho Chehab 	/* Initialize the tuner */
10760c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_type != TUNER_ABSENT) {
1077c3c3f1aeSMatthias Schwarzott 		struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
1078c3c3f1aeSMatthias Schwarzott 						dev->board.tuner_i2c_master);
10790c0d06caSMauro Carvalho Chehab 		dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1080c3c3f1aeSMatthias Schwarzott 						    tuner_i2c,
10810c0d06caSMauro Carvalho Chehab 						    "tuner",
10820c0d06caSMauro Carvalho Chehab 						    dev->tuner_addr, NULL);
10830c0d06caSMauro Carvalho Chehab 		if (dev->sd_tuner == NULL)
1084336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1085b7085c08SMauro Carvalho Chehab 				"tuner subdev registration failure\n");
10860c0d06caSMauro Carvalho Chehab 		else
10870c0d06caSMauro Carvalho Chehab 			cx231xx_config_tuner(dev);
10880c0d06caSMauro Carvalho Chehab 	}
1089dd2e7dd2SMatthias Schwarzott 
1090dd2e7dd2SMatthias Schwarzott 	switch (dev->model) {
1091dd2e7dd2SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
10929e49f7c3SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
1093809abdbfSOlli Salonen 	case CX231XX_BOARD_HAUPPAUGE_955Q:
1094dd2e7dd2SMatthias Schwarzott 		{
1095dd2e7dd2SMatthias Schwarzott 			struct tveeprom tvee;
1096dd2e7dd2SMatthias Schwarzott 			static u8 eeprom[256];
10979c672890SMatthias Schwarzott 			struct i2c_client client;
1098dd2e7dd2SMatthias Schwarzott 
10999c672890SMatthias Schwarzott 			memset(&client, 0, sizeof(client));
1100b9ce9dfdSMatthias Schwarzott 			client.adapter = cx231xx_get_i2c_adap(dev, I2C_1_MUX_1);
11019c672890SMatthias Schwarzott 			client.addr = 0xa0 >> 1;
11029c672890SMatthias Schwarzott 
11039c672890SMatthias Schwarzott 			read_eeprom(dev, &client, eeprom, sizeof(eeprom));
11049c672890SMatthias Schwarzott 			tveeprom_hauppauge_analog(&client,
1105dd2e7dd2SMatthias Schwarzott 						&tvee, eeprom + 0xc0);
1106dd2e7dd2SMatthias Schwarzott 			break;
1107dd2e7dd2SMatthias Schwarzott 		}
1108dd2e7dd2SMatthias Schwarzott 	}
1109dd2e7dd2SMatthias Schwarzott 
11100c0d06caSMauro Carvalho Chehab }
11110c0d06caSMauro Carvalho Chehab 
11120c0d06caSMauro Carvalho Chehab /*
11130c0d06caSMauro Carvalho Chehab  * cx231xx_config()
11140c0d06caSMauro Carvalho Chehab  * inits registers with sane defaults
11150c0d06caSMauro Carvalho Chehab  */
11160c0d06caSMauro Carvalho Chehab int cx231xx_config(struct cx231xx *dev)
11170c0d06caSMauro Carvalho Chehab {
11180c0d06caSMauro Carvalho Chehab 	/* TBD need to add cx231xx specific code */
11190c0d06caSMauro Carvalho Chehab 
11200c0d06caSMauro Carvalho Chehab 	return 0;
11210c0d06caSMauro Carvalho Chehab }
11220c0d06caSMauro Carvalho Chehab 
11230c0d06caSMauro Carvalho Chehab /*
11240c0d06caSMauro Carvalho Chehab  * cx231xx_config_i2c()
11250c0d06caSMauro Carvalho Chehab  * configure i2c attached devices
11260c0d06caSMauro Carvalho Chehab  */
11270c0d06caSMauro Carvalho Chehab void cx231xx_config_i2c(struct cx231xx *dev)
11280c0d06caSMauro Carvalho Chehab {
11290c0d06caSMauro Carvalho Chehab 	/* u32 input = INPUT(dev->video_input)->vmux; */
11300c0d06caSMauro Carvalho Chehab 
11310c0d06caSMauro Carvalho Chehab 	call_all(dev, video, s_stream, 1);
11320c0d06caSMauro Carvalho Chehab }
11330c0d06caSMauro Carvalho Chehab 
11341d058bdcSMauro Carvalho Chehab static void cx231xx_unregister_media_device(struct cx231xx *dev)
11351d058bdcSMauro Carvalho Chehab {
11361d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
11371d058bdcSMauro Carvalho Chehab 	if (dev->media_dev) {
11381d058bdcSMauro Carvalho Chehab 		media_device_unregister(dev->media_dev);
11391d058bdcSMauro Carvalho Chehab 		kfree(dev->media_dev);
11401d058bdcSMauro Carvalho Chehab 		dev->media_dev = NULL;
11411d058bdcSMauro Carvalho Chehab 	}
11421d058bdcSMauro Carvalho Chehab #endif
11431d058bdcSMauro Carvalho Chehab }
11441d058bdcSMauro Carvalho Chehab 
11450c0d06caSMauro Carvalho Chehab /*
11460c0d06caSMauro Carvalho Chehab  * cx231xx_realease_resources()
11470c0d06caSMauro Carvalho Chehab  * unregisters the v4l2,i2c and usb devices
11480c0d06caSMauro Carvalho Chehab  * called when the device gets disconected or at module unload
11490c0d06caSMauro Carvalho Chehab */
11500c0d06caSMauro Carvalho Chehab void cx231xx_release_resources(struct cx231xx *dev)
11510c0d06caSMauro Carvalho Chehab {
11521d058bdcSMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
11531d058bdcSMauro Carvalho Chehab 
11540c0d06caSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
11550c0d06caSMauro Carvalho Chehab 
11560c0d06caSMauro Carvalho Chehab 	cx231xx_remove_from_devlist(dev);
11570c0d06caSMauro Carvalho Chehab 
11580c0d06caSMauro Carvalho Chehab 	cx231xx_ir_exit(dev);
11590c0d06caSMauro Carvalho Chehab 
11600c0d06caSMauro Carvalho Chehab 	/* Release I2C buses */
11610c0d06caSMauro Carvalho Chehab 	cx231xx_dev_uninit(dev);
11620c0d06caSMauro Carvalho Chehab 
11630c0d06caSMauro Carvalho Chehab 	/* delete v4l2 device */
11640c0d06caSMauro Carvalho Chehab 	v4l2_device_unregister(&dev->v4l2_dev);
11650c0d06caSMauro Carvalho Chehab 
11660c0d06caSMauro Carvalho Chehab 	usb_put_dev(dev->udev);
11670c0d06caSMauro Carvalho Chehab 
11680c0d06caSMauro Carvalho Chehab 	/* Mark device as unused */
11690c0d06caSMauro Carvalho Chehab 	clear_bit(dev->devno, &cx231xx_devused);
11700c0d06caSMauro Carvalho Chehab }
11710c0d06caSMauro Carvalho Chehab 
11721d058bdcSMauro Carvalho Chehab static void cx231xx_media_device_register(struct cx231xx *dev,
11731d058bdcSMauro Carvalho Chehab 					  struct usb_device *udev)
11741d058bdcSMauro Carvalho Chehab {
11751d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
11761d058bdcSMauro Carvalho Chehab 	struct media_device *mdev;
11771d058bdcSMauro Carvalho Chehab 	int ret;
11781d058bdcSMauro Carvalho Chehab 
11791d058bdcSMauro Carvalho Chehab 	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
11801d058bdcSMauro Carvalho Chehab 	if (!mdev)
11811d058bdcSMauro Carvalho Chehab 		return;
11821d058bdcSMauro Carvalho Chehab 
11831d058bdcSMauro Carvalho Chehab 	mdev->dev = dev->dev;
11841d058bdcSMauro Carvalho Chehab 	strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
11851d058bdcSMauro Carvalho Chehab 	if (udev->serial)
11861d058bdcSMauro Carvalho Chehab 		strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
11871d058bdcSMauro Carvalho Chehab 	strcpy(mdev->bus_info, udev->devpath);
11881d058bdcSMauro Carvalho Chehab 	mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
11891d058bdcSMauro Carvalho Chehab 	mdev->driver_version = LINUX_VERSION_CODE;
11901d058bdcSMauro Carvalho Chehab 
11911d058bdcSMauro Carvalho Chehab 	ret = media_device_register(mdev);
11921d058bdcSMauro Carvalho Chehab 	if (ret) {
11931d058bdcSMauro Carvalho Chehab 		dev_err(dev->dev,
11941d058bdcSMauro Carvalho Chehab 			"Couldn't create a media device. Error: %d\n",
11951d058bdcSMauro Carvalho Chehab 			ret);
11961d058bdcSMauro Carvalho Chehab 		kfree(mdev);
11971d058bdcSMauro Carvalho Chehab 		return;
11981d058bdcSMauro Carvalho Chehab 	}
11991d058bdcSMauro Carvalho Chehab 
12001d058bdcSMauro Carvalho Chehab 	dev->media_dev = mdev;
12011d058bdcSMauro Carvalho Chehab #endif
12021d058bdcSMauro Carvalho Chehab }
12031d058bdcSMauro Carvalho Chehab 
1204d35a9855SMauro Carvalho Chehab static void cx231xx_create_media_graph(struct cx231xx *dev)
1205d35a9855SMauro Carvalho Chehab {
1206d35a9855SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
1207d35a9855SMauro Carvalho Chehab 	struct media_device *mdev = dev->media_dev;
1208d35a9855SMauro Carvalho Chehab 	struct media_entity *entity;
1209d35a9855SMauro Carvalho Chehab 	struct media_entity *tuner = NULL, *decoder = NULL;
1210d35a9855SMauro Carvalho Chehab 
1211d35a9855SMauro Carvalho Chehab 	if (!mdev)
1212d35a9855SMauro Carvalho Chehab 		return;
1213d35a9855SMauro Carvalho Chehab 
1214d35a9855SMauro Carvalho Chehab 	media_device_for_each_entity(entity, mdev) {
1215d35a9855SMauro Carvalho Chehab 		switch (entity->type) {
1216d35a9855SMauro Carvalho Chehab 		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
1217d35a9855SMauro Carvalho Chehab 			tuner = entity;
1218d35a9855SMauro Carvalho Chehab 			break;
1219d35a9855SMauro Carvalho Chehab 		case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
1220d35a9855SMauro Carvalho Chehab 			decoder = entity;
1221d35a9855SMauro Carvalho Chehab 			break;
1222d35a9855SMauro Carvalho Chehab 		}
1223d35a9855SMauro Carvalho Chehab 	}
1224d35a9855SMauro Carvalho Chehab 
1225d35a9855SMauro Carvalho Chehab 	/* Analog setup, using tuner as a link */
1226d35a9855SMauro Carvalho Chehab 
1227d35a9855SMauro Carvalho Chehab 	if (!decoder)
1228d35a9855SMauro Carvalho Chehab 		return;
1229d35a9855SMauro Carvalho Chehab 
1230d35a9855SMauro Carvalho Chehab 	if (tuner)
1231d35a9855SMauro Carvalho Chehab 		media_entity_create_link(tuner, 0, decoder, 0,
1232d35a9855SMauro Carvalho Chehab 					 MEDIA_LNK_FL_ENABLED);
123360acf187SHans Verkuil 	media_entity_create_link(decoder, 1, &dev->vdev.entity, 0,
1234d35a9855SMauro Carvalho Chehab 				 MEDIA_LNK_FL_ENABLED);
123560acf187SHans Verkuil 	media_entity_create_link(decoder, 2, &dev->vbi_dev.entity, 0,
1236d35a9855SMauro Carvalho Chehab 				 MEDIA_LNK_FL_ENABLED);
1237d35a9855SMauro Carvalho Chehab #endif
1238d35a9855SMauro Carvalho Chehab }
1239d35a9855SMauro Carvalho Chehab 
12400c0d06caSMauro Carvalho Chehab /*
12410c0d06caSMauro Carvalho Chehab  * cx231xx_init_dev()
12420c0d06caSMauro Carvalho Chehab  * allocates and inits the device structs, registers i2c bus and v4l device
12430c0d06caSMauro Carvalho Chehab  */
12440c0d06caSMauro Carvalho Chehab static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
12450c0d06caSMauro Carvalho Chehab 			    int minor)
12460c0d06caSMauro Carvalho Chehab {
12470c0d06caSMauro Carvalho Chehab 	int retval = -ENOMEM;
12480c0d06caSMauro Carvalho Chehab 	unsigned int maxh, maxw;
12490c0d06caSMauro Carvalho Chehab 
12500c0d06caSMauro Carvalho Chehab 	dev->udev = udev;
12510c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->lock);
12520c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->ctrl_urb_lock);
12530c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->gpio_i2c_lock);
12540c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->i2c_lock);
12550c0d06caSMauro Carvalho Chehab 
12560c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->video_mode.slock);
12570c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->vbi_mode.slock);
12580c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->sliced_cc_mode.slock);
12590c0d06caSMauro Carvalho Chehab 
12600c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->open);
12610c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_frame);
12620c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_stream);
12630c0d06caSMauro Carvalho Chehab 
12640c0d06caSMauro Carvalho Chehab 	dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
12650c0d06caSMauro Carvalho Chehab 	dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
12660c0d06caSMauro Carvalho Chehab 	dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
12670c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
12680c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
12690c0d06caSMauro Carvalho Chehab 
12700c0d06caSMauro Carvalho Chehab 	/* Query cx231xx to find what pcb config it is related to */
127152841e5eSMauro Carvalho Chehab 	retval = initialize_cx231xx(dev);
127252841e5eSMauro Carvalho Chehab 	if (retval < 0) {
1273336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Failed to read PCB config\n");
127452841e5eSMauro Carvalho Chehab 		return retval;
127552841e5eSMauro Carvalho Chehab 	}
12760c0d06caSMauro Carvalho Chehab 
12770c0d06caSMauro Carvalho Chehab 	/*To workaround error number=-71 on EP0 for VideoGrabber,
12780c0d06caSMauro Carvalho Chehab 		 need set alt here.*/
12790c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
12800c0d06caSMauro Carvalho Chehab 	    dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
12810c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
12820c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
12830c0d06caSMauro Carvalho Chehab 	}
12840c0d06caSMauro Carvalho Chehab 	/* Cx231xx pre card setup */
12850c0d06caSMauro Carvalho Chehab 	cx231xx_pre_card_setup(dev);
12860c0d06caSMauro Carvalho Chehab 
1287256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1288256d013aSAlexey Khoroshilov 	if (retval) {
1289336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "error configuring device\n");
12900c0d06caSMauro Carvalho Chehab 		return -ENOMEM;
12910c0d06caSMauro Carvalho Chehab 	}
12920c0d06caSMauro Carvalho Chehab 
12930c0d06caSMauro Carvalho Chehab 	/* set default norm */
12940c0d06caSMauro Carvalho Chehab 	dev->norm = dev->board.norm;
12950c0d06caSMauro Carvalho Chehab 
12960c0d06caSMauro Carvalho Chehab 	/* register i2c bus */
1297256d013aSAlexey Khoroshilov 	retval = cx231xx_dev_init(dev);
1298256d013aSAlexey Khoroshilov 	if (retval) {
1299336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1300b7085c08SMauro Carvalho Chehab 			"%s: cx231xx_i2c_register - errCode [%d]!\n",
1301256d013aSAlexey Khoroshilov 			__func__, retval);
1302256d013aSAlexey Khoroshilov 		goto err_dev_init;
13030c0d06caSMauro Carvalho Chehab 	}
13040c0d06caSMauro Carvalho Chehab 
13050c0d06caSMauro Carvalho Chehab 	/* Do board specific init */
13060c0d06caSMauro Carvalho Chehab 	cx231xx_card_setup(dev);
13070c0d06caSMauro Carvalho Chehab 
13080c0d06caSMauro Carvalho Chehab 	/* configure the device */
13090c0d06caSMauro Carvalho Chehab 	cx231xx_config_i2c(dev);
13100c0d06caSMauro Carvalho Chehab 
13110c0d06caSMauro Carvalho Chehab 	maxw = norm_maxw(dev);
13120c0d06caSMauro Carvalho Chehab 	maxh = norm_maxh(dev);
13130c0d06caSMauro Carvalho Chehab 
13140c0d06caSMauro Carvalho Chehab 	/* set default image size */
13150c0d06caSMauro Carvalho Chehab 	dev->width = maxw;
13160c0d06caSMauro Carvalho Chehab 	dev->height = maxh;
13170c0d06caSMauro Carvalho Chehab 	dev->interlaced = 0;
13180c0d06caSMauro Carvalho Chehab 	dev->video_input = 0;
13190c0d06caSMauro Carvalho Chehab 
1320256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1321256d013aSAlexey Khoroshilov 	if (retval) {
1322336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "%s: cx231xx_config - errCode [%d]!\n",
1323256d013aSAlexey Khoroshilov 			__func__, retval);
1324256d013aSAlexey Khoroshilov 		goto err_dev_init;
13250c0d06caSMauro Carvalho Chehab 	}
13260c0d06caSMauro Carvalho Chehab 
13270c0d06caSMauro Carvalho Chehab 	/* init video dma queues */
13280c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->video_mode.vidq.active);
13290c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
13300c0d06caSMauro Carvalho Chehab 
13310c0d06caSMauro Carvalho Chehab 	/* init vbi dma queues */
13320c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
13330c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
13340c0d06caSMauro Carvalho Chehab 
13350c0d06caSMauro Carvalho Chehab 	/* Reset other chips required if they are tied up with GPIO pins */
13360c0d06caSMauro Carvalho Chehab 	cx231xx_add_into_devlist(dev);
13370c0d06caSMauro Carvalho Chehab 
13380c0d06caSMauro Carvalho Chehab 	if (dev->board.has_417) {
1339336fea92SMauro Carvalho Chehab 		dev_info(dev->dev, "attach 417 %d\n", dev->model);
13400c0d06caSMauro Carvalho Chehab 		if (cx231xx_417_register(dev) < 0) {
1341336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
13420c0d06caSMauro Carvalho Chehab 				"%s() Failed to register 417 on VID_B\n",
13430c0d06caSMauro Carvalho Chehab 				__func__);
13440c0d06caSMauro Carvalho Chehab 		}
13450c0d06caSMauro Carvalho Chehab 	}
13460c0d06caSMauro Carvalho Chehab 
13470c0d06caSMauro Carvalho Chehab 	retval = cx231xx_register_analog_devices(dev);
13481d058bdcSMauro Carvalho Chehab 	if (retval)
1349256d013aSAlexey Khoroshilov 		goto err_analog;
13500c0d06caSMauro Carvalho Chehab 
13510c0d06caSMauro Carvalho Chehab 	cx231xx_ir_init(dev);
13520c0d06caSMauro Carvalho Chehab 
13530c0d06caSMauro Carvalho Chehab 	cx231xx_init_extension(dev);
13540c0d06caSMauro Carvalho Chehab 
13550c0d06caSMauro Carvalho Chehab 	return 0;
1356256d013aSAlexey Khoroshilov err_analog:
13571d058bdcSMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
13581d058bdcSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
1359256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1360256d013aSAlexey Khoroshilov err_dev_init:
1361256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1362256d013aSAlexey Khoroshilov 	return retval;
13630c0d06caSMauro Carvalho Chehab }
13640c0d06caSMauro Carvalho Chehab 
13650c0d06caSMauro Carvalho Chehab #if defined(CONFIG_MODULES) && defined(MODULE)
13660c0d06caSMauro Carvalho Chehab static void request_module_async(struct work_struct *work)
13670c0d06caSMauro Carvalho Chehab {
13680c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = container_of(work,
13690c0d06caSMauro Carvalho Chehab 					   struct cx231xx, request_module_wk);
13700c0d06caSMauro Carvalho Chehab 
13710c0d06caSMauro Carvalho Chehab 	if (dev->has_alsa_audio)
13720c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-alsa");
13730c0d06caSMauro Carvalho Chehab 
13740c0d06caSMauro Carvalho Chehab 	if (dev->board.has_dvb)
13750c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-dvb");
13760c0d06caSMauro Carvalho Chehab 
13770c0d06caSMauro Carvalho Chehab }
13780c0d06caSMauro Carvalho Chehab 
13790c0d06caSMauro Carvalho Chehab static void request_modules(struct cx231xx *dev)
13800c0d06caSMauro Carvalho Chehab {
13810c0d06caSMauro Carvalho Chehab 	INIT_WORK(&dev->request_module_wk, request_module_async);
13820c0d06caSMauro Carvalho Chehab 	schedule_work(&dev->request_module_wk);
13830c0d06caSMauro Carvalho Chehab }
13840c0d06caSMauro Carvalho Chehab 
13850c0d06caSMauro Carvalho Chehab static void flush_request_modules(struct cx231xx *dev)
13860c0d06caSMauro Carvalho Chehab {
13870b8e74c6SLinus Torvalds 	flush_work(&dev->request_module_wk);
13880c0d06caSMauro Carvalho Chehab }
13890c0d06caSMauro Carvalho Chehab #else
13900c0d06caSMauro Carvalho Chehab #define request_modules(dev)
13910c0d06caSMauro Carvalho Chehab #define flush_request_modules(dev)
13920c0d06caSMauro Carvalho Chehab #endif /* CONFIG_MODULES */
13930c0d06caSMauro Carvalho Chehab 
13944d2a7d35SMauro Carvalho Chehab static int cx231xx_init_v4l2(struct cx231xx *dev,
13954d2a7d35SMauro Carvalho Chehab 			     struct usb_device *udev,
13964d2a7d35SMauro Carvalho Chehab 			     struct usb_interface *interface,
13974d2a7d35SMauro Carvalho Chehab 			     int isoc_pipe)
13984d2a7d35SMauro Carvalho Chehab {
13994d2a7d35SMauro Carvalho Chehab 	struct usb_interface *uif;
14004d2a7d35SMauro Carvalho Chehab 	int i, idx;
14014d2a7d35SMauro Carvalho Chehab 
14024d2a7d35SMauro Carvalho Chehab 	/* Video Init */
14034d2a7d35SMauro Carvalho Chehab 
14044d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for video */
14054d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
14064d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1407336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1408b7085c08SMauro Carvalho Chehab 			"Video PCB interface #%d doesn't exist\n", idx);
14094d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
14104d2a7d35SMauro Carvalho Chehab 	}
14114d2a7d35SMauro Carvalho Chehab 
14124d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
14134d2a7d35SMauro Carvalho Chehab 
14144d2a7d35SMauro Carvalho Chehab 	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
14154d2a7d35SMauro Carvalho Chehab 	dev->video_mode.num_alt = uif->num_altsetting;
14164d2a7d35SMauro Carvalho Chehab 
1417336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1418b7085c08SMauro Carvalho Chehab 		 "video EndPoint Addr 0x%x, Alternate settings: %i\n",
14194d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.end_point_addr,
14204d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.num_alt);
14214d2a7d35SMauro Carvalho Chehab 
14224d2a7d35SMauro Carvalho Chehab 	dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
1423ed0e3729SMauro Carvalho Chehab 	if (dev->video_mode.alt_max_pkt_size == NULL)
14244d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
14254d2a7d35SMauro Carvalho Chehab 
14264d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->video_mode.num_alt; i++) {
14274d2a7d35SMauro Carvalho Chehab 		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
14284d2a7d35SMauro Carvalho Chehab 		dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1429336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1430b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
14314d2a7d35SMauro Carvalho Chehab 			dev->video_mode.alt_max_pkt_size[i]);
14324d2a7d35SMauro Carvalho Chehab 	}
14334d2a7d35SMauro Carvalho Chehab 
14344d2a7d35SMauro Carvalho Chehab 	/* VBI Init */
14354d2a7d35SMauro Carvalho Chehab 
14364d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
14374d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1438336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1439b7085c08SMauro Carvalho Chehab 			"VBI PCB interface #%d doesn't exist\n", idx);
14404d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
14414d2a7d35SMauro Carvalho Chehab 	}
14424d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
14434d2a7d35SMauro Carvalho Chehab 
14444d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.end_point_addr =
14454d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
14464d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
14474d2a7d35SMauro Carvalho Chehab 
14484d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.num_alt = uif->num_altsetting;
1449336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1450b7085c08SMauro Carvalho Chehab 		 "VBI EndPoint Addr 0x%x, Alternate settings: %i\n",
14514d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.end_point_addr,
14524d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.num_alt);
14534d2a7d35SMauro Carvalho Chehab 
14544d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for vbi */
14554d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
1456ed0e3729SMauro Carvalho Chehab 	if (dev->vbi_mode.alt_max_pkt_size == NULL)
14574d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
14584d2a7d35SMauro Carvalho Chehab 
14594d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
14604d2a7d35SMauro Carvalho Chehab 		u16 tmp =
14614d2a7d35SMauro Carvalho Chehab 		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
14624d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
14634d2a7d35SMauro Carvalho Chehab 		dev->vbi_mode.alt_max_pkt_size[i] =
14644d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1465336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1466b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
14674d2a7d35SMauro Carvalho Chehab 			dev->vbi_mode.alt_max_pkt_size[i]);
14684d2a7d35SMauro Carvalho Chehab 	}
14694d2a7d35SMauro Carvalho Chehab 
14704d2a7d35SMauro Carvalho Chehab 	/* Sliced CC VBI init */
14714d2a7d35SMauro Carvalho Chehab 
14724d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for sliced CC */
14734d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
14744d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1475336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1476b7085c08SMauro Carvalho Chehab 			"Sliced CC PCB interface #%d doesn't exist\n", idx);
14774d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
14784d2a7d35SMauro Carvalho Chehab 	}
14794d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
14804d2a7d35SMauro Carvalho Chehab 
14814d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.end_point_addr =
14824d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
14834d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
14844d2a7d35SMauro Carvalho Chehab 
14854d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
1486336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1487b7085c08SMauro Carvalho Chehab 		 "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
14884d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.end_point_addr,
14894d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.num_alt);
14904d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
1491ed0e3729SMauro Carvalho Chehab 	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
14924d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
14934d2a7d35SMauro Carvalho Chehab 
14944d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
14954d2a7d35SMauro Carvalho Chehab 		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
14964d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
14974d2a7d35SMauro Carvalho Chehab 		dev->sliced_cc_mode.alt_max_pkt_size[i] =
14984d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1499336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1500b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
15014d2a7d35SMauro Carvalho Chehab 			dev->sliced_cc_mode.alt_max_pkt_size[i]);
15024d2a7d35SMauro Carvalho Chehab 	}
15034d2a7d35SMauro Carvalho Chehab 
15044d2a7d35SMauro Carvalho Chehab 	return 0;
15054d2a7d35SMauro Carvalho Chehab }
15064d2a7d35SMauro Carvalho Chehab 
15070c0d06caSMauro Carvalho Chehab /*
15080c0d06caSMauro Carvalho Chehab  * cx231xx_usb_probe()
15090c0d06caSMauro Carvalho Chehab  * checks for supported devices
15100c0d06caSMauro Carvalho Chehab  */
15110c0d06caSMauro Carvalho Chehab static int cx231xx_usb_probe(struct usb_interface *interface,
15120c0d06caSMauro Carvalho Chehab 			     const struct usb_device_id *id)
15130c0d06caSMauro Carvalho Chehab {
15140c0d06caSMauro Carvalho Chehab 	struct usb_device *udev;
1515336fea92SMauro Carvalho Chehab 	struct device *d = &interface->dev;
15160c0d06caSMauro Carvalho Chehab 	struct usb_interface *uif;
15170c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = NULL;
15180c0d06caSMauro Carvalho Chehab 	int retval = -ENODEV;
15190c0d06caSMauro Carvalho Chehab 	int nr = 0, ifnum;
15200c0d06caSMauro Carvalho Chehab 	int i, isoc_pipe = 0;
15210c0d06caSMauro Carvalho Chehab 	char *speed;
1522dcb78ac7SMauro Carvalho Chehab 	u8 idx;
15230c0d06caSMauro Carvalho Chehab 	struct usb_interface_assoc_descriptor *assoc_desc;
15240c0d06caSMauro Carvalho Chehab 
15250c0d06caSMauro Carvalho Chehab 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
15260c0d06caSMauro Carvalho Chehab 
15270c0d06caSMauro Carvalho Chehab 	/*
15280c0d06caSMauro Carvalho Chehab 	 * Interface number 0 - IR interface (handled by mceusb driver)
15290c0d06caSMauro Carvalho Chehab 	 * Interface number 1 - AV interface (handled by this driver)
15300c0d06caSMauro Carvalho Chehab 	 */
15310c0d06caSMauro Carvalho Chehab 	if (ifnum != 1)
15320c0d06caSMauro Carvalho Chehab 		return -ENODEV;
15330c0d06caSMauro Carvalho Chehab 
15340c0d06caSMauro Carvalho Chehab 	/* Check to see next free device and mark as used */
15350c0d06caSMauro Carvalho Chehab 	do {
15360c0d06caSMauro Carvalho Chehab 		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
15370c0d06caSMauro Carvalho Chehab 		if (nr >= CX231XX_MAXBOARDS) {
15380c0d06caSMauro Carvalho Chehab 			/* No free device slots */
1539336fea92SMauro Carvalho Chehab 			dev_err(d,
1540b7085c08SMauro Carvalho Chehab 				"Supports only %i devices.\n",
1541b7085c08SMauro Carvalho Chehab 				CX231XX_MAXBOARDS);
15420c0d06caSMauro Carvalho Chehab 			return -ENOMEM;
15430c0d06caSMauro Carvalho Chehab 		}
15440c0d06caSMauro Carvalho Chehab 	} while (test_and_set_bit(nr, &cx231xx_devused));
15450c0d06caSMauro Carvalho Chehab 
15465eeb3014SAlexey Khoroshilov 	udev = usb_get_dev(interface_to_usbdev(interface));
15475eeb3014SAlexey Khoroshilov 
15480c0d06caSMauro Carvalho Chehab 	/* allocate memory for our device state and initialize it */
1549184a8278SMauro Carvalho Chehab 	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
15500c0d06caSMauro Carvalho Chehab 	if (dev == NULL) {
15515eeb3014SAlexey Khoroshilov 		retval = -ENOMEM;
15525eeb3014SAlexey Khoroshilov 		goto err_if;
15530c0d06caSMauro Carvalho Chehab 	}
15540c0d06caSMauro Carvalho Chehab 
15550c0d06caSMauro Carvalho Chehab 	snprintf(dev->name, 29, "cx231xx #%d", nr);
15560c0d06caSMauro Carvalho Chehab 	dev->devno = nr;
15570c0d06caSMauro Carvalho Chehab 	dev->model = id->driver_info;
15580c0d06caSMauro Carvalho Chehab 	dev->video_mode.alt = -1;
1559336fea92SMauro Carvalho Chehab 	dev->dev = d;
15600c0d06caSMauro Carvalho Chehab 
15611d058bdcSMauro Carvalho Chehab 	cx231xx_set_model(dev);
15621d058bdcSMauro Carvalho Chehab 
15630c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
15640c0d06caSMauro Carvalho Chehab 	/* reset gpio dir and value */
15650c0d06caSMauro Carvalho Chehab 	dev->gpio_dir = 0;
15660c0d06caSMauro Carvalho Chehab 	dev->gpio_val = 0;
15670c0d06caSMauro Carvalho Chehab 	dev->xc_fw_load_done = 0;
15680c0d06caSMauro Carvalho Chehab 	dev->has_alsa_audio = 1;
15690c0d06caSMauro Carvalho Chehab 	dev->power_mode = -1;
15700c0d06caSMauro Carvalho Chehab 	atomic_set(&dev->devlist_count, 0);
15710c0d06caSMauro Carvalho Chehab 
15720c0d06caSMauro Carvalho Chehab 	/* 0 - vbi ; 1 -sliced cc mode */
15730c0d06caSMauro Carvalho Chehab 	dev->vbi_or_sliced_cc_mode = 0;
15740c0d06caSMauro Carvalho Chehab 
15750c0d06caSMauro Carvalho Chehab 	/* get maximum no.of IAD interfaces */
1576139d2882SMauro Carvalho Chehab 	dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
15770c0d06caSMauro Carvalho Chehab 
15780c0d06caSMauro Carvalho Chehab 	/* init CIR module TBD */
15790c0d06caSMauro Carvalho Chehab 
15800c0d06caSMauro Carvalho Chehab 	/*mode_tv: digital=1 or analog=0*/
15810c0d06caSMauro Carvalho Chehab 	dev->mode_tv = 0;
15820c0d06caSMauro Carvalho Chehab 
15830c0d06caSMauro Carvalho Chehab 	dev->USE_ISO = transfer_mode;
15840c0d06caSMauro Carvalho Chehab 
15850c0d06caSMauro Carvalho Chehab 	switch (udev->speed) {
15860c0d06caSMauro Carvalho Chehab 	case USB_SPEED_LOW:
15870c0d06caSMauro Carvalho Chehab 		speed = "1.5";
15880c0d06caSMauro Carvalho Chehab 		break;
15890c0d06caSMauro Carvalho Chehab 	case USB_SPEED_UNKNOWN:
15900c0d06caSMauro Carvalho Chehab 	case USB_SPEED_FULL:
15910c0d06caSMauro Carvalho Chehab 		speed = "12";
15920c0d06caSMauro Carvalho Chehab 		break;
15930c0d06caSMauro Carvalho Chehab 	case USB_SPEED_HIGH:
15940c0d06caSMauro Carvalho Chehab 		speed = "480";
15950c0d06caSMauro Carvalho Chehab 		break;
15960c0d06caSMauro Carvalho Chehab 	default:
15970c0d06caSMauro Carvalho Chehab 		speed = "unknown";
15980c0d06caSMauro Carvalho Chehab 	}
15990c0d06caSMauro Carvalho Chehab 
1600336fea92SMauro Carvalho Chehab 	dev_info(d,
1601b7085c08SMauro Carvalho Chehab 		 "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
16020c0d06caSMauro Carvalho Chehab 		 udev->manufacturer ? udev->manufacturer : "",
16030c0d06caSMauro Carvalho Chehab 		 udev->product ? udev->product : "",
16040c0d06caSMauro Carvalho Chehab 		 speed,
16050c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idVendor),
16060c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idProduct),
16070c0d06caSMauro Carvalho Chehab 		 dev->max_iad_interface_count);
16080c0d06caSMauro Carvalho Chehab 
16090c0d06caSMauro Carvalho Chehab 	/* increment interface count */
16100c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
16110c0d06caSMauro Carvalho Chehab 
16120c0d06caSMauro Carvalho Chehab 	/* get device number */
16130c0d06caSMauro Carvalho Chehab 	nr = dev->devno;
16140c0d06caSMauro Carvalho Chehab 
16150c0d06caSMauro Carvalho Chehab 	assoc_desc = udev->actconfig->intf_assoc[0];
16160c0d06caSMauro Carvalho Chehab 	if (assoc_desc->bFirstInterface != ifnum) {
1617336fea92SMauro Carvalho Chehab 		dev_err(d, "Not found matching IAD interface\n");
1618256d013aSAlexey Khoroshilov 		retval = -ENODEV;
1619256d013aSAlexey Khoroshilov 		goto err_if;
16200c0d06caSMauro Carvalho Chehab 	}
16210c0d06caSMauro Carvalho Chehab 
1622336fea92SMauro Carvalho Chehab 	dev_dbg(d, "registering interface %d\n", ifnum);
16230c0d06caSMauro Carvalho Chehab 
16240c0d06caSMauro Carvalho Chehab 	/* save our data pointer in this interface device */
16250c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, dev);
16260c0d06caSMauro Carvalho Chehab 
16271d058bdcSMauro Carvalho Chehab 	/* Register the media controller */
16281d058bdcSMauro Carvalho Chehab 	cx231xx_media_device_register(dev, udev);
16291d058bdcSMauro Carvalho Chehab 
16300c0d06caSMauro Carvalho Chehab 	/* Create v4l2 device */
163163ba8c75SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
16321d058bdcSMauro Carvalho Chehab 	dev->v4l2_dev.mdev = dev->media_dev;
163363ba8c75SMauro Carvalho Chehab #endif
16340c0d06caSMauro Carvalho Chehab 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
16350c0d06caSMauro Carvalho Chehab 	if (retval) {
1636336fea92SMauro Carvalho Chehab 		dev_err(d, "v4l2_device_register failed\n");
1637256d013aSAlexey Khoroshilov 		goto err_v4l2;
16380c0d06caSMauro Carvalho Chehab 	}
16394d2a7d35SMauro Carvalho Chehab 
16400c0d06caSMauro Carvalho Chehab 	/* allocate device struct */
16410c0d06caSMauro Carvalho Chehab 	retval = cx231xx_init_dev(dev, udev, nr);
1642256d013aSAlexey Khoroshilov 	if (retval)
1643256d013aSAlexey Khoroshilov 		goto err_init;
16440c0d06caSMauro Carvalho Chehab 
16454d2a7d35SMauro Carvalho Chehab 	retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
16464d2a7d35SMauro Carvalho Chehab 	if (retval)
1647dcb78ac7SMauro Carvalho Chehab 		goto err_init;
16480c0d06caSMauro Carvalho Chehab 
16490c0d06caSMauro Carvalho Chehab 	if (dev->current_pcb_config.ts1_source != 0xff) {
16500c0d06caSMauro Carvalho Chehab 		/* compute alternate max packet sizes for TS1 */
1651dcb78ac7SMauro Carvalho Chehab 		idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
1652dcb78ac7SMauro Carvalho Chehab 		if (idx >= dev->max_iad_interface_count) {
1653336fea92SMauro Carvalho Chehab 			dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
1654336fea92SMauro Carvalho Chehab 				idx);
1655dcb78ac7SMauro Carvalho Chehab 			retval = -ENODEV;
1656184a8278SMauro Carvalho Chehab 			goto err_video_alt;
1657dcb78ac7SMauro Carvalho Chehab 		}
1658dcb78ac7SMauro Carvalho Chehab 		uif = udev->actconfig->interface[idx];
16590c0d06caSMauro Carvalho Chehab 
16600c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.end_point_addr =
166169a11a32SHans Verkuil 		    uif->altsetting[0].endpoint[isoc_pipe].
166269a11a32SHans Verkuil 				desc.bEndpointAddress;
16630c0d06caSMauro Carvalho Chehab 
16640c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.num_alt = uif->num_altsetting;
1665336fea92SMauro Carvalho Chehab 		dev_info(d,
1666b7085c08SMauro Carvalho Chehab 			 "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
16670c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.end_point_addr,
16680c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.num_alt);
16690c0d06caSMauro Carvalho Chehab 
1670184a8278SMauro Carvalho Chehab 		dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
16710c0d06caSMauro Carvalho Chehab 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
1672256d013aSAlexey Khoroshilov 			retval = -ENOMEM;
1673184a8278SMauro Carvalho Chehab 			goto err_video_alt;
16740c0d06caSMauro Carvalho Chehab 		}
16750c0d06caSMauro Carvalho Chehab 
16760c0d06caSMauro Carvalho Chehab 		for (i = 0; i < dev->ts1_mode.num_alt; i++) {
16770c0d06caSMauro Carvalho Chehab 			u16 tmp = le16_to_cpu(uif->altsetting[i].
16780c0d06caSMauro Carvalho Chehab 						endpoint[isoc_pipe].desc.
16790c0d06caSMauro Carvalho Chehab 						wMaxPacketSize);
16800c0d06caSMauro Carvalho Chehab 			dev->ts1_mode.alt_max_pkt_size[i] =
16810c0d06caSMauro Carvalho Chehab 			    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1682336fea92SMauro Carvalho Chehab 			dev_dbg(d, "Alternate setting %i, max size= %i\n",
1683336fea92SMauro Carvalho Chehab 				i, dev->ts1_mode.alt_max_pkt_size[i]);
16840c0d06caSMauro Carvalho Chehab 		}
16850c0d06caSMauro Carvalho Chehab 	}
16860c0d06caSMauro Carvalho Chehab 
16870c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
16880c0d06caSMauro Carvalho Chehab 		cx231xx_enable_OSC(dev);
16890c0d06caSMauro Carvalho Chehab 		cx231xx_reset_out(dev);
16900c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
16910c0d06caSMauro Carvalho Chehab 	}
16920c0d06caSMauro Carvalho Chehab 
16930c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
16940c0d06caSMauro Carvalho Chehab 		cx231xx_sleep_s5h1432(dev);
16950c0d06caSMauro Carvalho Chehab 
16960c0d06caSMauro Carvalho Chehab 	/* load other modules required */
16970c0d06caSMauro Carvalho Chehab 	request_modules(dev);
16980c0d06caSMauro Carvalho Chehab 
1699d35a9855SMauro Carvalho Chehab 	cx231xx_create_media_graph(dev);
1700d35a9855SMauro Carvalho Chehab 
17010c0d06caSMauro Carvalho Chehab 	return 0;
1702256d013aSAlexey Khoroshilov err_video_alt:
1703256d013aSAlexey Khoroshilov 	/* cx231xx_uninit_dev: */
1704256d013aSAlexey Khoroshilov 	cx231xx_close_extension(dev);
1705256d013aSAlexey Khoroshilov 	cx231xx_ir_exit(dev);
1706256d013aSAlexey Khoroshilov 	cx231xx_release_analog_resources(dev);
1707256d013aSAlexey Khoroshilov 	cx231xx_417_unregister(dev);
1708256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1709256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1710256d013aSAlexey Khoroshilov err_init:
1711256d013aSAlexey Khoroshilov 	v4l2_device_unregister(&dev->v4l2_dev);
1712256d013aSAlexey Khoroshilov err_v4l2:
1713256d013aSAlexey Khoroshilov 	usb_set_intfdata(interface, NULL);
1714256d013aSAlexey Khoroshilov err_if:
1715256d013aSAlexey Khoroshilov 	usb_put_dev(udev);
1716b5603a94SMauro Carvalho Chehab 	clear_bit(nr, &cx231xx_devused);
1717256d013aSAlexey Khoroshilov 	return retval;
17180c0d06caSMauro Carvalho Chehab }
17190c0d06caSMauro Carvalho Chehab 
17200c0d06caSMauro Carvalho Chehab /*
17210c0d06caSMauro Carvalho Chehab  * cx231xx_usb_disconnect()
17220c0d06caSMauro Carvalho Chehab  * called when the device gets diconencted
17230c0d06caSMauro Carvalho Chehab  * video device will be unregistered on v4l2_close in case it is still open
17240c0d06caSMauro Carvalho Chehab  */
17250c0d06caSMauro Carvalho Chehab static void cx231xx_usb_disconnect(struct usb_interface *interface)
17260c0d06caSMauro Carvalho Chehab {
17270c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev;
17280c0d06caSMauro Carvalho Chehab 
17290c0d06caSMauro Carvalho Chehab 	dev = usb_get_intfdata(interface);
17300c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, NULL);
17310c0d06caSMauro Carvalho Chehab 
17320c0d06caSMauro Carvalho Chehab 	if (!dev)
17330c0d06caSMauro Carvalho Chehab 		return;
17340c0d06caSMauro Carvalho Chehab 
17350c0d06caSMauro Carvalho Chehab 	if (!dev->udev)
17360c0d06caSMauro Carvalho Chehab 		return;
17370c0d06caSMauro Carvalho Chehab 
17380c0d06caSMauro Carvalho Chehab 	dev->state |= DEV_DISCONNECTED;
17390c0d06caSMauro Carvalho Chehab 
17400c0d06caSMauro Carvalho Chehab 	flush_request_modules(dev);
17410c0d06caSMauro Carvalho Chehab 
17420c0d06caSMauro Carvalho Chehab 	/* wait until all current v4l2 io is finished then deallocate
17430c0d06caSMauro Carvalho Chehab 	   resources */
17440c0d06caSMauro Carvalho Chehab 	mutex_lock(&dev->lock);
17450c0d06caSMauro Carvalho Chehab 
17460c0d06caSMauro Carvalho Chehab 	wake_up_interruptible_all(&dev->open);
17470c0d06caSMauro Carvalho Chehab 
17480c0d06caSMauro Carvalho Chehab 	if (dev->users) {
1749336fea92SMauro Carvalho Chehab 		dev_warn(dev->dev,
1750b7085c08SMauro Carvalho Chehab 			 "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
175160acf187SHans Verkuil 			 video_device_node_name(&dev->vdev));
17520c0d06caSMauro Carvalho Chehab 
17530c0d06caSMauro Carvalho Chehab 		/* Even having users, it is safe to remove the RC i2c driver */
17540c0d06caSMauro Carvalho Chehab 		cx231xx_ir_exit(dev);
17550c0d06caSMauro Carvalho Chehab 
17560c0d06caSMauro Carvalho Chehab 		if (dev->USE_ISO)
17570c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_isoc(dev);
17580c0d06caSMauro Carvalho Chehab 		else
17590c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_bulk(dev);
17600c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_frame);
17610c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_stream);
17620c0d06caSMauro Carvalho Chehab 	} else {
17630c0d06caSMauro Carvalho Chehab 	}
17640c0d06caSMauro Carvalho Chehab 
17650c0d06caSMauro Carvalho Chehab 	cx231xx_close_extension(dev);
17660c0d06caSMauro Carvalho Chehab 
17670c0d06caSMauro Carvalho Chehab 	mutex_unlock(&dev->lock);
17680c0d06caSMauro Carvalho Chehab 
17690c0d06caSMauro Carvalho Chehab 	if (!dev->users)
17700c0d06caSMauro Carvalho Chehab 		cx231xx_release_resources(dev);
17710c0d06caSMauro Carvalho Chehab }
17720c0d06caSMauro Carvalho Chehab 
17730c0d06caSMauro Carvalho Chehab static struct usb_driver cx231xx_usb_driver = {
17740c0d06caSMauro Carvalho Chehab 	.name = "cx231xx",
17750c0d06caSMauro Carvalho Chehab 	.probe = cx231xx_usb_probe,
17760c0d06caSMauro Carvalho Chehab 	.disconnect = cx231xx_usb_disconnect,
17770c0d06caSMauro Carvalho Chehab 	.id_table = cx231xx_id_table,
17780c0d06caSMauro Carvalho Chehab };
17790c0d06caSMauro Carvalho Chehab 
17800c0d06caSMauro Carvalho Chehab module_usb_driver(cx231xx_usb_driver);
1781