174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20c0d06caSMauro Carvalho Chehab /*
30c0d06caSMauro Carvalho Chehab    cx231xx-cards.c - driver for Conexant Cx23100/101/102
40c0d06caSMauro Carvalho Chehab 				USB video capture devices
50c0d06caSMauro Carvalho Chehab 
60c0d06caSMauro Carvalho Chehab    Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
70c0d06caSMauro Carvalho Chehab 				Based on em28xx driver
80c0d06caSMauro Carvalho Chehab 
90c0d06caSMauro Carvalho Chehab  */
100c0d06caSMauro Carvalho Chehab 
11589dadf2SMauro Carvalho Chehab #include "cx231xx.h"
120c0d06caSMauro Carvalho Chehab #include <linux/init.h>
130c0d06caSMauro Carvalho Chehab #include <linux/module.h>
140c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
150c0d06caSMauro Carvalho Chehab #include <linux/delay.h>
160c0d06caSMauro Carvalho Chehab #include <linux/i2c.h>
170c0d06caSMauro Carvalho Chehab #include <media/tuner.h>
180c0d06caSMauro Carvalho Chehab #include <media/tveeprom.h>
190c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
200c0d06caSMauro Carvalho Chehab 
21d647f0b7SMauro Carvalho Chehab #include <media/drv-intf/cx25840.h>
22fada1935SMauro Carvalho Chehab #include <media/dvb-usb-ids.h>
230c0d06caSMauro Carvalho Chehab #include "xc5000.h"
240c0d06caSMauro Carvalho Chehab #include "tda18271.h"
250c0d06caSMauro Carvalho Chehab 
260c0d06caSMauro Carvalho Chehab 
270c0d06caSMauro Carvalho Chehab static int tuner = -1;
280c0d06caSMauro Carvalho Chehab module_param(tuner, int, 0444);
290c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(tuner, "tuner type");
300c0d06caSMauro Carvalho Chehab 
310c0d06caSMauro Carvalho Chehab static int transfer_mode = 1;
320c0d06caSMauro Carvalho Chehab module_param(transfer_mode, int, 0444);
330c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)");
340c0d06caSMauro Carvalho Chehab 
350c0d06caSMauro Carvalho Chehab static unsigned int disable_ir;
360c0d06caSMauro Carvalho Chehab module_param(disable_ir, int, 0444);
370c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
380c0d06caSMauro Carvalho Chehab 
390c0d06caSMauro Carvalho Chehab /* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */
400c0d06caSMauro Carvalho Chehab static unsigned long cx231xx_devused;
410c0d06caSMauro Carvalho Chehab 
420c0d06caSMauro Carvalho Chehab /*
430c0d06caSMauro Carvalho Chehab  *  Reset sequences for analog/digital modes
440c0d06caSMauro Carvalho Chehab  */
450c0d06caSMauro Carvalho Chehab 
460c0d06caSMauro Carvalho Chehab static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = {
470c0d06caSMauro Carvalho Chehab 	{0x03, 0x01, 10},
480c0d06caSMauro Carvalho Chehab 	{0x03, 0x00, 30},
490c0d06caSMauro Carvalho Chehab 	{0x03, 0x01, 10},
500c0d06caSMauro Carvalho Chehab 	{-1, -1, -1},
510c0d06caSMauro Carvalho Chehab };
520c0d06caSMauro Carvalho Chehab 
530c0d06caSMauro Carvalho Chehab /*
540c0d06caSMauro Carvalho Chehab  *  Board definitions
550c0d06caSMauro Carvalho Chehab  */
560c0d06caSMauro Carvalho Chehab struct cx231xx_board cx231xx_boards[] = {
570c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_UNKNOWN] = {
580c0d06caSMauro Carvalho Chehab 		.name = "Unknown CX231xx video grabber",
590c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
600c0d06caSMauro Carvalho Chehab 		.input = {{
610c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
620c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
630c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
640c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
650c0d06caSMauro Carvalho Chehab 			}, {
660c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
670c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
680c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
690c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
700c0d06caSMauro Carvalho Chehab 			}, {
710c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
720c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
730c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
740c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
750c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
760c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
770c0d06caSMauro Carvalho Chehab 			}
780c0d06caSMauro Carvalho Chehab 		},
790c0d06caSMauro Carvalho Chehab 	},
800c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_CARRAERA] = {
810c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - CARRAERA",
820c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
830c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
840c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
850c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
860c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
870c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
880c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
890c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
900c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
910c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
920c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
930c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
94b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
95d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
960c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
970c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
980c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
990c0d06caSMauro Carvalho Chehab 
1000c0d06caSMauro Carvalho Chehab 		.input = {{
1010c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1020c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1030c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1040c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1050c0d06caSMauro Carvalho Chehab 			}, {
1060c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1070c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
1080c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1090c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1100c0d06caSMauro Carvalho Chehab 			}, {
1110c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
1120c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
1130c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
1140c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
1150c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1160c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1170c0d06caSMauro Carvalho Chehab 			}
1180c0d06caSMauro Carvalho Chehab 		},
1190c0d06caSMauro Carvalho Chehab 	},
1200c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_SHELBY] = {
1210c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - SHELBY",
1220c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
1230c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
1240c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
1250c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
1260c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
1270c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
1280c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
1290c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
1300c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
1310c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
1320c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
1330c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
134b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
135d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
1360c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
1370c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x32,
1380c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
1390c0d06caSMauro Carvalho Chehab 
1400c0d06caSMauro Carvalho Chehab 		.input = {{
1410c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1420c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1430c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1440c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1450c0d06caSMauro Carvalho Chehab 			}, {
1460c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1470c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
1480c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1490c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1500c0d06caSMauro Carvalho Chehab 			}, {
1510c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
1520c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
1530c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
1540c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
1550c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1560c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1570c0d06caSMauro Carvalho Chehab 			}
1580c0d06caSMauro Carvalho Chehab 		},
1590c0d06caSMauro Carvalho Chehab 	},
1600c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDE_253S] = {
1610c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDE253S",
1620c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
1630c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
1640c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
1650c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
1660c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
1670c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
1680c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
1690c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
1700c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
1710c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
1720c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
1730c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
174b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
175d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
1760c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
1770c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
1780c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
1790c0d06caSMauro Carvalho Chehab 
1800c0d06caSMauro Carvalho Chehab 		.input = {{
1810c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
1820c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
1830c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
1840c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1850c0d06caSMauro Carvalho Chehab 			}, {
1860c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
1870c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
1880c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1890c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1900c0d06caSMauro Carvalho Chehab 			}, {
1910c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
1920c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
1930c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
1940c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
1950c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
1960c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
1970c0d06caSMauro Carvalho Chehab 			}
1980c0d06caSMauro Carvalho Chehab 		},
1990c0d06caSMauro Carvalho Chehab 	},
2000c0d06caSMauro Carvalho Chehab 
2010c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDU_253S] = {
2020c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDU253S",
2030c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
2040c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
2050c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
2060c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
2070c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
2080c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
2090c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2100c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2110c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
2120c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2130c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
2140c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
215b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
216d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
2170c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
2180c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
2190c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
2200c0d06caSMauro Carvalho Chehab 
2210c0d06caSMauro Carvalho Chehab 		.input = {{
2220c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
2230c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_3_1,
2240c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
2250c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2260c0d06caSMauro Carvalho Chehab 			}, {
2270c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
2280c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2290c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2300c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2310c0d06caSMauro Carvalho Chehab 			}, {
2320c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
2330c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
2340c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
2350c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
2360c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2370c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2380c0d06caSMauro Carvalho Chehab 			}
2390c0d06caSMauro Carvalho Chehab 		},
2400c0d06caSMauro Carvalho Chehab 	},
2410c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_VIDEO_GRABBER] = {
2420c0d06caSMauro Carvalho Chehab 		.name = "Conexant VIDEO GRABBER",
2430c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
2440c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2450c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2460c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2470c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
2480c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
2490c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
2500c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
2510c0d06caSMauro Carvalho Chehab 		.external_av = 1,
252b31077a8SHans Verkuil 		/* Actually, it has a 417, but it isn't working correctly.
253b31077a8SHans Verkuil 		 * So set to 0 for now until someone can manage to get this
254b31077a8SHans Verkuil 		 * to work reliably. */
255b31077a8SHans Verkuil 		.has_417 = 0,
2560c0d06caSMauro Carvalho Chehab 
2570c0d06caSMauro Carvalho Chehab 		.input = {{
2580c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
2590c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2600c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2610c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2620c0d06caSMauro Carvalho Chehab 			}, {
2630c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
2640c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
2650c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
2660c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
2670c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
2680c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2690c0d06caSMauro Carvalho Chehab 			}
2700c0d06caSMauro Carvalho Chehab 		},
2710c0d06caSMauro Carvalho Chehab 	},
2720c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDE_250] = {
2730c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - rde 250",
2740c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
2750c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
2760c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
2770c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
2780c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
2790c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
2800c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
2810c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
2820c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
2830c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
2840c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
2850c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
286b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
287d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
2880c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
2890c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x02,
2900c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
2910c0d06caSMauro Carvalho Chehab 
2920c0d06caSMauro Carvalho Chehab 		.input = {{
2930c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
2940c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
2950c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
2960c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
2970c0d06caSMauro Carvalho Chehab 			}
2980c0d06caSMauro Carvalho Chehab 		},
2990c0d06caSMauro Carvalho Chehab 	},
3000c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_CNXT_RDU_250] = {
3010c0d06caSMauro Carvalho Chehab 		.name = "Conexant Hybrid TV - RDU 250",
3020c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_XC5000,
3030c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x61,
3040c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
3050c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
3060c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
3070c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
3080c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3090c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3100c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3110c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3120c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3130c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
314b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
315d032ca12SMatthias Schwarzott 		.demod_i2c_master = I2C_2,
3160c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
3170c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x32,
3180c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3190c0d06caSMauro Carvalho Chehab 
3200c0d06caSMauro Carvalho Chehab 		.input = {{
3210c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_TELEVISION,
3220c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
3230c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_VIDEO,
3240c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
3250c0d06caSMauro Carvalho Chehab 			}
3260c0d06caSMauro Carvalho Chehab 		},
3270c0d06caSMauro Carvalho Chehab 	},
3280c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_EXETER] = {
3290c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge EXETER",
3300c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
3310c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
3320c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
3330c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
3340c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
3350c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
3360c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3370c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3380c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3390c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3400c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3410c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
342b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_1,
343599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_1,
3440c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
3450c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x0e,
3460c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3470c0d06caSMauro Carvalho Chehab 
3480c0d06caSMauro Carvalho Chehab 		.input = {{
3490c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
3500c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
3510c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
3520c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3530c0d06caSMauro Carvalho Chehab 		}, {
3540c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
3550c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
3560c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3570c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3580c0d06caSMauro Carvalho Chehab 		}, {
3590c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
3600c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
3610c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
3620c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
3630c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3640c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3650c0d06caSMauro Carvalho Chehab 		} },
3660c0d06caSMauro Carvalho Chehab 	},
3670c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = {
3680c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge USB Live 2",
3690c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
3700c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3710c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3720c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
3730c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
3740c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
3750c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
3760c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
3770c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
3780c0d06caSMauro Carvalho Chehab 		.external_av = 1,
3790c0d06caSMauro Carvalho Chehab 		.input = {{
3800c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
3810c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
3820c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3830c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3840c0d06caSMauro Carvalho Chehab 		}, {
3850c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
3860c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
3870c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
3880c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
3890c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
3900c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
3910c0d06caSMauro Carvalho Chehab 		} },
3920c0d06caSMauro Carvalho Chehab 	},
3930c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = {
3940c0d06caSMauro Carvalho Chehab 		.name = "Kworld UB430 USB Hybrid",
3950c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
3960c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
3970c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
3980c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
3990c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
4000c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
4010c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x11,	/* According with PV cxPolaris.inf file */
4020c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = -1,
4030c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = -1,
4040c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = -1,
4050c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
406d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
407b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
408d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4090c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
4100c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x10,
4110c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL_M,
4120c0d06caSMauro Carvalho Chehab 		.input = {{
4130c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
4140c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
4150c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
4160c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4170c0d06caSMauro Carvalho Chehab 		}, {
4180c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
4190c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
4200c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4210c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4220c0d06caSMauro Carvalho Chehab 		}, {
4230c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
4240c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
4250c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
4260c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
4270c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4280c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4290c0d06caSMauro Carvalho Chehab 		} },
4300c0d06caSMauro Carvalho Chehab 	},
4318b1255a2SJohannes Erdfelt 	[CX231XX_BOARD_KWORLD_UB445_USB_HYBRID] = {
4328b1255a2SJohannes Erdfelt 		.name = "Kworld UB445 USB Hybrid",
4338b1255a2SJohannes Erdfelt 		.tuner_type = TUNER_NXP_TDA18271,
4348b1255a2SJohannes Erdfelt 		.tuner_addr = 0x60,
4358b1255a2SJohannes Erdfelt 		.decoder = CX231XX_AVDECODER,
4368b1255a2SJohannes Erdfelt 		.output_mode = OUT_MODE_VIP11,
4378b1255a2SJohannes Erdfelt 		.demod_xfer_mode = 0,
4388b1255a2SJohannes Erdfelt 		.ctl_pin_status_mask = 0xFFFFFFC4,
4398b1255a2SJohannes Erdfelt 		.agc_analog_digital_select_gpio = 0x11,	/* According with PV cxPolaris.inf file */
4408b1255a2SJohannes Erdfelt 		.tuner_sif_gpio = -1,
4418b1255a2SJohannes Erdfelt 		.tuner_scl_gpio = -1,
4428b1255a2SJohannes Erdfelt 		.tuner_sda_gpio = -1,
4438b1255a2SJohannes Erdfelt 		.gpio_pin_status_mask = 0x4001000,
444d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
445b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
446d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4478b1255a2SJohannes Erdfelt 		.has_dvb = 1,
4488b1255a2SJohannes Erdfelt 		.demod_addr = 0x10,
4498b1255a2SJohannes Erdfelt 		.norm = V4L2_STD_NTSC_M,
4508b1255a2SJohannes Erdfelt 		.input = {{
4518b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_TELEVISION,
4528b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_3_1,
4538b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_VIDEO,
4548b1255a2SJohannes Erdfelt 			.gpio = NULL,
4558b1255a2SJohannes Erdfelt 		}, {
4568b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_COMPOSITE1,
4578b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_2_1,
4588b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_LINE_IN,
4598b1255a2SJohannes Erdfelt 			.gpio = NULL,
4608b1255a2SJohannes Erdfelt 		}, {
4618b1255a2SJohannes Erdfelt 			.type = CX231XX_VMUX_SVIDEO,
4628b1255a2SJohannes Erdfelt 			.vmux = CX231XX_VIN_1_1 |
4638b1255a2SJohannes Erdfelt 				(CX231XX_VIN_1_2 << 8) |
4648b1255a2SJohannes Erdfelt 				CX25840_SVIDEO_ON,
4658b1255a2SJohannes Erdfelt 			.amux = CX231XX_AMUX_LINE_IN,
4668b1255a2SJohannes Erdfelt 			.gpio = NULL,
4678b1255a2SJohannes Erdfelt 		} },
4688b1255a2SJohannes Erdfelt 	},
4690c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
4700c0d06caSMauro Carvalho Chehab 		.name = "Pixelview PlayTV USB Hybrid",
4710c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
4720c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
4730c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
4740c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
4750c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
4760c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
47724b923f0SMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1c,
4780c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = -1,
4790c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = -1,
4800c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = -1,
4810c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
482d032ca12SMatthias Schwarzott 		.tuner_i2c_master = I2C_2,
483b9ce9dfdSMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
484d032ca12SMatthias Schwarzott 		.ir_i2c_master = I2C_2,
4850c0d06caSMauro Carvalho Chehab 		.rc_map_name = RC_MAP_PIXELVIEW_002T,
4860c0d06caSMauro Carvalho Chehab 		.has_dvb = 1,
4870c0d06caSMauro Carvalho Chehab 		.demod_addr = 0x10,
4880c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL_M,
4890c0d06caSMauro Carvalho Chehab 		.input = {{
4900c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
4910c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
4920c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
4930c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4940c0d06caSMauro Carvalho Chehab 		}, {
4950c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
4960c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
4970c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
4980c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
4990c0d06caSMauro Carvalho Chehab 		}, {
5000c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
5010c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
5020c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
5030c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
5040c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5050c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5060c0d06caSMauro Carvalho Chehab 		} },
5070c0d06caSMauro Carvalho Chehab 	},
5080c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_PV_XCAPTURE_USB] = {
5090c0d06caSMauro Carvalho Chehab 		.name = "Pixelview Xcapture USB",
5100c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
5110c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5120c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5130c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
5140c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5150c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
5160c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
5170c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
5180c0d06caSMauro Carvalho Chehab 		.no_alt_vanc = 1,
5190c0d06caSMauro Carvalho Chehab 		.external_av = 1,
5200c0d06caSMauro Carvalho Chehab 
5210c0d06caSMauro Carvalho Chehab 		.input = {{
5220c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_COMPOSITE1,
5230c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_2_1,
5240c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
5250c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
5260c0d06caSMauro Carvalho Chehab 			}, {
5270c0d06caSMauro Carvalho Chehab 				.type = CX231XX_VMUX_SVIDEO,
5280c0d06caSMauro Carvalho Chehab 				.vmux = CX231XX_VIN_1_1 |
5290c0d06caSMauro Carvalho Chehab 					(CX231XX_VIN_1_2 << 8) |
5300c0d06caSMauro Carvalho Chehab 					CX25840_SVIDEO_ON,
5310c0d06caSMauro Carvalho Chehab 				.amux = CX231XX_AMUX_LINE_IN,
5320c0d06caSMauro Carvalho Chehab 				.gpio = NULL,
5330c0d06caSMauro Carvalho Chehab 			}
5340c0d06caSMauro Carvalho Chehab 		},
5350c0d06caSMauro Carvalho Chehab 	},
5360c0d06caSMauro Carvalho Chehab 
5370c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_ICONBIT_U100] = {
5380c0d06caSMauro Carvalho Chehab 		.name = "Iconbit Analog Stick U100 FM",
5390c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_ABSENT,
5400c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5410c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5420c0d06caSMauro Carvalho Chehab 		.demod_xfer_mode = 0,
5430c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5440c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x1C,
5450c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
5460c0d06caSMauro Carvalho Chehab 
5470c0d06caSMauro Carvalho Chehab 		.input = {{
5480c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
5490c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
5500c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5510c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5520c0d06caSMauro Carvalho Chehab 		}, {
5530c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
5540c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
5550c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
5560c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
5570c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5580c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5590c0d06caSMauro Carvalho Chehab 		} },
5600c0d06caSMauro Carvalho Chehab 	},
5610c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
5620c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge WinTV USB2 FM (PAL)",
5630c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
5640c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
5650c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
5660c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
5670c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
5680c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
5690c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
5700c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
5710c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
5720c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
5730c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
574b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
5750c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_PAL,
5760c0d06caSMauro Carvalho Chehab 
5770c0d06caSMauro Carvalho Chehab 		.input = {{
5780c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
5790c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
5800c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
5810c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5820c0d06caSMauro Carvalho Chehab 		}, {
5830c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
5840c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
5850c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5860c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5870c0d06caSMauro Carvalho Chehab 		}, {
5880c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
5890c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
5900c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
5910c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
5920c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
5930c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
5940c0d06caSMauro Carvalho Chehab 		} },
5950c0d06caSMauro Carvalho Chehab 	},
5960c0d06caSMauro Carvalho Chehab 	[CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
5970c0d06caSMauro Carvalho Chehab 		.name = "Hauppauge WinTV USB2 FM (NTSC)",
5980c0d06caSMauro Carvalho Chehab 		.tuner_type = TUNER_NXP_TDA18271,
5990c0d06caSMauro Carvalho Chehab 		.tuner_addr = 0x60,
6000c0d06caSMauro Carvalho Chehab 		.tuner_gpio = RDE250_XCV_TUNER,
6010c0d06caSMauro Carvalho Chehab 		.tuner_sif_gpio = 0x05,
6020c0d06caSMauro Carvalho Chehab 		.tuner_scl_gpio = 0x1a,
6030c0d06caSMauro Carvalho Chehab 		.tuner_sda_gpio = 0x1b,
6040c0d06caSMauro Carvalho Chehab 		.decoder = CX231XX_AVDECODER,
6050c0d06caSMauro Carvalho Chehab 		.output_mode = OUT_MODE_VIP11,
6060c0d06caSMauro Carvalho Chehab 		.ctl_pin_status_mask = 0xFFFFFFC4,
6070c0d06caSMauro Carvalho Chehab 		.agc_analog_digital_select_gpio = 0x0c,
6080c0d06caSMauro Carvalho Chehab 		.gpio_pin_status_mask = 0x4001000,
609b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
6100c0d06caSMauro Carvalho Chehab 		.norm = V4L2_STD_NTSC,
6110c0d06caSMauro Carvalho Chehab 
6120c0d06caSMauro Carvalho Chehab 		.input = {{
6130c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_TELEVISION,
6140c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_3_1,
6150c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_VIDEO,
6160c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6170c0d06caSMauro Carvalho Chehab 		}, {
6180c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_COMPOSITE1,
6190c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_2_1,
6200c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
6210c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6220c0d06caSMauro Carvalho Chehab 		}, {
6230c0d06caSMauro Carvalho Chehab 			.type = CX231XX_VMUX_SVIDEO,
6240c0d06caSMauro Carvalho Chehab 			.vmux = CX231XX_VIN_1_1 |
6250c0d06caSMauro Carvalho Chehab 				(CX231XX_VIN_1_2 << 8) |
6260c0d06caSMauro Carvalho Chehab 				CX25840_SVIDEO_ON,
6270c0d06caSMauro Carvalho Chehab 			.amux = CX231XX_AMUX_LINE_IN,
6280c0d06caSMauro Carvalho Chehab 			.gpio = NULL,
6290c0d06caSMauro Carvalho Chehab 		} },
6300c0d06caSMauro Carvalho Chehab 	},
63168c97bf3SAlf Høgemark 	[CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2] = {
63268c97bf3SAlf Høgemark 		.name = "Elgato Video Capture V2",
63368c97bf3SAlf Høgemark 		.tuner_type = TUNER_ABSENT,
63468c97bf3SAlf Høgemark 		.decoder = CX231XX_AVDECODER,
63568c97bf3SAlf Høgemark 		.output_mode = OUT_MODE_VIP11,
63668c97bf3SAlf Høgemark 		.demod_xfer_mode = 0,
63768c97bf3SAlf Høgemark 		.ctl_pin_status_mask = 0xFFFFFFC4,
63868c97bf3SAlf Høgemark 		.agc_analog_digital_select_gpio = 0x0c,
63968c97bf3SAlf Høgemark 		.gpio_pin_status_mask = 0x4001000,
64068c97bf3SAlf Høgemark 		.norm = V4L2_STD_NTSC,
64168c97bf3SAlf Høgemark 		.no_alt_vanc = 1,
64268c97bf3SAlf Høgemark 		.external_av = 1,
64368c97bf3SAlf Høgemark 		.input = {{
64468c97bf3SAlf Høgemark 			.type = CX231XX_VMUX_COMPOSITE1,
64568c97bf3SAlf Høgemark 			.vmux = CX231XX_VIN_2_1,
64668c97bf3SAlf Høgemark 			.amux = CX231XX_AMUX_LINE_IN,
64768c97bf3SAlf Høgemark 			.gpio = NULL,
64868c97bf3SAlf Høgemark 		}, {
64968c97bf3SAlf Høgemark 			.type = CX231XX_VMUX_SVIDEO,
65068c97bf3SAlf Høgemark 			.vmux = CX231XX_VIN_1_1 |
65168c97bf3SAlf Høgemark 				(CX231XX_VIN_1_2 << 8) |
65268c97bf3SAlf Høgemark 				CX25840_SVIDEO_ON,
65368c97bf3SAlf Høgemark 			.amux = CX231XX_AMUX_LINE_IN,
65468c97bf3SAlf Høgemark 			.gpio = NULL,
65568c97bf3SAlf Høgemark 		} },
65668c97bf3SAlf Høgemark 	},
6573ead1ba3SMatt Gomboc 	[CX231XX_BOARD_OTG102] = {
6583ead1ba3SMatt Gomboc 		.name = "Geniatech OTG102",
6593ead1ba3SMatt Gomboc 		.tuner_type = TUNER_ABSENT,
6603ead1ba3SMatt Gomboc 		.decoder = CX231XX_AVDECODER,
6613ead1ba3SMatt Gomboc 		.output_mode = OUT_MODE_VIP11,
6623ead1ba3SMatt Gomboc 		.ctl_pin_status_mask = 0xFFFFFFC4,
6633ead1ba3SMatt Gomboc 		.agc_analog_digital_select_gpio = 0x0c,
6643ead1ba3SMatt Gomboc 			/* According with PV CxPlrCAP.inf file */
6653ead1ba3SMatt Gomboc 		.gpio_pin_status_mask = 0x4001000,
6663ead1ba3SMatt Gomboc 		.norm = V4L2_STD_NTSC,
6673ead1ba3SMatt Gomboc 		.no_alt_vanc = 1,
6683ead1ba3SMatt Gomboc 		.external_av = 1,
6693ead1ba3SMatt Gomboc 		/*.has_417 = 1, */
6703ead1ba3SMatt Gomboc 		/* This board is believed to have a hardware encoding chip
6713ead1ba3SMatt Gomboc 		 * supporting mpeg1/2/4, but as the 417 is apparently not
6723ead1ba3SMatt Gomboc 		 * working for the reference board it is not here either. */
6733ead1ba3SMatt Gomboc 
6743ead1ba3SMatt Gomboc 		.input = {{
6753ead1ba3SMatt Gomboc 				.type = CX231XX_VMUX_COMPOSITE1,
6763ead1ba3SMatt Gomboc 				.vmux = CX231XX_VIN_2_1,
6773ead1ba3SMatt Gomboc 				.amux = CX231XX_AMUX_LINE_IN,
6783ead1ba3SMatt Gomboc 				.gpio = NULL,
6793ead1ba3SMatt Gomboc 			}, {
6803ead1ba3SMatt Gomboc 				.type = CX231XX_VMUX_SVIDEO,
6813ead1ba3SMatt Gomboc 				.vmux = CX231XX_VIN_1_1 |
6823ead1ba3SMatt Gomboc 					(CX231XX_VIN_1_2 << 8) |
6833ead1ba3SMatt Gomboc 					CX25840_SVIDEO_ON,
6843ead1ba3SMatt Gomboc 				.amux = CX231XX_AMUX_LINE_IN,
6853ead1ba3SMatt Gomboc 				.gpio = NULL,
6863ead1ba3SMatt Gomboc 			}
6873ead1ba3SMatt Gomboc 		},
6883ead1ba3SMatt Gomboc 	},
689dd2e7dd2SMatthias Schwarzott 	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx] = {
69057cbf3efSMatthias Schwarzott 		.name = "Hauppauge WinTV 930C-HD (1113xx) / HVR-900H (111xxx) / PCTV QuatroStick 521e",
691dd2e7dd2SMatthias Schwarzott 		.tuner_type = TUNER_NXP_TDA18271,
692dd2e7dd2SMatthias Schwarzott 		.tuner_addr = 0x60,
693dd2e7dd2SMatthias Schwarzott 		.tuner_gpio = RDE250_XCV_TUNER,
694dd2e7dd2SMatthias Schwarzott 		.tuner_sif_gpio = 0x05,
695dd2e7dd2SMatthias Schwarzott 		.tuner_scl_gpio = 0x1a,
696dd2e7dd2SMatthias Schwarzott 		.tuner_sda_gpio = 0x1b,
697dd2e7dd2SMatthias Schwarzott 		.decoder = CX231XX_AVDECODER,
698dd2e7dd2SMatthias Schwarzott 		.output_mode = OUT_MODE_VIP11,
699dd2e7dd2SMatthias Schwarzott 		.demod_xfer_mode = 0,
700dd2e7dd2SMatthias Schwarzott 		.ctl_pin_status_mask = 0xFFFFFFC4,
701dd2e7dd2SMatthias Schwarzott 		.agc_analog_digital_select_gpio = 0x0c,
702dd2e7dd2SMatthias Schwarzott 		.gpio_pin_status_mask = 0x4001000,
703b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
704599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
705dd2e7dd2SMatthias Schwarzott 		.has_dvb = 1,
706830a57f4SBrad Love 		.demod_addr = 0x64, /* 0xc8 >> 1 */
707dd2e7dd2SMatthias Schwarzott 		.norm = V4L2_STD_PAL,
708dd2e7dd2SMatthias Schwarzott 
709dd2e7dd2SMatthias Schwarzott 		.input = {{
710dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_TELEVISION,
711dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_3_1,
712dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_VIDEO,
713dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
714dd2e7dd2SMatthias Schwarzott 		}, {
715dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_COMPOSITE1,
716dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_2_1,
717dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
718dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
719dd2e7dd2SMatthias Schwarzott 		}, {
720dd2e7dd2SMatthias Schwarzott 			.type = CX231XX_VMUX_SVIDEO,
721dd2e7dd2SMatthias Schwarzott 			.vmux = CX231XX_VIN_1_1 |
722dd2e7dd2SMatthias Schwarzott 				(CX231XX_VIN_1_2 << 8) |
723dd2e7dd2SMatthias Schwarzott 				CX25840_SVIDEO_ON,
724dd2e7dd2SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
725dd2e7dd2SMatthias Schwarzott 			.gpio = NULL,
726dd2e7dd2SMatthias Schwarzott 		} },
727dd2e7dd2SMatthias Schwarzott 	},
7289e49f7c3SMatthias Schwarzott 	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx] = {
7298618ac4dSMatthias Schwarzott 		.name = "Hauppauge WinTV 930C-HD (1114xx) / HVR-901H (1114xx) / PCTV QuatroStick 522e",
7309e49f7c3SMatthias Schwarzott 		.tuner_type = TUNER_ABSENT,
7319e49f7c3SMatthias Schwarzott 		.tuner_addr = 0x60,
7329e49f7c3SMatthias Schwarzott 		.tuner_gpio = RDE250_XCV_TUNER,
7339e49f7c3SMatthias Schwarzott 		.tuner_sif_gpio = 0x05,
7349e49f7c3SMatthias Schwarzott 		.tuner_scl_gpio = 0x1a,
7359e49f7c3SMatthias Schwarzott 		.tuner_sda_gpio = 0x1b,
7369e49f7c3SMatthias Schwarzott 		.decoder = CX231XX_AVDECODER,
7379e49f7c3SMatthias Schwarzott 		.output_mode = OUT_MODE_VIP11,
7389e49f7c3SMatthias Schwarzott 		.demod_xfer_mode = 0,
7399e49f7c3SMatthias Schwarzott 		.ctl_pin_status_mask = 0xFFFFFFC4,
7409e49f7c3SMatthias Schwarzott 		.agc_analog_digital_select_gpio = 0x0c,
7419e49f7c3SMatthias Schwarzott 		.gpio_pin_status_mask = 0x4001000,
742b9ce9dfdSMatthias Schwarzott 		.tuner_i2c_master = I2C_1_MUX_3,
743599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
7449e49f7c3SMatthias Schwarzott 		.has_dvb = 1,
745830a57f4SBrad Love 		.demod_addr = 0x64, /* 0xc8 >> 1 */
7469e49f7c3SMatthias Schwarzott 		.norm = V4L2_STD_PAL,
7479e49f7c3SMatthias Schwarzott 
7489e49f7c3SMatthias Schwarzott 		.input = {{
7499e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_TELEVISION,
7509e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_3_1,
7519e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_VIDEO,
7529e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7539e49f7c3SMatthias Schwarzott 		}, {
7549e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_COMPOSITE1,
7559e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_2_1,
7569e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
7579e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7589e49f7c3SMatthias Schwarzott 		}, {
7599e49f7c3SMatthias Schwarzott 			.type = CX231XX_VMUX_SVIDEO,
7609e49f7c3SMatthias Schwarzott 			.vmux = CX231XX_VIN_1_1 |
7619e49f7c3SMatthias Schwarzott 				(CX231XX_VIN_1_2 << 8) |
7629e49f7c3SMatthias Schwarzott 				CX25840_SVIDEO_ON,
7639e49f7c3SMatthias Schwarzott 			.amux = CX231XX_AMUX_LINE_IN,
7649e49f7c3SMatthias Schwarzott 			.gpio = NULL,
7659e49f7c3SMatthias Schwarzott 		} },
7669e49f7c3SMatthias Schwarzott 	},
767809abdbfSOlli Salonen 	[CX231XX_BOARD_HAUPPAUGE_955Q] = {
768809abdbfSOlli Salonen 		.name = "Hauppauge WinTV-HVR-955Q (111401)",
769809abdbfSOlli Salonen 		.tuner_type = TUNER_ABSENT,
770809abdbfSOlli Salonen 		.tuner_addr = 0x60,
771809abdbfSOlli Salonen 		.tuner_gpio = RDE250_XCV_TUNER,
772809abdbfSOlli Salonen 		.tuner_sif_gpio = 0x05,
773809abdbfSOlli Salonen 		.tuner_scl_gpio = 0x1a,
774809abdbfSOlli Salonen 		.tuner_sda_gpio = 0x1b,
775809abdbfSOlli Salonen 		.decoder = CX231XX_AVDECODER,
776809abdbfSOlli Salonen 		.output_mode = OUT_MODE_VIP11,
777809abdbfSOlli Salonen 		.demod_xfer_mode = 0,
778809abdbfSOlli Salonen 		.ctl_pin_status_mask = 0xFFFFFFC4,
779809abdbfSOlli Salonen 		.agc_analog_digital_select_gpio = 0x0c,
780809abdbfSOlli Salonen 		.gpio_pin_status_mask = 0x4001000,
781809abdbfSOlli Salonen 		.tuner_i2c_master = I2C_1_MUX_3,
782599bedb7SMatthias Schwarzott 		.demod_i2c_master = I2C_1_MUX_3,
783809abdbfSOlli Salonen 		.has_dvb = 1,
784830a57f4SBrad Love 		.demod_addr = 0x59, /* 0xb2 >> 1 */
785809abdbfSOlli Salonen 		.norm = V4L2_STD_NTSC,
786809abdbfSOlli Salonen 
787809abdbfSOlli Salonen 		.input = {{
788809abdbfSOlli Salonen 			.type = CX231XX_VMUX_TELEVISION,
789809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_3_1,
790809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_VIDEO,
791809abdbfSOlli Salonen 			.gpio = NULL,
792809abdbfSOlli Salonen 		}, {
793809abdbfSOlli Salonen 			.type = CX231XX_VMUX_COMPOSITE1,
794809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_2_1,
795809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_LINE_IN,
796809abdbfSOlli Salonen 			.gpio = NULL,
797809abdbfSOlli Salonen 		}, {
798809abdbfSOlli Salonen 			.type = CX231XX_VMUX_SVIDEO,
799809abdbfSOlli Salonen 			.vmux = CX231XX_VIN_1_1 |
800809abdbfSOlli Salonen 				(CX231XX_VIN_1_2 << 8) |
801809abdbfSOlli Salonen 				CX25840_SVIDEO_ON,
802809abdbfSOlli Salonen 			.amux = CX231XX_AMUX_LINE_IN,
803809abdbfSOlli Salonen 			.gpio = NULL,
804809abdbfSOlli Salonen 		} },
805809abdbfSOlli Salonen 	},
806eee1d06dSTommi Rantala 	[CX231XX_BOARD_TERRATEC_GRABBY] = {
807eee1d06dSTommi Rantala 		.name = "Terratec Grabby",
808eee1d06dSTommi Rantala 		.tuner_type = TUNER_ABSENT,
809eee1d06dSTommi Rantala 		.decoder = CX231XX_AVDECODER,
810eee1d06dSTommi Rantala 		.output_mode = OUT_MODE_VIP11,
811eee1d06dSTommi Rantala 		.demod_xfer_mode = 0,
812eee1d06dSTommi Rantala 		.ctl_pin_status_mask = 0xFFFFFFC4,
813eee1d06dSTommi Rantala 		.agc_analog_digital_select_gpio = 0x0c,
814eee1d06dSTommi Rantala 		.gpio_pin_status_mask = 0x4001000,
815eee1d06dSTommi Rantala 		.norm = V4L2_STD_PAL,
816eee1d06dSTommi Rantala 		.no_alt_vanc = 1,
817eee1d06dSTommi Rantala 		.external_av = 1,
818eee1d06dSTommi Rantala 		.input = {{
819eee1d06dSTommi Rantala 			.type = CX231XX_VMUX_COMPOSITE1,
820eee1d06dSTommi Rantala 			.vmux = CX231XX_VIN_2_1,
821eee1d06dSTommi Rantala 			.amux = CX231XX_AMUX_LINE_IN,
822eee1d06dSTommi Rantala 			.gpio = NULL,
823eee1d06dSTommi Rantala 		}, {
824eee1d06dSTommi Rantala 			.type = CX231XX_VMUX_SVIDEO,
825eee1d06dSTommi Rantala 			.vmux = CX231XX_VIN_1_1 |
826eee1d06dSTommi Rantala 				(CX231XX_VIN_1_2 << 8) |
827eee1d06dSTommi Rantala 				CX25840_SVIDEO_ON,
828eee1d06dSTommi Rantala 			.amux = CX231XX_AMUX_LINE_IN,
829eee1d06dSTommi Rantala 			.gpio = NULL,
830eee1d06dSTommi Rantala 		} },
831eee1d06dSTommi Rantala 	},
832a096fd64SOleh Kravchenko 	[CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD] = {
833a096fd64SOleh Kravchenko 		.name = "Evromedia USB Full Hybrid Full HD",
834a096fd64SOleh Kravchenko 		.tuner_type = TUNER_ABSENT,
835a096fd64SOleh Kravchenko 		.demod_addr = 0x64, /* 0xc8 >> 1 */
836a096fd64SOleh Kravchenko 		.demod_i2c_master = I2C_1_MUX_3,
837a096fd64SOleh Kravchenko 		.has_dvb = 1,
8389d377daeSOleh Kravchenko 		.decoder = CX231XX_AVDECODER,
839a096fd64SOleh Kravchenko 		.norm = V4L2_STD_PAL,
840a096fd64SOleh Kravchenko 		.output_mode = OUT_MODE_VIP11,
841a096fd64SOleh Kravchenko 		.tuner_addr = 0x60, /* 0xc0 >> 1 */
842a096fd64SOleh Kravchenko 		.tuner_i2c_master = I2C_2,
843a096fd64SOleh Kravchenko 		.input = {{
844a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_TELEVISION,
845a096fd64SOleh Kravchenko 			.vmux = 0,
846a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_VIDEO,
847a096fd64SOleh Kravchenko 		}, {
848a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_COMPOSITE1,
849a096fd64SOleh Kravchenko 			.vmux = CX231XX_VIN_2_1,
850a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_LINE_IN,
851a096fd64SOleh Kravchenko 		}, {
852a096fd64SOleh Kravchenko 			.type = CX231XX_VMUX_SVIDEO,
853a096fd64SOleh Kravchenko 			.vmux = CX231XX_VIN_1_1 |
854a096fd64SOleh Kravchenko 				(CX231XX_VIN_1_2 << 8) |
855a096fd64SOleh Kravchenko 				CX25840_SVIDEO_ON,
856a096fd64SOleh Kravchenko 			.amux = CX231XX_AMUX_LINE_IN,
857a096fd64SOleh Kravchenko 		} },
858a096fd64SOleh Kravchenko 	},
8590f42b331SOleh Kravchenko 	[CX231XX_BOARD_ASTROMETA_T2HYBRID] = {
8600f42b331SOleh Kravchenko 		.name = "Astrometa T2hybrid",
8610f42b331SOleh Kravchenko 		.tuner_type = TUNER_ABSENT,
8620f42b331SOleh Kravchenko 		.has_dvb = 1,
8631bfbb885SOleh Kravchenko 		.decoder = CX231XX_AVDECODER,
8640f42b331SOleh Kravchenko 		.output_mode = OUT_MODE_VIP11,
8650f42b331SOleh Kravchenko 		.agc_analog_digital_select_gpio = 0x01,
8660f42b331SOleh Kravchenko 		.ctl_pin_status_mask = 0xffffffc4,
8670f42b331SOleh Kravchenko 		.demod_addr = 0x18, /* 0x30 >> 1 */
8680f42b331SOleh Kravchenko 		.demod_i2c_master = I2C_1_MUX_1,
8690f42b331SOleh Kravchenko 		.gpio_pin_status_mask = 0xa,
8700f42b331SOleh Kravchenko 		.norm = V4L2_STD_NTSC,
8710f42b331SOleh Kravchenko 		.tuner_addr = 0x3a, /* 0x74 >> 1 */
8720f42b331SOleh Kravchenko 		.tuner_i2c_master = I2C_1_MUX_3,
8730f42b331SOleh Kravchenko 		.tuner_scl_gpio = 0x1a,
8740f42b331SOleh Kravchenko 		.tuner_sda_gpio = 0x1b,
8750f42b331SOleh Kravchenko 		.tuner_sif_gpio = 0x05,
8760f42b331SOleh Kravchenko 		.input = {{
8770f42b331SOleh Kravchenko 				.type = CX231XX_VMUX_TELEVISION,
8780f42b331SOleh Kravchenko 				.vmux = CX231XX_VIN_1_1,
8790f42b331SOleh Kravchenko 				.amux = CX231XX_AMUX_VIDEO,
8800f42b331SOleh Kravchenko 			}, {
8810f42b331SOleh Kravchenko 				.type = CX231XX_VMUX_COMPOSITE1,
8820f42b331SOleh Kravchenko 				.vmux = CX231XX_VIN_2_1,
8830f42b331SOleh Kravchenko 				.amux = CX231XX_AMUX_LINE_IN,
8840f42b331SOleh Kravchenko 			},
8850f42b331SOleh Kravchenko 		},
8860f42b331SOleh Kravchenko 	},
887fdda0109SRomain Reignier 	[CX231XX_BOARD_THE_IMAGING_SOURCE_DFG_USB2_PRO] = {
888fdda0109SRomain Reignier 		.name = "The Imaging Source DFG/USB2pro",
889fdda0109SRomain Reignier 		.tuner_type = TUNER_ABSENT,
890fdda0109SRomain Reignier 		.decoder = CX231XX_AVDECODER,
891fdda0109SRomain Reignier 		.output_mode = OUT_MODE_VIP11,
892fdda0109SRomain Reignier 		.demod_xfer_mode = 0,
893fdda0109SRomain Reignier 		.ctl_pin_status_mask = 0xFFFFFFC4,
894fdda0109SRomain Reignier 		.agc_analog_digital_select_gpio = 0x0c,
895fdda0109SRomain Reignier 		.gpio_pin_status_mask = 0x4001000,
896fdda0109SRomain Reignier 		.norm = V4L2_STD_PAL,
897fdda0109SRomain Reignier 		.no_alt_vanc = 1,
898fdda0109SRomain Reignier 		.external_av = 1,
899fdda0109SRomain Reignier 		.input = {{
900fdda0109SRomain Reignier 			.type = CX231XX_VMUX_COMPOSITE1,
901fdda0109SRomain Reignier 			.vmux = CX231XX_VIN_1_1,
902fdda0109SRomain Reignier 			.amux = CX231XX_AMUX_LINE_IN,
903fdda0109SRomain Reignier 			.gpio = NULL,
904fdda0109SRomain Reignier 		}, {
905fdda0109SRomain Reignier 			.type = CX231XX_VMUX_SVIDEO,
906fdda0109SRomain Reignier 			.vmux = CX231XX_VIN_2_1 |
907fdda0109SRomain Reignier 				(CX231XX_VIN_2_2 << 8) |
908fdda0109SRomain Reignier 				CX25840_SVIDEO_ON,
909fdda0109SRomain Reignier 			.amux = CX231XX_AMUX_LINE_IN,
910fdda0109SRomain Reignier 			.gpio = NULL,
911fdda0109SRomain Reignier 		} },
912fdda0109SRomain Reignier 	},
913c5bef50eSBrad Love 	[CX231XX_BOARD_HAUPPAUGE_935C] = {
914c5bef50eSBrad Love 		.name = "Hauppauge WinTV-HVR-935C",
915c5bef50eSBrad Love 		.tuner_type = TUNER_ABSENT,
916c5bef50eSBrad Love 		.tuner_addr = 0x60,
917c5bef50eSBrad Love 		.tuner_gpio = RDE250_XCV_TUNER,
918c5bef50eSBrad Love 		.tuner_sif_gpio = 0x05,
919c5bef50eSBrad Love 		.tuner_scl_gpio = 0x1a,
920c5bef50eSBrad Love 		.tuner_sda_gpio = 0x1b,
921c5bef50eSBrad Love 		.decoder = CX231XX_AVDECODER,
922c5bef50eSBrad Love 		.output_mode = OUT_MODE_VIP11,
923c5bef50eSBrad Love 		.demod_xfer_mode = 0,
924c5bef50eSBrad Love 		.ctl_pin_status_mask = 0xFFFFFFC4,
925c5bef50eSBrad Love 		.agc_analog_digital_select_gpio = 0x0c,
926c5bef50eSBrad Love 		.gpio_pin_status_mask = 0x4001000,
927c5bef50eSBrad Love 		.tuner_i2c_master = I2C_1_MUX_3,
928c5bef50eSBrad Love 		.demod_i2c_master = I2C_1_MUX_3,
929c5bef50eSBrad Love 		.has_dvb = 1,
930c5bef50eSBrad Love 		.demod_addr = 0x64, /* 0xc8 >> 1 */
931c5bef50eSBrad Love 		.norm = V4L2_STD_PAL,
932c5bef50eSBrad Love 
933c5bef50eSBrad Love 		.input = {{
934c5bef50eSBrad Love 			.type = CX231XX_VMUX_TELEVISION,
935c5bef50eSBrad Love 			.vmux = CX231XX_VIN_3_1,
936c5bef50eSBrad Love 			.amux = CX231XX_AMUX_VIDEO,
937c5bef50eSBrad Love 			.gpio = NULL,
938c5bef50eSBrad Love 		}, {
939c5bef50eSBrad Love 			.type = CX231XX_VMUX_COMPOSITE1,
940c5bef50eSBrad Love 			.vmux = CX231XX_VIN_2_1,
941c5bef50eSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
942c5bef50eSBrad Love 			.gpio = NULL,
943c5bef50eSBrad Love 		}, {
944c5bef50eSBrad Love 			.type = CX231XX_VMUX_SVIDEO,
945c5bef50eSBrad Love 			.vmux = CX231XX_VIN_1_1 |
946c5bef50eSBrad Love 				(CX231XX_VIN_1_2 << 8) |
947c5bef50eSBrad Love 				CX25840_SVIDEO_ON,
948c5bef50eSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
949c5bef50eSBrad Love 			.gpio = NULL,
950c5bef50eSBrad Love 		} },
951c5bef50eSBrad Love 	},
95219fbf1baSBrad Love 	[CX231XX_BOARD_HAUPPAUGE_975] = {
95319fbf1baSBrad Love 		.name = "Hauppauge WinTV-HVR-975",
95419fbf1baSBrad Love 		.tuner_type = TUNER_ABSENT,
95519fbf1baSBrad Love 		.tuner_addr = 0x60,
95619fbf1baSBrad Love 		.tuner_gpio = RDE250_XCV_TUNER,
95719fbf1baSBrad Love 		.tuner_sif_gpio = 0x05,
95819fbf1baSBrad Love 		.tuner_scl_gpio = 0x1a,
95919fbf1baSBrad Love 		.tuner_sda_gpio = 0x1b,
96019fbf1baSBrad Love 		.decoder = CX231XX_AVDECODER,
96119fbf1baSBrad Love 		.output_mode = OUT_MODE_VIP11,
96219fbf1baSBrad Love 		.demod_xfer_mode = 0,
96319fbf1baSBrad Love 		.ctl_pin_status_mask = 0xFFFFFFC4,
96419fbf1baSBrad Love 		.agc_analog_digital_select_gpio = 0x0c,
96519fbf1baSBrad Love 		.gpio_pin_status_mask = 0x4001000,
96619fbf1baSBrad Love 		.tuner_i2c_master = I2C_1_MUX_3,
96719fbf1baSBrad Love 		.demod_i2c_master = I2C_1_MUX_3,
96819fbf1baSBrad Love 		.has_dvb = 1,
96919fbf1baSBrad Love 		.demod_addr = 0x59, /* 0xb2 >> 1 */
970a2c52cd7SBrad Love 		.demod_addr2 = 0x64, /* 0xc8 >> 1 */
97119fbf1baSBrad Love 		.norm = V4L2_STD_ALL,
97219fbf1baSBrad Love 
97319fbf1baSBrad Love 		.input = {{
97419fbf1baSBrad Love 			.type = CX231XX_VMUX_TELEVISION,
97519fbf1baSBrad Love 			.vmux = CX231XX_VIN_3_1,
97619fbf1baSBrad Love 			.amux = CX231XX_AMUX_VIDEO,
97719fbf1baSBrad Love 			.gpio = NULL,
97819fbf1baSBrad Love 		}, {
97919fbf1baSBrad Love 			.type = CX231XX_VMUX_COMPOSITE1,
98019fbf1baSBrad Love 			.vmux = CX231XX_VIN_2_1,
98119fbf1baSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
98219fbf1baSBrad Love 			.gpio = NULL,
98319fbf1baSBrad Love 		}, {
98419fbf1baSBrad Love 			.type = CX231XX_VMUX_SVIDEO,
98519fbf1baSBrad Love 			.vmux = CX231XX_VIN_1_1 |
98619fbf1baSBrad Love 				(CX231XX_VIN_1_2 << 8) |
98719fbf1baSBrad Love 				CX25840_SVIDEO_ON,
98819fbf1baSBrad Love 			.amux = CX231XX_AMUX_LINE_IN,
98919fbf1baSBrad Love 			.gpio = NULL,
99019fbf1baSBrad Love 		} },
99119fbf1baSBrad Love 	},
9920c0d06caSMauro Carvalho Chehab };
9930c0d06caSMauro Carvalho Chehab const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
9940c0d06caSMauro Carvalho Chehab 
9950c0d06caSMauro Carvalho Chehab /* table of devices that work with this driver */
9960c0d06caSMauro Carvalho Chehab struct usb_device_id cx231xx_id_table[] = {
997dad4c418SLinks (Markus) 	{USB_DEVICE(0x1D19, 0x6109),
998dad4c418SLinks (Markus) 	.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
9990c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x5A3C),
10000c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_UNKNOWN},
10010c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A2),
10020c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
10030c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A1),
10040c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_SHELBY},
10050c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A4),
10060c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_253S},
10070c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A5),
10080c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_253S},
10090c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A6),
10100c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
10110c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x589E),
10120c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDE_250},
10130c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x0572, 0x58A0),
10140c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_CNXT_RDU_250},
101529e61d6eSKai-Heng Feng 	/* AverMedia DVD EZMaker 7 */
101629e61d6eSKai-Heng Feng 	{USB_DEVICE(0x07ca, 0xc039),
101729e61d6eSKai-Heng Feng 	 .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
10180c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb110),
10190c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
10200c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb111),
10210c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
10220c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb120),
10230c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
1024809abdbfSOlli Salonen 	{USB_DEVICE(0x2040, 0xb123),
1025809abdbfSOlli Salonen 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q},
1026575f6031SBrad Love 	{USB_DEVICE(0x2040, 0xb124),
1027575f6031SBrad Love 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q},
1028c5bef50eSBrad Love 	{USB_DEVICE(0x2040, 0xb151),
1029c5bef50eSBrad Love 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_935C},
103019fbf1baSBrad Love 	{USB_DEVICE(0x2040, 0xb150),
103119fbf1baSBrad Love 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_975},
1032dd2e7dd2SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb130),
1033dd2e7dd2SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
10349e49f7c3SMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb131),
10359e49f7c3SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
103657cbf3efSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-900-H */
103757cbf3efSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb138),
103857cbf3efSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
10398618ac4dSMatthias Schwarzott 	/* Hauppauge WinTV-HVR-901-H */
10408618ac4dSMatthias Schwarzott 	{USB_DEVICE(0x2040, 0xb139),
10418618ac4dSMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
10420c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xb140),
10430c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
10440c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x2040, 0xc200),
10450c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
1046a141a887SMatthias Schwarzott 	/* PCTV QuatroStick 521e */
1047a141a887SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x0259),
1048a141a887SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
1049140a7987SMatthias Schwarzott 	/* PCTV QuatroStick 522e */
1050140a7987SMatthias Schwarzott 	{USB_DEVICE(0x2013, 0x025e),
1051140a7987SMatthias Schwarzott 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
10520c0d06caSMauro Carvalho Chehab 	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
10530c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
10540c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
10550c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
10560c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1b80, 0xe424),
10570c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID},
10588b1255a2SJohannes Erdfelt 	{USB_DEVICE(0x1b80, 0xe421),
10598b1255a2SJohannes Erdfelt 	 .driver_info = CX231XX_BOARD_KWORLD_UB445_USB_HYBRID},
10600c0d06caSMauro Carvalho Chehab 	{USB_DEVICE(0x1f4d, 0x0237),
10610c0d06caSMauro Carvalho Chehab 	 .driver_info = CX231XX_BOARD_ICONBIT_U100},
106268c97bf3SAlf Høgemark 	{USB_DEVICE(0x0fd9, 0x0037),
106368c97bf3SAlf Høgemark 	 .driver_info = CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2},
10643ead1ba3SMatt Gomboc 	{USB_DEVICE(0x1f4d, 0x0102),
10653ead1ba3SMatt Gomboc 	 .driver_info = CX231XX_BOARD_OTG102},
1066eee1d06dSTommi Rantala 	{USB_DEVICE(USB_VID_TERRATEC, 0x00a6),
1067eee1d06dSTommi Rantala 	 .driver_info = CX231XX_BOARD_TERRATEC_GRABBY},
1068a096fd64SOleh Kravchenko 	{USB_DEVICE(0x1b80, 0xd3b2),
1069a096fd64SOleh Kravchenko 	.driver_info = CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD},
10700f42b331SOleh Kravchenko 	{USB_DEVICE(0x15f4, 0x0135),
10710f42b331SOleh Kravchenko 	.driver_info = CX231XX_BOARD_ASTROMETA_T2HYBRID},
1072fdda0109SRomain Reignier 	{USB_DEVICE(0x199e, 0x8002),
1073fdda0109SRomain Reignier 	 .driver_info = CX231XX_BOARD_THE_IMAGING_SOURCE_DFG_USB2_PRO},
10740c0d06caSMauro Carvalho Chehab 	{},
10750c0d06caSMauro Carvalho Chehab };
10760c0d06caSMauro Carvalho Chehab 
10770c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
10780c0d06caSMauro Carvalho Chehab 
10790c0d06caSMauro Carvalho Chehab /* cx231xx_tuner_callback
10800c0d06caSMauro Carvalho Chehab  * will be used to reset XC5000 tuner using GPIO pin
10810c0d06caSMauro Carvalho Chehab  */
10820c0d06caSMauro Carvalho Chehab 
cx231xx_tuner_callback(void * ptr,int component,int command,int arg)10830c0d06caSMauro Carvalho Chehab int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
10840c0d06caSMauro Carvalho Chehab {
10850c0d06caSMauro Carvalho Chehab 	int rc = 0;
10860c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = ptr;
10870c0d06caSMauro Carvalho Chehab 
10880c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_XC5000) {
10890c0d06caSMauro Carvalho Chehab 		if (command == XC5000_TUNER_RESET) {
1090336fea92SMauro Carvalho Chehab 			dev_dbg(dev->dev,
1091b7085c08SMauro Carvalho Chehab 				"Tuner CB: RESET: cmd %d : tuner type %d\n",
10920c0d06caSMauro Carvalho Chehab 				command, dev->tuner_type);
10930c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
10940c0d06caSMauro Carvalho Chehab 					       1);
10950c0d06caSMauro Carvalho Chehab 			msleep(10);
10960c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
10970c0d06caSMauro Carvalho Chehab 					       0);
10980c0d06caSMauro Carvalho Chehab 			msleep(330);
10990c0d06caSMauro Carvalho Chehab 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
11000c0d06caSMauro Carvalho Chehab 					       1);
11010c0d06caSMauro Carvalho Chehab 			msleep(10);
11020c0d06caSMauro Carvalho Chehab 		}
11030c0d06caSMauro Carvalho Chehab 	} else if (dev->tuner_type == TUNER_NXP_TDA18271) {
11040c0d06caSMauro Carvalho Chehab 		switch (command) {
11050c0d06caSMauro Carvalho Chehab 		case TDA18271_CALLBACK_CMD_AGC_ENABLE:
11060c0d06caSMauro Carvalho Chehab 			if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
11070c0d06caSMauro Carvalho Chehab 				rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
11080c0d06caSMauro Carvalho Chehab 			break;
11090c0d06caSMauro Carvalho Chehab 		default:
11100c0d06caSMauro Carvalho Chehab 			rc = -EINVAL;
11110c0d06caSMauro Carvalho Chehab 			break;
11120c0d06caSMauro Carvalho Chehab 		}
11130c0d06caSMauro Carvalho Chehab 	}
11140c0d06caSMauro Carvalho Chehab 	return rc;
11150c0d06caSMauro Carvalho Chehab }
11160c0d06caSMauro Carvalho Chehab EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
11170c0d06caSMauro Carvalho Chehab 
cx231xx_reset_out(struct cx231xx * dev)1118d4c06133SMauro Carvalho Chehab static void cx231xx_reset_out(struct cx231xx *dev)
11190c0d06caSMauro Carvalho Chehab {
11200c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
11210c0d06caSMauro Carvalho Chehab 	msleep(200);
11220c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
11230c0d06caSMauro Carvalho Chehab 	msleep(200);
11240c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
11250c0d06caSMauro Carvalho Chehab }
1126d4c06133SMauro Carvalho Chehab 
cx231xx_enable_OSC(struct cx231xx * dev)1127d4c06133SMauro Carvalho Chehab static void cx231xx_enable_OSC(struct cx231xx *dev)
11280c0d06caSMauro Carvalho Chehab {
11290c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
11300c0d06caSMauro Carvalho Chehab }
1131d4c06133SMauro Carvalho Chehab 
cx231xx_sleep_s5h1432(struct cx231xx * dev)1132d4c06133SMauro Carvalho Chehab static void cx231xx_sleep_s5h1432(struct cx231xx *dev)
11330c0d06caSMauro Carvalho Chehab {
11340c0d06caSMauro Carvalho Chehab 	cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
11350c0d06caSMauro Carvalho Chehab }
11360c0d06caSMauro Carvalho Chehab 
cx231xx_set_model(struct cx231xx * dev)11370c0d06caSMauro Carvalho Chehab static inline void cx231xx_set_model(struct cx231xx *dev)
11380c0d06caSMauro Carvalho Chehab {
11393724dde9SEzequiel Garcia 	dev->board = cx231xx_boards[dev->model];
11400c0d06caSMauro Carvalho Chehab }
11410c0d06caSMauro Carvalho Chehab 
11420c0d06caSMauro Carvalho Chehab /* Since cx231xx_pre_card_setup() requires a proper dev->model,
11430c0d06caSMauro Carvalho Chehab  * this won't work for boards with generic PCI IDs
11440c0d06caSMauro Carvalho Chehab  */
cx231xx_pre_card_setup(struct cx231xx * dev)11450c0d06caSMauro Carvalho Chehab void cx231xx_pre_card_setup(struct cx231xx *dev)
11460c0d06caSMauro Carvalho Chehab {
1147336fea92SMauro Carvalho Chehab 	dev_info(dev->dev, "Identified as %s (card=%d)\n",
11480c0d06caSMauro Carvalho Chehab 		dev->board.name, dev->model);
11490c0d06caSMauro Carvalho Chehab 
11500f42b331SOleh Kravchenko 	if (CX231XX_BOARD_ASTROMETA_T2HYBRID == dev->model) {
11510f42b331SOleh Kravchenko 		/* turn on demodulator chip */
11520f42b331SOleh Kravchenko 		cx231xx_set_gpio_value(dev, 0x03, 0x01);
11530f42b331SOleh Kravchenko 	}
11540f42b331SOleh Kravchenko 
11550c0d06caSMauro Carvalho Chehab 	/* set the direction for GPIO pins */
11560c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_gpio) {
11570c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
11580c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
11590c0d06caSMauro Carvalho Chehab 	}
11600c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_sif_gpio >= 0)
11610c0d06caSMauro Carvalho Chehab 		cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
11620c0d06caSMauro Carvalho Chehab 
11630c0d06caSMauro Carvalho Chehab 	/* request some modules if any required */
11640c0d06caSMauro Carvalho Chehab 
11650c0d06caSMauro Carvalho Chehab 	/* set the mode to Analog mode initially */
11660c0d06caSMauro Carvalho Chehab 	cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
11670c0d06caSMauro Carvalho Chehab 
11680c0d06caSMauro Carvalho Chehab 	/* Unlock device */
11690c0d06caSMauro Carvalho Chehab 	/* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
11700c0d06caSMauro Carvalho Chehab 
11710c0d06caSMauro Carvalho Chehab }
11720c0d06caSMauro Carvalho Chehab 
cx231xx_config_tuner(struct cx231xx * dev)11730c0d06caSMauro Carvalho Chehab static void cx231xx_config_tuner(struct cx231xx *dev)
11740c0d06caSMauro Carvalho Chehab {
11750c0d06caSMauro Carvalho Chehab 	struct tuner_setup tun_setup;
11760c0d06caSMauro Carvalho Chehab 	struct v4l2_frequency f;
11770c0d06caSMauro Carvalho Chehab 
11780c0d06caSMauro Carvalho Chehab 	if (dev->tuner_type == TUNER_ABSENT)
11790c0d06caSMauro Carvalho Chehab 		return;
11800c0d06caSMauro Carvalho Chehab 
11810c0d06caSMauro Carvalho Chehab 	tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
11820c0d06caSMauro Carvalho Chehab 	tun_setup.type = dev->tuner_type;
11830c0d06caSMauro Carvalho Chehab 	tun_setup.addr = dev->tuner_addr;
11840c0d06caSMauro Carvalho Chehab 	tun_setup.tuner_callback = cx231xx_tuner_callback;
11850c0d06caSMauro Carvalho Chehab 
11860c0d06caSMauro Carvalho Chehab 	tuner_call(dev, tuner, s_type_addr, &tun_setup);
11870c0d06caSMauro Carvalho Chehab 
11880c0d06caSMauro Carvalho Chehab #if 0
11890c0d06caSMauro Carvalho Chehab 	if (tun_setup.type == TUNER_XC5000) {
11900c0d06caSMauro Carvalho Chehab 		static struct xc2028_ctrl ctrl = {
11910c0d06caSMauro Carvalho Chehab 			.fname = XC5000_DEFAULT_FIRMWARE,
11920c0d06caSMauro Carvalho Chehab 			.max_len = 64,
11930c0d06caSMauro Carvalho Chehab 			.demod = 0;
11940c0d06caSMauro Carvalho Chehab 		};
11950c0d06caSMauro Carvalho Chehab 		struct v4l2_priv_tun_config cfg = {
11960c0d06caSMauro Carvalho Chehab 			.tuner = dev->tuner_type,
11970c0d06caSMauro Carvalho Chehab 			.priv = &ctrl,
11980c0d06caSMauro Carvalho Chehab 		};
11990c0d06caSMauro Carvalho Chehab 		tuner_call(dev, tuner, s_config, &cfg);
12000c0d06caSMauro Carvalho Chehab 	}
12010c0d06caSMauro Carvalho Chehab #endif
12020c0d06caSMauro Carvalho Chehab 	/* configure tuner */
12030c0d06caSMauro Carvalho Chehab 	f.tuner = 0;
12040c0d06caSMauro Carvalho Chehab 	f.type = V4L2_TUNER_ANALOG_TV;
12050c0d06caSMauro Carvalho Chehab 	f.frequency = 9076;	/* just a magic number */
12060c0d06caSMauro Carvalho Chehab 	dev->ctl_freq = f.frequency;
12070c0d06caSMauro Carvalho Chehab 	call_all(dev, tuner, s_frequency, &f);
12080c0d06caSMauro Carvalho Chehab 
12090c0d06caSMauro Carvalho Chehab }
12100c0d06caSMauro Carvalho Chehab 
read_eeprom(struct cx231xx * dev,struct i2c_client * client,u8 * eedata,int len)12119c672890SMatthias Schwarzott static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
12129c672890SMatthias Schwarzott 		       u8 *eedata, int len)
1213dd2e7dd2SMatthias Schwarzott {
12149aa4d4eaSMarkus Elfring 	int ret;
1215dd2e7dd2SMatthias Schwarzott 	u8 start_offset = 0;
1216dd2e7dd2SMatthias Schwarzott 	int len_todo = len;
1217dd2e7dd2SMatthias Schwarzott 	u8 *eedata_cur = eedata;
1218dd2e7dd2SMatthias Schwarzott 	int i;
12199c672890SMatthias Schwarzott 	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
1220dd2e7dd2SMatthias Schwarzott 		.buf = &start_offset, .len = 1 };
12219c672890SMatthias Schwarzott 	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
1222dd2e7dd2SMatthias Schwarzott 
1223dd2e7dd2SMatthias Schwarzott 	/* start reading at offset 0 */
12249c672890SMatthias Schwarzott 	ret = i2c_transfer(client->adapter, &msg_write, 1);
12251f97947cSMauro Carvalho Chehab 	if (ret < 0) {
1226336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Can't read eeprom\n");
12271f97947cSMauro Carvalho Chehab 		return ret;
12281f97947cSMauro Carvalho Chehab 	}
1229dd2e7dd2SMatthias Schwarzott 
1230dd2e7dd2SMatthias Schwarzott 	while (len_todo > 0) {
1231dd2e7dd2SMatthias Schwarzott 		msg_read.len = (len_todo > 64) ? 64 : len_todo;
1232dd2e7dd2SMatthias Schwarzott 		msg_read.buf = eedata_cur;
1233dd2e7dd2SMatthias Schwarzott 
12349c672890SMatthias Schwarzott 		ret = i2c_transfer(client->adapter, &msg_read, 1);
12351f97947cSMauro Carvalho Chehab 		if (ret < 0) {
1236336fea92SMauro Carvalho Chehab 			dev_err(dev->dev, "Can't read eeprom\n");
12371f97947cSMauro Carvalho Chehab 			return ret;
12381f97947cSMauro Carvalho Chehab 		}
1239dd2e7dd2SMatthias Schwarzott 		eedata_cur += msg_read.len;
1240dd2e7dd2SMatthias Schwarzott 		len_todo -= msg_read.len;
1241dd2e7dd2SMatthias Schwarzott 	}
1242dd2e7dd2SMatthias Schwarzott 
1243dd2e7dd2SMatthias Schwarzott 	for (i = 0; i + 15 < len; i += 16)
1244336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev, "i2c eeprom %02x: %*ph\n",
1245b7085c08SMauro Carvalho Chehab 			i, 16, &eedata[i]);
1246dd2e7dd2SMatthias Schwarzott 
1247dd2e7dd2SMatthias Schwarzott 	return 0;
1248dd2e7dd2SMatthias Schwarzott }
1249dd2e7dd2SMatthias Schwarzott 
cx231xx_card_setup(struct cx231xx * dev)12500c0d06caSMauro Carvalho Chehab void cx231xx_card_setup(struct cx231xx *dev)
12510c0d06caSMauro Carvalho Chehab {
12520c0d06caSMauro Carvalho Chehab 
12530c0d06caSMauro Carvalho Chehab 	cx231xx_set_model(dev);
12540c0d06caSMauro Carvalho Chehab 
12550c0d06caSMauro Carvalho Chehab 	dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
12560c0d06caSMauro Carvalho Chehab 	if (cx231xx_boards[dev->model].tuner_addr)
12570c0d06caSMauro Carvalho Chehab 		dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
12580c0d06caSMauro Carvalho Chehab 
12590c0d06caSMauro Carvalho Chehab 	/* request some modules */
12600c0d06caSMauro Carvalho Chehab 	if (dev->board.decoder == CX231XX_AVDECODER) {
12610c0d06caSMauro Carvalho Chehab 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1262c3c3f1aeSMatthias Schwarzott 					cx231xx_get_i2c_adap(dev, I2C_0),
12630c0d06caSMauro Carvalho Chehab 					"cx25840", 0x88 >> 1, NULL);
12640c0d06caSMauro Carvalho Chehab 		if (dev->sd_cx25840 == NULL)
1265336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1266b7085c08SMauro Carvalho Chehab 				"cx25840 subdev registration failure\n");
12670c0d06caSMauro Carvalho Chehab 		cx25840_call(dev, core, load_fw);
12680c0d06caSMauro Carvalho Chehab 
12690c0d06caSMauro Carvalho Chehab 	}
12700c0d06caSMauro Carvalho Chehab 
12710c0d06caSMauro Carvalho Chehab 	/* Initialize the tuner */
12720c0d06caSMauro Carvalho Chehab 	if (dev->board.tuner_type != TUNER_ABSENT) {
1273c3c3f1aeSMatthias Schwarzott 		struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
1274c3c3f1aeSMatthias Schwarzott 						dev->board.tuner_i2c_master);
12750c0d06caSMauro Carvalho Chehab 		dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1276c3c3f1aeSMatthias Schwarzott 						    tuner_i2c,
12770c0d06caSMauro Carvalho Chehab 						    "tuner",
12780c0d06caSMauro Carvalho Chehab 						    dev->tuner_addr, NULL);
12790c0d06caSMauro Carvalho Chehab 		if (dev->sd_tuner == NULL)
1280336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
1281b7085c08SMauro Carvalho Chehab 				"tuner subdev registration failure\n");
12820c0d06caSMauro Carvalho Chehab 		else
12830c0d06caSMauro Carvalho Chehab 			cx231xx_config_tuner(dev);
12840c0d06caSMauro Carvalho Chehab 	}
1285dd2e7dd2SMatthias Schwarzott 
1286dd2e7dd2SMatthias Schwarzott 	switch (dev->model) {
1287dd2e7dd2SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
12889e49f7c3SMatthias Schwarzott 	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
1289809abdbfSOlli Salonen 	case CX231XX_BOARD_HAUPPAUGE_955Q:
1290c5bef50eSBrad Love 	case CX231XX_BOARD_HAUPPAUGE_935C:
129119fbf1baSBrad Love 	case CX231XX_BOARD_HAUPPAUGE_975:
1292dd2e7dd2SMatthias Schwarzott 		{
12937f3c2e1dSHans Verkuil 			struct eeprom {
1294dd2e7dd2SMatthias Schwarzott 				struct tveeprom tvee;
12957f3c2e1dSHans Verkuil 				u8 eeprom[256];
12969c672890SMatthias Schwarzott 				struct i2c_client client;
12977f3c2e1dSHans Verkuil 			};
12987f3c2e1dSHans Verkuil 			struct eeprom *e = kzalloc(sizeof(*e), GFP_KERNEL);
1299dd2e7dd2SMatthias Schwarzott 
13007f3c2e1dSHans Verkuil 			if (e == NULL) {
13017f3c2e1dSHans Verkuil 				dev_err(dev->dev,
13027f3c2e1dSHans Verkuil 					"failed to allocate memory to read eeprom\n");
13037f3c2e1dSHans Verkuil 				break;
13047f3c2e1dSHans Verkuil 			}
13057f3c2e1dSHans Verkuil 			e->client.adapter = cx231xx_get_i2c_adap(dev, I2C_1_MUX_1);
13067f3c2e1dSHans Verkuil 			e->client.addr = 0xa0 >> 1;
13079c672890SMatthias Schwarzott 
13087f3c2e1dSHans Verkuil 			read_eeprom(dev, &e->client, e->eeprom, sizeof(e->eeprom));
1309446aba66SMauro Carvalho Chehab 			tveeprom_hauppauge_analog(&e->tvee, e->eeprom + 0xc0);
13107f3c2e1dSHans Verkuil 			kfree(e);
1311dd2e7dd2SMatthias Schwarzott 			break;
1312dd2e7dd2SMatthias Schwarzott 		}
1313dd2e7dd2SMatthias Schwarzott 	}
1314dd2e7dd2SMatthias Schwarzott 
13150c0d06caSMauro Carvalho Chehab }
13160c0d06caSMauro Carvalho Chehab 
13170c0d06caSMauro Carvalho Chehab /*
13180c0d06caSMauro Carvalho Chehab  * cx231xx_config()
13190c0d06caSMauro Carvalho Chehab  * inits registers with sane defaults
13200c0d06caSMauro Carvalho Chehab  */
cx231xx_config(struct cx231xx * dev)13210c0d06caSMauro Carvalho Chehab int cx231xx_config(struct cx231xx *dev)
13220c0d06caSMauro Carvalho Chehab {
13230c0d06caSMauro Carvalho Chehab 	/* TBD need to add cx231xx specific code */
13240c0d06caSMauro Carvalho Chehab 
13250c0d06caSMauro Carvalho Chehab 	return 0;
13260c0d06caSMauro Carvalho Chehab }
13270c0d06caSMauro Carvalho Chehab 
13280c0d06caSMauro Carvalho Chehab /*
13290c0d06caSMauro Carvalho Chehab  * cx231xx_config_i2c()
13300c0d06caSMauro Carvalho Chehab  * configure i2c attached devices
13310c0d06caSMauro Carvalho Chehab  */
cx231xx_config_i2c(struct cx231xx * dev)13320c0d06caSMauro Carvalho Chehab void cx231xx_config_i2c(struct cx231xx *dev)
13330c0d06caSMauro Carvalho Chehab {
13340c0d06caSMauro Carvalho Chehab 	/* u32 input = INPUT(dev->video_input)->vmux; */
13350c0d06caSMauro Carvalho Chehab 
13360c0d06caSMauro Carvalho Chehab 	call_all(dev, video, s_stream, 1);
13370c0d06caSMauro Carvalho Chehab }
13380c0d06caSMauro Carvalho Chehab 
cx231xx_unregister_media_device(struct cx231xx * dev)13391d058bdcSMauro Carvalho Chehab static void cx231xx_unregister_media_device(struct cx231xx *dev)
13401d058bdcSMauro Carvalho Chehab {
13411d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
13421d058bdcSMauro Carvalho Chehab 	if (dev->media_dev) {
13431d058bdcSMauro Carvalho Chehab 		media_device_unregister(dev->media_dev);
13449832e155SJavier Martinez Canillas 		media_device_cleanup(dev->media_dev);
13451d058bdcSMauro Carvalho Chehab 		kfree(dev->media_dev);
13461d058bdcSMauro Carvalho Chehab 		dev->media_dev = NULL;
13471d058bdcSMauro Carvalho Chehab 	}
13481d058bdcSMauro Carvalho Chehab #endif
13491d058bdcSMauro Carvalho Chehab }
13501d058bdcSMauro Carvalho Chehab 
13510c0d06caSMauro Carvalho Chehab /*
13520c0d06caSMauro Carvalho Chehab  * cx231xx_realease_resources()
13530c0d06caSMauro Carvalho Chehab  * unregisters the v4l2,i2c and usb devices
13546b338c72SGeert Uytterhoeven  * called when the device gets disconnected or at module unload
13550c0d06caSMauro Carvalho Chehab */
cx231xx_release_resources(struct cx231xx * dev)13560c0d06caSMauro Carvalho Chehab void cx231xx_release_resources(struct cx231xx *dev)
13570c0d06caSMauro Carvalho Chehab {
13583c59bb47SMauro Carvalho Chehab 	cx231xx_ir_exit(dev);
13593c59bb47SMauro Carvalho Chehab 
13600c0d06caSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
13610c0d06caSMauro Carvalho Chehab 
13620c0d06caSMauro Carvalho Chehab 	cx231xx_remove_from_devlist(dev);
13630c0d06caSMauro Carvalho Chehab 
13640c0d06caSMauro Carvalho Chehab 	/* Release I2C buses */
13650c0d06caSMauro Carvalho Chehab 	cx231xx_dev_uninit(dev);
13660c0d06caSMauro Carvalho Chehab 
13670c0d06caSMauro Carvalho Chehab 	/* delete v4l2 device */
13680c0d06caSMauro Carvalho Chehab 	v4l2_device_unregister(&dev->v4l2_dev);
13690c0d06caSMauro Carvalho Chehab 
1370ab232e46SMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
1371ab232e46SMauro Carvalho Chehab 
13720c0d06caSMauro Carvalho Chehab 	usb_put_dev(dev->udev);
13730c0d06caSMauro Carvalho Chehab 
13740c0d06caSMauro Carvalho Chehab 	/* Mark device as unused */
13750c0d06caSMauro Carvalho Chehab 	clear_bit(dev->devno, &cx231xx_devused);
13760c0d06caSMauro Carvalho Chehab }
13770c0d06caSMauro Carvalho Chehab 
cx231xx_media_device_init(struct cx231xx * dev,struct usb_device * udev)13789f806795SMauro Carvalho Chehab static int cx231xx_media_device_init(struct cx231xx *dev,
13791d058bdcSMauro Carvalho Chehab 				      struct usb_device *udev)
13801d058bdcSMauro Carvalho Chehab {
13811d058bdcSMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
13821d058bdcSMauro Carvalho Chehab 	struct media_device *mdev;
13831d058bdcSMauro Carvalho Chehab 
13846cf5dad1SMauro Carvalho Chehab 	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
13851d058bdcSMauro Carvalho Chehab 	if (!mdev)
13869f806795SMauro Carvalho Chehab 		return -ENOMEM;
13871d058bdcSMauro Carvalho Chehab 
13886cf5dad1SMauro Carvalho Chehab 	media_device_usb_init(mdev, udev, dev->board.name);
13896cf5dad1SMauro Carvalho Chehab 
13901d058bdcSMauro Carvalho Chehab 	dev->media_dev = mdev;
13911d058bdcSMauro Carvalho Chehab #endif
13929f806795SMauro Carvalho Chehab 	return 0;
13931d058bdcSMauro Carvalho Chehab }
13941d058bdcSMauro Carvalho Chehab 
13950c0d06caSMauro Carvalho Chehab /*
13960c0d06caSMauro Carvalho Chehab  * cx231xx_init_dev()
13970c0d06caSMauro Carvalho Chehab  * allocates and inits the device structs, registers i2c bus and v4l device
13980c0d06caSMauro Carvalho Chehab  */
cx231xx_init_dev(struct cx231xx * dev,struct usb_device * udev,int minor)13990c0d06caSMauro Carvalho Chehab static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
14000c0d06caSMauro Carvalho Chehab 			    int minor)
14010c0d06caSMauro Carvalho Chehab {
14020c0d06caSMauro Carvalho Chehab 	int retval = -ENOMEM;
14030c0d06caSMauro Carvalho Chehab 	unsigned int maxh, maxw;
14040c0d06caSMauro Carvalho Chehab 
14050c0d06caSMauro Carvalho Chehab 	dev->udev = udev;
14060c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->lock);
14070c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->ctrl_urb_lock);
14080c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->gpio_i2c_lock);
14090c0d06caSMauro Carvalho Chehab 	mutex_init(&dev->i2c_lock);
14100c0d06caSMauro Carvalho Chehab 
14110c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->video_mode.slock);
14120c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->vbi_mode.slock);
14130c0d06caSMauro Carvalho Chehab 	spin_lock_init(&dev->sliced_cc_mode.slock);
14140c0d06caSMauro Carvalho Chehab 
14150c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->open);
14160c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_frame);
14170c0d06caSMauro Carvalho Chehab 	init_waitqueue_head(&dev->wait_stream);
14180c0d06caSMauro Carvalho Chehab 
14190c0d06caSMauro Carvalho Chehab 	dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
14200c0d06caSMauro Carvalho Chehab 	dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
14210c0d06caSMauro Carvalho Chehab 	dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
14220c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
14230c0d06caSMauro Carvalho Chehab 	dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
14240c0d06caSMauro Carvalho Chehab 
14250c0d06caSMauro Carvalho Chehab 	/* Query cx231xx to find what pcb config it is related to */
142652841e5eSMauro Carvalho Chehab 	retval = initialize_cx231xx(dev);
142752841e5eSMauro Carvalho Chehab 	if (retval < 0) {
1428336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "Failed to read PCB config\n");
142952841e5eSMauro Carvalho Chehab 		return retval;
143052841e5eSMauro Carvalho Chehab 	}
14310c0d06caSMauro Carvalho Chehab 
14320c0d06caSMauro Carvalho Chehab 	/*To workaround error number=-71 on EP0 for VideoGrabber,
14330c0d06caSMauro Carvalho Chehab 		 need set alt here.*/
14340c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
14350c0d06caSMauro Carvalho Chehab 	    dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
14360c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
14370c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
14380c0d06caSMauro Carvalho Chehab 	}
14390c0d06caSMauro Carvalho Chehab 	/* Cx231xx pre card setup */
14400c0d06caSMauro Carvalho Chehab 	cx231xx_pre_card_setup(dev);
14410c0d06caSMauro Carvalho Chehab 
1442256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1443256d013aSAlexey Khoroshilov 	if (retval) {
1444336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "error configuring device\n");
14450c0d06caSMauro Carvalho Chehab 		return -ENOMEM;
14460c0d06caSMauro Carvalho Chehab 	}
14470c0d06caSMauro Carvalho Chehab 
14480c0d06caSMauro Carvalho Chehab 	/* set default norm */
14490c0d06caSMauro Carvalho Chehab 	dev->norm = dev->board.norm;
14500c0d06caSMauro Carvalho Chehab 
14510c0d06caSMauro Carvalho Chehab 	/* register i2c bus */
1452256d013aSAlexey Khoroshilov 	retval = cx231xx_dev_init(dev);
1453256d013aSAlexey Khoroshilov 	if (retval) {
1454336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1455b7085c08SMauro Carvalho Chehab 			"%s: cx231xx_i2c_register - errCode [%d]!\n",
1456256d013aSAlexey Khoroshilov 			__func__, retval);
1457256d013aSAlexey Khoroshilov 		goto err_dev_init;
14580c0d06caSMauro Carvalho Chehab 	}
14590c0d06caSMauro Carvalho Chehab 
14600c0d06caSMauro Carvalho Chehab 	/* Do board specific init */
14610c0d06caSMauro Carvalho Chehab 	cx231xx_card_setup(dev);
14620c0d06caSMauro Carvalho Chehab 
14630c0d06caSMauro Carvalho Chehab 	/* configure the device */
14640c0d06caSMauro Carvalho Chehab 	cx231xx_config_i2c(dev);
14650c0d06caSMauro Carvalho Chehab 
14660c0d06caSMauro Carvalho Chehab 	maxw = norm_maxw(dev);
14670c0d06caSMauro Carvalho Chehab 	maxh = norm_maxh(dev);
14680c0d06caSMauro Carvalho Chehab 
14690c0d06caSMauro Carvalho Chehab 	/* set default image size */
14700c0d06caSMauro Carvalho Chehab 	dev->width = maxw;
14710c0d06caSMauro Carvalho Chehab 	dev->height = maxh;
14720c0d06caSMauro Carvalho Chehab 	dev->interlaced = 0;
14730c0d06caSMauro Carvalho Chehab 	dev->video_input = 0;
14740c0d06caSMauro Carvalho Chehab 
1475256d013aSAlexey Khoroshilov 	retval = cx231xx_config(dev);
1476256d013aSAlexey Khoroshilov 	if (retval) {
1477336fea92SMauro Carvalho Chehab 		dev_err(dev->dev, "%s: cx231xx_config - errCode [%d]!\n",
1478256d013aSAlexey Khoroshilov 			__func__, retval);
1479256d013aSAlexey Khoroshilov 		goto err_dev_init;
14800c0d06caSMauro Carvalho Chehab 	}
14810c0d06caSMauro Carvalho Chehab 
14827c617138SHans Verkuil 	/* init video dma queue */
14830c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->video_mode.vidq.active);
14840c0d06caSMauro Carvalho Chehab 
14857c617138SHans Verkuil 	/* init vbi dma queue */
14860c0d06caSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
14870c0d06caSMauro Carvalho Chehab 
14880c0d06caSMauro Carvalho Chehab 	/* Reset other chips required if they are tied up with GPIO pins */
14890c0d06caSMauro Carvalho Chehab 	cx231xx_add_into_devlist(dev);
14900c0d06caSMauro Carvalho Chehab 
14910c0d06caSMauro Carvalho Chehab 	if (dev->board.has_417) {
1492336fea92SMauro Carvalho Chehab 		dev_info(dev->dev, "attach 417 %d\n", dev->model);
14930c0d06caSMauro Carvalho Chehab 		if (cx231xx_417_register(dev) < 0) {
1494336fea92SMauro Carvalho Chehab 			dev_err(dev->dev,
14950c0d06caSMauro Carvalho Chehab 				"%s() Failed to register 417 on VID_B\n",
14960c0d06caSMauro Carvalho Chehab 				__func__);
14970c0d06caSMauro Carvalho Chehab 		}
14980c0d06caSMauro Carvalho Chehab 	}
14990c0d06caSMauro Carvalho Chehab 
15000c0d06caSMauro Carvalho Chehab 	retval = cx231xx_register_analog_devices(dev);
15011d058bdcSMauro Carvalho Chehab 	if (retval)
1502256d013aSAlexey Khoroshilov 		goto err_analog;
15030c0d06caSMauro Carvalho Chehab 
15040c0d06caSMauro Carvalho Chehab 	cx231xx_ir_init(dev);
15050c0d06caSMauro Carvalho Chehab 
15060c0d06caSMauro Carvalho Chehab 	cx231xx_init_extension(dev);
15070c0d06caSMauro Carvalho Chehab 
15080c0d06caSMauro Carvalho Chehab 	return 0;
1509256d013aSAlexey Khoroshilov err_analog:
15101d058bdcSMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
15111d058bdcSMauro Carvalho Chehab 	cx231xx_release_analog_resources(dev);
1512256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1513256d013aSAlexey Khoroshilov err_dev_init:
1514256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1515256d013aSAlexey Khoroshilov 	return retval;
15160c0d06caSMauro Carvalho Chehab }
15170c0d06caSMauro Carvalho Chehab 
15180c0d06caSMauro Carvalho Chehab #if defined(CONFIG_MODULES) && defined(MODULE)
request_module_async(struct work_struct * work)15190c0d06caSMauro Carvalho Chehab static void request_module_async(struct work_struct *work)
15200c0d06caSMauro Carvalho Chehab {
15210c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = container_of(work,
15220c0d06caSMauro Carvalho Chehab 					   struct cx231xx, request_module_wk);
15230c0d06caSMauro Carvalho Chehab 
15240c0d06caSMauro Carvalho Chehab 	if (dev->has_alsa_audio)
15250c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-alsa");
15260c0d06caSMauro Carvalho Chehab 
15270c0d06caSMauro Carvalho Chehab 	if (dev->board.has_dvb)
15280c0d06caSMauro Carvalho Chehab 		request_module("cx231xx-dvb");
15290c0d06caSMauro Carvalho Chehab 
15300c0d06caSMauro Carvalho Chehab }
15310c0d06caSMauro Carvalho Chehab 
request_modules(struct cx231xx * dev)15320c0d06caSMauro Carvalho Chehab static void request_modules(struct cx231xx *dev)
15330c0d06caSMauro Carvalho Chehab {
15340c0d06caSMauro Carvalho Chehab 	INIT_WORK(&dev->request_module_wk, request_module_async);
15350c0d06caSMauro Carvalho Chehab 	schedule_work(&dev->request_module_wk);
15360c0d06caSMauro Carvalho Chehab }
15370c0d06caSMauro Carvalho Chehab 
flush_request_modules(struct cx231xx * dev)15380c0d06caSMauro Carvalho Chehab static void flush_request_modules(struct cx231xx *dev)
15390c0d06caSMauro Carvalho Chehab {
15400b8e74c6SLinus Torvalds 	flush_work(&dev->request_module_wk);
15410c0d06caSMauro Carvalho Chehab }
15420c0d06caSMauro Carvalho Chehab #else
15430c0d06caSMauro Carvalho Chehab #define request_modules(dev)
15440c0d06caSMauro Carvalho Chehab #define flush_request_modules(dev)
15450c0d06caSMauro Carvalho Chehab #endif /* CONFIG_MODULES */
15460c0d06caSMauro Carvalho Chehab 
cx231xx_init_v4l2(struct cx231xx * dev,struct usb_device * udev,struct usb_interface * interface,int isoc_pipe)15474d2a7d35SMauro Carvalho Chehab static int cx231xx_init_v4l2(struct cx231xx *dev,
15484d2a7d35SMauro Carvalho Chehab 			     struct usb_device *udev,
15494d2a7d35SMauro Carvalho Chehab 			     struct usb_interface *interface,
15504d2a7d35SMauro Carvalho Chehab 			     int isoc_pipe)
15514d2a7d35SMauro Carvalho Chehab {
15524d2a7d35SMauro Carvalho Chehab 	struct usb_interface *uif;
15534d2a7d35SMauro Carvalho Chehab 	int i, idx;
15544d2a7d35SMauro Carvalho Chehab 
15554d2a7d35SMauro Carvalho Chehab 	/* Video Init */
15564d2a7d35SMauro Carvalho Chehab 
15574d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for video */
15584d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
15594d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1560336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1561b7085c08SMauro Carvalho Chehab 			"Video PCB interface #%d doesn't exist\n", idx);
15624d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
15634d2a7d35SMauro Carvalho Chehab 	}
15644d2a7d35SMauro Carvalho Chehab 
15654d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
15664d2a7d35SMauro Carvalho Chehab 
15670cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
15680cd273bbSJohan Hovold 		return -ENODEV;
15690cd273bbSJohan Hovold 
15704d2a7d35SMauro Carvalho Chehab 	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
15714d2a7d35SMauro Carvalho Chehab 	dev->video_mode.num_alt = uif->num_altsetting;
15724d2a7d35SMauro Carvalho Chehab 
1573336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1574b7085c08SMauro Carvalho Chehab 		 "video EndPoint Addr 0x%x, Alternate settings: %i\n",
15754d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.end_point_addr,
15764d2a7d35SMauro Carvalho Chehab 		 dev->video_mode.num_alt);
15774d2a7d35SMauro Carvalho Chehab 
15784d2a7d35SMauro Carvalho Chehab 	dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
1579ed0e3729SMauro Carvalho Chehab 	if (dev->video_mode.alt_max_pkt_size == NULL)
15804d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
15814d2a7d35SMauro Carvalho Chehab 
15824d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->video_mode.num_alt; i++) {
15830cd273bbSJohan Hovold 		u16 tmp;
15840cd273bbSJohan Hovold 
15850cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
15860cd273bbSJohan Hovold 			return -ENODEV;
15870cd273bbSJohan Hovold 
15880cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
15894d2a7d35SMauro Carvalho Chehab 		dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1590336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1591b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
15924d2a7d35SMauro Carvalho Chehab 			dev->video_mode.alt_max_pkt_size[i]);
15934d2a7d35SMauro Carvalho Chehab 	}
15944d2a7d35SMauro Carvalho Chehab 
15954d2a7d35SMauro Carvalho Chehab 	/* VBI Init */
15964d2a7d35SMauro Carvalho Chehab 
15974d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
15984d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1599336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1600b7085c08SMauro Carvalho Chehab 			"VBI PCB interface #%d doesn't exist\n", idx);
16014d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
16024d2a7d35SMauro Carvalho Chehab 	}
16034d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
16044d2a7d35SMauro Carvalho Chehab 
16050cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
16060cd273bbSJohan Hovold 		return -ENODEV;
16070cd273bbSJohan Hovold 
16084d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.end_point_addr =
16094d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
16104d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
16114d2a7d35SMauro Carvalho Chehab 
16124d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.num_alt = uif->num_altsetting;
1613336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1614b7085c08SMauro Carvalho Chehab 		 "VBI EndPoint Addr 0x%x, Alternate settings: %i\n",
16154d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.end_point_addr,
16164d2a7d35SMauro Carvalho Chehab 		 dev->vbi_mode.num_alt);
16174d2a7d35SMauro Carvalho Chehab 
16184d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for vbi */
16194d2a7d35SMauro Carvalho Chehab 	dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
1620ed0e3729SMauro Carvalho Chehab 	if (dev->vbi_mode.alt_max_pkt_size == NULL)
16214d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
16224d2a7d35SMauro Carvalho Chehab 
16234d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
16240cd273bbSJohan Hovold 		u16 tmp;
16250cd273bbSJohan Hovold 
16260cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
16270cd273bbSJohan Hovold 			return -ENODEV;
16280cd273bbSJohan Hovold 
16290cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
16304d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
16314d2a7d35SMauro Carvalho Chehab 		dev->vbi_mode.alt_max_pkt_size[i] =
16324d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1633336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1634b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
16354d2a7d35SMauro Carvalho Chehab 			dev->vbi_mode.alt_max_pkt_size[i]);
16364d2a7d35SMauro Carvalho Chehab 	}
16374d2a7d35SMauro Carvalho Chehab 
16384d2a7d35SMauro Carvalho Chehab 	/* Sliced CC VBI init */
16394d2a7d35SMauro Carvalho Chehab 
16404d2a7d35SMauro Carvalho Chehab 	/* compute alternate max packet sizes for sliced CC */
16414d2a7d35SMauro Carvalho Chehab 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
16424d2a7d35SMauro Carvalho Chehab 	if (idx >= dev->max_iad_interface_count) {
1643336fea92SMauro Carvalho Chehab 		dev_err(dev->dev,
1644b7085c08SMauro Carvalho Chehab 			"Sliced CC PCB interface #%d doesn't exist\n", idx);
16454d2a7d35SMauro Carvalho Chehab 		return -ENODEV;
16464d2a7d35SMauro Carvalho Chehab 	}
16474d2a7d35SMauro Carvalho Chehab 	uif = udev->actconfig->interface[idx];
16484d2a7d35SMauro Carvalho Chehab 
16490cd273bbSJohan Hovold 	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
16500cd273bbSJohan Hovold 		return -ENODEV;
16510cd273bbSJohan Hovold 
16524d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.end_point_addr =
16534d2a7d35SMauro Carvalho Chehab 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
16544d2a7d35SMauro Carvalho Chehab 			bEndpointAddress;
16554d2a7d35SMauro Carvalho Chehab 
16564d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
1657336fea92SMauro Carvalho Chehab 	dev_info(dev->dev,
1658b7085c08SMauro Carvalho Chehab 		 "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
16594d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.end_point_addr,
16604d2a7d35SMauro Carvalho Chehab 		 dev->sliced_cc_mode.num_alt);
16614d2a7d35SMauro Carvalho Chehab 	dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
1662ed0e3729SMauro Carvalho Chehab 	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
16634d2a7d35SMauro Carvalho Chehab 		return -ENOMEM;
16644d2a7d35SMauro Carvalho Chehab 
16654d2a7d35SMauro Carvalho Chehab 	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
16660cd273bbSJohan Hovold 		u16 tmp;
16670cd273bbSJohan Hovold 
16680cd273bbSJohan Hovold 		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
16690cd273bbSJohan Hovold 			return -ENODEV;
16700cd273bbSJohan Hovold 
16710cd273bbSJohan Hovold 		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
16724d2a7d35SMauro Carvalho Chehab 				desc.wMaxPacketSize);
16734d2a7d35SMauro Carvalho Chehab 		dev->sliced_cc_mode.alt_max_pkt_size[i] =
16744d2a7d35SMauro Carvalho Chehab 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1675336fea92SMauro Carvalho Chehab 		dev_dbg(dev->dev,
1676b7085c08SMauro Carvalho Chehab 			"Alternate setting %i, max size= %i\n", i,
16774d2a7d35SMauro Carvalho Chehab 			dev->sliced_cc_mode.alt_max_pkt_size[i]);
16784d2a7d35SMauro Carvalho Chehab 	}
16794d2a7d35SMauro Carvalho Chehab 
16804d2a7d35SMauro Carvalho Chehab 	return 0;
16814d2a7d35SMauro Carvalho Chehab }
16824d2a7d35SMauro Carvalho Chehab 
16830c0d06caSMauro Carvalho Chehab /*
16840c0d06caSMauro Carvalho Chehab  * cx231xx_usb_probe()
16850c0d06caSMauro Carvalho Chehab  * checks for supported devices
16860c0d06caSMauro Carvalho Chehab  */
cx231xx_usb_probe(struct usb_interface * interface,const struct usb_device_id * id)16870c0d06caSMauro Carvalho Chehab static int cx231xx_usb_probe(struct usb_interface *interface,
16880c0d06caSMauro Carvalho Chehab 			     const struct usb_device_id *id)
16890c0d06caSMauro Carvalho Chehab {
16900c0d06caSMauro Carvalho Chehab 	struct usb_device *udev;
1691336fea92SMauro Carvalho Chehab 	struct device *d = &interface->dev;
16920c0d06caSMauro Carvalho Chehab 	struct usb_interface *uif;
16930c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev = NULL;
16940c0d06caSMauro Carvalho Chehab 	int retval = -ENODEV;
16950c0d06caSMauro Carvalho Chehab 	int nr = 0, ifnum;
16960c0d06caSMauro Carvalho Chehab 	int i, isoc_pipe = 0;
16970c0d06caSMauro Carvalho Chehab 	char *speed;
1698dcb78ac7SMauro Carvalho Chehab 	u8 idx;
16990c0d06caSMauro Carvalho Chehab 	struct usb_interface_assoc_descriptor *assoc_desc;
17000c0d06caSMauro Carvalho Chehab 
17010c0d06caSMauro Carvalho Chehab 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
17020c0d06caSMauro Carvalho Chehab 
17030c0d06caSMauro Carvalho Chehab 	/*
17040c0d06caSMauro Carvalho Chehab 	 * Interface number 0 - IR interface (handled by mceusb driver)
17050c0d06caSMauro Carvalho Chehab 	 * Interface number 1 - AV interface (handled by this driver)
17060c0d06caSMauro Carvalho Chehab 	 */
17070c0d06caSMauro Carvalho Chehab 	if (ifnum != 1)
17080c0d06caSMauro Carvalho Chehab 		return -ENODEV;
17090c0d06caSMauro Carvalho Chehab 
17100c0d06caSMauro Carvalho Chehab 	/* Check to see next free device and mark as used */
17110c0d06caSMauro Carvalho Chehab 	do {
17120c0d06caSMauro Carvalho Chehab 		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
17130c0d06caSMauro Carvalho Chehab 		if (nr >= CX231XX_MAXBOARDS) {
17140c0d06caSMauro Carvalho Chehab 			/* No free device slots */
1715336fea92SMauro Carvalho Chehab 			dev_err(d,
1716b7085c08SMauro Carvalho Chehab 				"Supports only %i devices.\n",
1717b7085c08SMauro Carvalho Chehab 				CX231XX_MAXBOARDS);
17180c0d06caSMauro Carvalho Chehab 			return -ENOMEM;
17190c0d06caSMauro Carvalho Chehab 		}
17200c0d06caSMauro Carvalho Chehab 	} while (test_and_set_bit(nr, &cx231xx_devused));
17210c0d06caSMauro Carvalho Chehab 
17225eeb3014SAlexey Khoroshilov 	udev = usb_get_dev(interface_to_usbdev(interface));
17235eeb3014SAlexey Khoroshilov 
17240c0d06caSMauro Carvalho Chehab 	/* allocate memory for our device state and initialize it */
1725184a8278SMauro Carvalho Chehab 	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
17260c0d06caSMauro Carvalho Chehab 	if (dev == NULL) {
17275eeb3014SAlexey Khoroshilov 		retval = -ENOMEM;
17285eeb3014SAlexey Khoroshilov 		goto err_if;
17290c0d06caSMauro Carvalho Chehab 	}
17300c0d06caSMauro Carvalho Chehab 
17310c0d06caSMauro Carvalho Chehab 	snprintf(dev->name, 29, "cx231xx #%d", nr);
17320c0d06caSMauro Carvalho Chehab 	dev->devno = nr;
17330c0d06caSMauro Carvalho Chehab 	dev->model = id->driver_info;
17340c0d06caSMauro Carvalho Chehab 	dev->video_mode.alt = -1;
1735336fea92SMauro Carvalho Chehab 	dev->dev = d;
17360c0d06caSMauro Carvalho Chehab 
17371d058bdcSMauro Carvalho Chehab 	cx231xx_set_model(dev);
17381d058bdcSMauro Carvalho Chehab 
17390c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
17400c0d06caSMauro Carvalho Chehab 	/* reset gpio dir and value */
17410c0d06caSMauro Carvalho Chehab 	dev->gpio_dir = 0;
17420c0d06caSMauro Carvalho Chehab 	dev->gpio_val = 0;
17430c0d06caSMauro Carvalho Chehab 	dev->xc_fw_load_done = 0;
17440c0d06caSMauro Carvalho Chehab 	dev->has_alsa_audio = 1;
17450c0d06caSMauro Carvalho Chehab 	dev->power_mode = -1;
17460c0d06caSMauro Carvalho Chehab 	atomic_set(&dev->devlist_count, 0);
17470c0d06caSMauro Carvalho Chehab 
17480c0d06caSMauro Carvalho Chehab 	/* 0 - vbi ; 1 -sliced cc mode */
17490c0d06caSMauro Carvalho Chehab 	dev->vbi_or_sliced_cc_mode = 0;
17500c0d06caSMauro Carvalho Chehab 
17510c0d06caSMauro Carvalho Chehab 	/* get maximum no.of IAD interfaces */
1752139d2882SMauro Carvalho Chehab 	dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
17530c0d06caSMauro Carvalho Chehab 
17540c0d06caSMauro Carvalho Chehab 	/* init CIR module TBD */
17550c0d06caSMauro Carvalho Chehab 
17560c0d06caSMauro Carvalho Chehab 	/*mode_tv: digital=1 or analog=0*/
17570c0d06caSMauro Carvalho Chehab 	dev->mode_tv = 0;
17580c0d06caSMauro Carvalho Chehab 
17590c0d06caSMauro Carvalho Chehab 	dev->USE_ISO = transfer_mode;
17600c0d06caSMauro Carvalho Chehab 
17610c0d06caSMauro Carvalho Chehab 	switch (udev->speed) {
17620c0d06caSMauro Carvalho Chehab 	case USB_SPEED_LOW:
17630c0d06caSMauro Carvalho Chehab 		speed = "1.5";
17640c0d06caSMauro Carvalho Chehab 		break;
17650c0d06caSMauro Carvalho Chehab 	case USB_SPEED_UNKNOWN:
17660c0d06caSMauro Carvalho Chehab 	case USB_SPEED_FULL:
17670c0d06caSMauro Carvalho Chehab 		speed = "12";
17680c0d06caSMauro Carvalho Chehab 		break;
17690c0d06caSMauro Carvalho Chehab 	case USB_SPEED_HIGH:
17700c0d06caSMauro Carvalho Chehab 		speed = "480";
17710c0d06caSMauro Carvalho Chehab 		break;
17720c0d06caSMauro Carvalho Chehab 	default:
17730c0d06caSMauro Carvalho Chehab 		speed = "unknown";
17740c0d06caSMauro Carvalho Chehab 	}
17750c0d06caSMauro Carvalho Chehab 
1776336fea92SMauro Carvalho Chehab 	dev_info(d,
1777b7085c08SMauro Carvalho Chehab 		 "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
17780c0d06caSMauro Carvalho Chehab 		 udev->manufacturer ? udev->manufacturer : "",
17790c0d06caSMauro Carvalho Chehab 		 udev->product ? udev->product : "",
17800c0d06caSMauro Carvalho Chehab 		 speed,
17810c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idVendor),
17820c0d06caSMauro Carvalho Chehab 		 le16_to_cpu(udev->descriptor.idProduct),
17830c0d06caSMauro Carvalho Chehab 		 dev->max_iad_interface_count);
17840c0d06caSMauro Carvalho Chehab 
17850c0d06caSMauro Carvalho Chehab 	/* increment interface count */
17860c0d06caSMauro Carvalho Chehab 	dev->interface_count++;
17870c0d06caSMauro Carvalho Chehab 
17880c0d06caSMauro Carvalho Chehab 	/* get device number */
17890c0d06caSMauro Carvalho Chehab 	nr = dev->devno;
17900c0d06caSMauro Carvalho Chehab 
17910c0d06caSMauro Carvalho Chehab 	assoc_desc = udev->actconfig->intf_assoc[0];
17926c3b047fSJohan Hovold 	if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) {
1793336fea92SMauro Carvalho Chehab 		dev_err(d, "Not found matching IAD interface\n");
1794256d013aSAlexey Khoroshilov 		retval = -ENODEV;
1795256d013aSAlexey Khoroshilov 		goto err_if;
17960c0d06caSMauro Carvalho Chehab 	}
17970c0d06caSMauro Carvalho Chehab 
1798336fea92SMauro Carvalho Chehab 	dev_dbg(d, "registering interface %d\n", ifnum);
17990c0d06caSMauro Carvalho Chehab 
18000c0d06caSMauro Carvalho Chehab 	/* save our data pointer in this interface device */
18010c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, dev);
18020c0d06caSMauro Carvalho Chehab 
18039832e155SJavier Martinez Canillas 	/* Initialize the media controller */
18049f806795SMauro Carvalho Chehab 	retval = cx231xx_media_device_init(dev, udev);
18059f806795SMauro Carvalho Chehab 	if (retval) {
18069f806795SMauro Carvalho Chehab 		dev_err(d, "cx231xx_media_device_init failed\n");
18079f806795SMauro Carvalho Chehab 		goto err_media_init;
18089f806795SMauro Carvalho Chehab 	}
18091d058bdcSMauro Carvalho Chehab 
18100c0d06caSMauro Carvalho Chehab 	/* Create v4l2 device */
181163ba8c75SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
18121d058bdcSMauro Carvalho Chehab 	dev->v4l2_dev.mdev = dev->media_dev;
181363ba8c75SMauro Carvalho Chehab #endif
18140c0d06caSMauro Carvalho Chehab 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
18150c0d06caSMauro Carvalho Chehab 	if (retval) {
1816336fea92SMauro Carvalho Chehab 		dev_err(d, "v4l2_device_register failed\n");
1817256d013aSAlexey Khoroshilov 		goto err_v4l2;
18180c0d06caSMauro Carvalho Chehab 	}
18194d2a7d35SMauro Carvalho Chehab 
18200c0d06caSMauro Carvalho Chehab 	/* allocate device struct */
18210c0d06caSMauro Carvalho Chehab 	retval = cx231xx_init_dev(dev, udev, nr);
1822256d013aSAlexey Khoroshilov 	if (retval)
1823256d013aSAlexey Khoroshilov 		goto err_init;
18240c0d06caSMauro Carvalho Chehab 
18254d2a7d35SMauro Carvalho Chehab 	retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
18264d2a7d35SMauro Carvalho Chehab 	if (retval)
1827dcb78ac7SMauro Carvalho Chehab 		goto err_init;
18280c0d06caSMauro Carvalho Chehab 
18290c0d06caSMauro Carvalho Chehab 	if (dev->current_pcb_config.ts1_source != 0xff) {
18300c0d06caSMauro Carvalho Chehab 		/* compute alternate max packet sizes for TS1 */
1831dcb78ac7SMauro Carvalho Chehab 		idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
1832dcb78ac7SMauro Carvalho Chehab 		if (idx >= dev->max_iad_interface_count) {
1833336fea92SMauro Carvalho Chehab 			dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
1834336fea92SMauro Carvalho Chehab 				idx);
1835dcb78ac7SMauro Carvalho Chehab 			retval = -ENODEV;
1836184a8278SMauro Carvalho Chehab 			goto err_video_alt;
1837dcb78ac7SMauro Carvalho Chehab 		}
1838dcb78ac7SMauro Carvalho Chehab 		uif = udev->actconfig->interface[idx];
18390c0d06caSMauro Carvalho Chehab 
18400cd273bbSJohan Hovold 		if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
18410cd273bbSJohan Hovold 			retval = -ENODEV;
18420cd273bbSJohan Hovold 			goto err_video_alt;
18430cd273bbSJohan Hovold 		}
18440cd273bbSJohan Hovold 
18450c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.end_point_addr =
184669a11a32SHans Verkuil 		    uif->altsetting[0].endpoint[isoc_pipe].
184769a11a32SHans Verkuil 				desc.bEndpointAddress;
18480c0d06caSMauro Carvalho Chehab 
18490c0d06caSMauro Carvalho Chehab 		dev->ts1_mode.num_alt = uif->num_altsetting;
1850336fea92SMauro Carvalho Chehab 		dev_info(d,
1851b7085c08SMauro Carvalho Chehab 			 "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
18520c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.end_point_addr,
18530c0d06caSMauro Carvalho Chehab 			 dev->ts1_mode.num_alt);
18540c0d06caSMauro Carvalho Chehab 
1855184a8278SMauro Carvalho Chehab 		dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
18560c0d06caSMauro Carvalho Chehab 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
1857256d013aSAlexey Khoroshilov 			retval = -ENOMEM;
1858184a8278SMauro Carvalho Chehab 			goto err_video_alt;
18590c0d06caSMauro Carvalho Chehab 		}
18600c0d06caSMauro Carvalho Chehab 
18610c0d06caSMauro Carvalho Chehab 		for (i = 0; i < dev->ts1_mode.num_alt; i++) {
18620cd273bbSJohan Hovold 			u16 tmp;
18630cd273bbSJohan Hovold 
18640cd273bbSJohan Hovold 			if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
18650cd273bbSJohan Hovold 				retval = -ENODEV;
18660cd273bbSJohan Hovold 				goto err_video_alt;
18670cd273bbSJohan Hovold 			}
18680cd273bbSJohan Hovold 
18690cd273bbSJohan Hovold 			tmp = le16_to_cpu(uif->altsetting[i].
18700c0d06caSMauro Carvalho Chehab 						endpoint[isoc_pipe].desc.
18710c0d06caSMauro Carvalho Chehab 						wMaxPacketSize);
18720c0d06caSMauro Carvalho Chehab 			dev->ts1_mode.alt_max_pkt_size[i] =
18730c0d06caSMauro Carvalho Chehab 			    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1874336fea92SMauro Carvalho Chehab 			dev_dbg(d, "Alternate setting %i, max size= %i\n",
1875336fea92SMauro Carvalho Chehab 				i, dev->ts1_mode.alt_max_pkt_size[i]);
18760c0d06caSMauro Carvalho Chehab 		}
18770c0d06caSMauro Carvalho Chehab 	}
18780c0d06caSMauro Carvalho Chehab 
18790c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
18800c0d06caSMauro Carvalho Chehab 		cx231xx_enable_OSC(dev);
18810c0d06caSMauro Carvalho Chehab 		cx231xx_reset_out(dev);
18820c0d06caSMauro Carvalho Chehab 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
18830c0d06caSMauro Carvalho Chehab 	}
18840c0d06caSMauro Carvalho Chehab 
18850c0d06caSMauro Carvalho Chehab 	if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
18860c0d06caSMauro Carvalho Chehab 		cx231xx_sleep_s5h1432(dev);
18870c0d06caSMauro Carvalho Chehab 
18880c0d06caSMauro Carvalho Chehab 	/* load other modules required */
18890c0d06caSMauro Carvalho Chehab 	request_modules(dev);
18900c0d06caSMauro Carvalho Chehab 
18919832e155SJavier Martinez Canillas #ifdef CONFIG_MEDIA_CONTROLLER
18926168309aSMauro Carvalho Chehab 	/* Init entities at the Media Controller */
18936168309aSMauro Carvalho Chehab 	cx231xx_v4l2_create_entities(dev);
18946168309aSMauro Carvalho Chehab 
189508f49200SMauro Carvalho Chehab 	retval = v4l2_mc_create_media_graph(dev->media_dev);
189608f49200SMauro Carvalho Chehab 	if (!retval)
18979832e155SJavier Martinez Canillas 		retval = media_device_register(dev->media_dev);
18989832e155SJavier Martinez Canillas #endif
18999832e155SJavier Martinez Canillas 	if (retval < 0)
19009832e155SJavier Martinez Canillas 		cx231xx_release_resources(dev);
1901ab232e46SMauro Carvalho Chehab 	return retval;
19029832e155SJavier Martinez Canillas 
1903256d013aSAlexey Khoroshilov err_video_alt:
1904256d013aSAlexey Khoroshilov 	/* cx231xx_uninit_dev: */
1905256d013aSAlexey Khoroshilov 	cx231xx_close_extension(dev);
1906256d013aSAlexey Khoroshilov 	cx231xx_ir_exit(dev);
1907256d013aSAlexey Khoroshilov 	cx231xx_release_analog_resources(dev);
1908256d013aSAlexey Khoroshilov 	cx231xx_417_unregister(dev);
1909256d013aSAlexey Khoroshilov 	cx231xx_remove_from_devlist(dev);
1910256d013aSAlexey Khoroshilov 	cx231xx_dev_uninit(dev);
1911256d013aSAlexey Khoroshilov err_init:
1912256d013aSAlexey Khoroshilov 	v4l2_device_unregister(&dev->v4l2_dev);
1913256d013aSAlexey Khoroshilov err_v4l2:
19149f806795SMauro Carvalho Chehab 	cx231xx_unregister_media_device(dev);
19159f806795SMauro Carvalho Chehab err_media_init:
1916256d013aSAlexey Khoroshilov 	usb_set_intfdata(interface, NULL);
1917256d013aSAlexey Khoroshilov err_if:
1918256d013aSAlexey Khoroshilov 	usb_put_dev(udev);
1919b5603a94SMauro Carvalho Chehab 	clear_bit(nr, &cx231xx_devused);
1920256d013aSAlexey Khoroshilov 	return retval;
19210c0d06caSMauro Carvalho Chehab }
19220c0d06caSMauro Carvalho Chehab 
19230c0d06caSMauro Carvalho Chehab /*
19240c0d06caSMauro Carvalho Chehab  * cx231xx_usb_disconnect()
19256b338c72SGeert Uytterhoeven  * called when the device gets disconnected
19260c0d06caSMauro Carvalho Chehab  * video device will be unregistered on v4l2_close in case it is still open
19270c0d06caSMauro Carvalho Chehab  */
cx231xx_usb_disconnect(struct usb_interface * interface)19280c0d06caSMauro Carvalho Chehab static void cx231xx_usb_disconnect(struct usb_interface *interface)
19290c0d06caSMauro Carvalho Chehab {
19300c0d06caSMauro Carvalho Chehab 	struct cx231xx *dev;
19310c0d06caSMauro Carvalho Chehab 
19320c0d06caSMauro Carvalho Chehab 	dev = usb_get_intfdata(interface);
19330c0d06caSMauro Carvalho Chehab 	usb_set_intfdata(interface, NULL);
19340c0d06caSMauro Carvalho Chehab 
19350c0d06caSMauro Carvalho Chehab 	if (!dev)
19360c0d06caSMauro Carvalho Chehab 		return;
19370c0d06caSMauro Carvalho Chehab 
19380c0d06caSMauro Carvalho Chehab 	if (!dev->udev)
19390c0d06caSMauro Carvalho Chehab 		return;
19400c0d06caSMauro Carvalho Chehab 
19410c0d06caSMauro Carvalho Chehab 	dev->state |= DEV_DISCONNECTED;
19420c0d06caSMauro Carvalho Chehab 
19430c0d06caSMauro Carvalho Chehab 	flush_request_modules(dev);
19440c0d06caSMauro Carvalho Chehab 
19450c0d06caSMauro Carvalho Chehab 	/* wait until all current v4l2 io is finished then deallocate
19460c0d06caSMauro Carvalho Chehab 	   resources */
19470c0d06caSMauro Carvalho Chehab 	mutex_lock(&dev->lock);
19480c0d06caSMauro Carvalho Chehab 
19490c0d06caSMauro Carvalho Chehab 	wake_up_interruptible_all(&dev->open);
19500c0d06caSMauro Carvalho Chehab 
19510c0d06caSMauro Carvalho Chehab 	if (dev->users) {
1952336fea92SMauro Carvalho Chehab 		dev_warn(dev->dev,
1953b7085c08SMauro Carvalho Chehab 			 "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
195460acf187SHans Verkuil 			 video_device_node_name(&dev->vdev));
19550c0d06caSMauro Carvalho Chehab 
19560c0d06caSMauro Carvalho Chehab 		/* Even having users, it is safe to remove the RC i2c driver */
19570c0d06caSMauro Carvalho Chehab 		cx231xx_ir_exit(dev);
19580c0d06caSMauro Carvalho Chehab 
19590c0d06caSMauro Carvalho Chehab 		if (dev->USE_ISO)
19600c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_isoc(dev);
19610c0d06caSMauro Carvalho Chehab 		else
19620c0d06caSMauro Carvalho Chehab 			cx231xx_uninit_bulk(dev);
19630c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_frame);
19640c0d06caSMauro Carvalho Chehab 		wake_up_interruptible(&dev->wait_stream);
19650c0d06caSMauro Carvalho Chehab 	} else {
19660c0d06caSMauro Carvalho Chehab 	}
19670c0d06caSMauro Carvalho Chehab 
19680c0d06caSMauro Carvalho Chehab 	cx231xx_close_extension(dev);
19690c0d06caSMauro Carvalho Chehab 
19700c0d06caSMauro Carvalho Chehab 	mutex_unlock(&dev->lock);
19710c0d06caSMauro Carvalho Chehab 
19720c0d06caSMauro Carvalho Chehab 	if (!dev->users)
19730c0d06caSMauro Carvalho Chehab 		cx231xx_release_resources(dev);
19740c0d06caSMauro Carvalho Chehab }
19750c0d06caSMauro Carvalho Chehab 
19760c0d06caSMauro Carvalho Chehab static struct usb_driver cx231xx_usb_driver = {
19770c0d06caSMauro Carvalho Chehab 	.name = "cx231xx",
19780c0d06caSMauro Carvalho Chehab 	.probe = cx231xx_usb_probe,
19790c0d06caSMauro Carvalho Chehab 	.disconnect = cx231xx_usb_disconnect,
19800c0d06caSMauro Carvalho Chehab 	.id_table = cx231xx_id_table,
19810c0d06caSMauro Carvalho Chehab };
19820c0d06caSMauro Carvalho Chehab 
19830c0d06caSMauro Carvalho Chehab module_usb_driver(cx231xx_usb_driver);
1984