xref: /linux/drivers/media/usb/em28xx/em28xx-dvb.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1f22e9e71SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
2f22e9e71SMauro Carvalho Chehab //
3f22e9e71SMauro Carvalho Chehab // DVB device driver for em28xx
4f22e9e71SMauro Carvalho Chehab //
532590819SMauro Carvalho Chehab // (c) 2008-2011 Mauro Carvalho Chehab <mchehab@kernel.org>
6f22e9e71SMauro Carvalho Chehab //
7f22e9e71SMauro Carvalho Chehab // (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
8f22e9e71SMauro Carvalho Chehab //	- Fixes for the driver to properly work with HVR-950
9f22e9e71SMauro Carvalho Chehab //	- Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
10f22e9e71SMauro Carvalho Chehab //	- Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
11f22e9e71SMauro Carvalho Chehab //
12f22e9e71SMauro Carvalho Chehab // (c) 2008 Aidan Thornton <makosoft@googlemail.com>
13f22e9e71SMauro Carvalho Chehab //
14f22e9e71SMauro Carvalho Chehab // (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
15f22e9e71SMauro Carvalho Chehab //
16f22e9e71SMauro Carvalho Chehab // Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
17f22e9e71SMauro Carvalho Chehab //	(c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
18f22e9e71SMauro Carvalho Chehab //	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
193aefb79aSMauro Carvalho Chehab 
208314d402SMauro Carvalho Chehab #include "em28xx.h"
218314d402SMauro Carvalho Chehab 
223aefb79aSMauro Carvalho Chehab #include <linux/kernel.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
243aefb79aSMauro Carvalho Chehab #include <linux/usb.h>
253aefb79aSMauro Carvalho Chehab 
263aefb79aSMauro Carvalho Chehab #include <media/v4l2-common.h>
27fada1935SMauro Carvalho Chehab #include <media/dvb_demux.h>
28fada1935SMauro Carvalho Chehab #include <media/dvb_net.h>
29fada1935SMauro Carvalho Chehab #include <media/dmxdev.h>
30d7de5d8fSFranklin Meng #include <media/tuner.h>
31d7de5d8fSFranklin Meng #include "tuner-simple.h"
321e8f31f3SAntti Palosaari #include <linux/gpio.h>
333aefb79aSMauro Carvalho Chehab 
343aefb79aSMauro Carvalho Chehab #include "lgdt330x.h"
357e48b30aSJarod Wilson #include "lgdt3305.h"
361586342eSKevin Cheng #include "lgdt3306a.h"
377e6388a1SAidan Thornton #include "zl10353.h"
386e7b9ea0SRobert Krakora #include "s5h1409.h"
398c47311dSAlberto Mardegan #include "mt2060.h"
404fb202a8SDevin Heitmueller #include "mt352.h"
414fb202a8SDevin Heitmueller #include "mt352_priv.h" /* FIXME */
42285eb1a4SAntti Palosaari #include "tda1002x.h"
4338b2df95SDevin Heitmueller #include "drx39xyj/drx39xxj.h"
447e48b30aSJarod Wilson #include "tda18271.h"
45ca3dfd6aSMauro Carvalho Chehab #include "s921.h"
4675e2b869SDevin Heitmueller #include "drxd.h"
47d6a5f921SAntti Palosaari #include "cxd2820r.h"
48fec528b7SMauro Carvalho Chehab #include "tda18271c2dd.h"
49fec528b7SMauro Carvalho Chehab #include "drxk.h"
5036588715SAntti Palosaari #include "tda10071.h"
5102bc1f55SMauro Carvalho Chehab #include "tda18212.h"
5236588715SAntti Palosaari #include "a8293.h"
531985f6fbSAivar Päkk #include "qt1010.h"
544159d01bSMauro Carvalho Chehab #include "mb86a20s.h"
55ec573362SAntti Palosaari #include "m88ds3103.h"
5683c1b6ceSAntti Palosaari #include "ts2020.h"
5719229240SAntti Palosaari #include "si2168.h"
5819229240SAntti Palosaari #include "si2157.h"
59ab4d1452SSatoshi Nagahama #include "tc90522.h"
60ab4d1452SSatoshi Nagahama #include "qm1d1c0042.h"
612e74a01fSBrad Love #include "mxl692.h"
623aefb79aSMauro Carvalho Chehab 
6332590819SMauro Carvalho Chehab MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
64f22e9e71SMauro Carvalho Chehab MODULE_LICENSE("GPL v2");
65d8992b09SMauro Carvalho Chehab MODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface");
66d8992b09SMauro Carvalho Chehab MODULE_VERSION(EM28XX_VERSION);
67d8992b09SMauro Carvalho Chehab 
683aefb79aSMauro Carvalho Chehab static unsigned int debug;
693aefb79aSMauro Carvalho Chehab module_param(debug, int, 0644);
703aefb79aSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
713aefb79aSMauro Carvalho Chehab 
723aefb79aSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
733aefb79aSMauro Carvalho Chehab 
743aefb79aSMauro Carvalho Chehab #define dprintk(level, fmt, arg...) do {				\
753aefb79aSMauro Carvalho Chehab 	if (debug >= level)						\
7629b05e22SMauro Carvalho Chehab 		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
77ce8591ffSMauro Carvalho Chehab 			   "dvb: " fmt, ## arg);			\
783aefb79aSMauro Carvalho Chehab } while (0)
793aefb79aSMauro Carvalho Chehab 
803421b778SAidan Thornton struct em28xx_dvb {
81f71095beSAntti Palosaari 	struct dvb_frontend        *fe[2];
823421b778SAidan Thornton 
833421b778SAidan Thornton 	/* feed count management */
843421b778SAidan Thornton 	struct mutex               lock;
853421b778SAidan Thornton 	int                        nfeeds;
863421b778SAidan Thornton 
873421b778SAidan Thornton 	/* general boilerplate stuff */
883421b778SAidan Thornton 	struct dvb_adapter         adapter;
893421b778SAidan Thornton 	struct dvb_demux           demux;
903421b778SAidan Thornton 	struct dmxdev              dmxdev;
913421b778SAidan Thornton 	struct dmx_frontend        fe_hw;
923421b778SAidan Thornton 	struct dmx_frontend        fe_mem;
933421b778SAidan Thornton 	struct dvb_net             net;
94fec528b7SMauro Carvalho Chehab 
95c4c3a3d3SMauro Carvalho Chehab 	/* Due to DRX-K - probably need changes */
96fe8d54f0SMauro Carvalho Chehab 	int (*gate_ctrl)(struct dvb_frontend *fe, int gate);
97fec528b7SMauro Carvalho Chehab 	struct semaphore      pll_mutex;
98c4c3a3d3SMauro Carvalho Chehab 	bool			dont_attach_fe1;
9913a5336eSAntti Palosaari 	int			lna_gpio;
10019229240SAntti Palosaari 	struct i2c_client	*i2c_client_demod;
101eafa2ad6SAntti Palosaari 	struct i2c_client	*i2c_client_tuner;
1027098f582SAntti Palosaari 	struct i2c_client	*i2c_client_sec;
1033421b778SAidan Thornton };
1043421b778SAidan Thornton 
print_err_status(struct em28xx * dev,int packet,int status)1053421b778SAidan Thornton static inline void print_err_status(struct em28xx *dev,
1063421b778SAidan Thornton 				    int packet, int status)
1073aefb79aSMauro Carvalho Chehab {
1083421b778SAidan Thornton 	char *errmsg = "Unknown";
1093aefb79aSMauro Carvalho Chehab 
1103421b778SAidan Thornton 	switch (status) {
1113421b778SAidan Thornton 	case -ENOENT:
112b436e26eSColin Ian King 		errmsg = "unlinked synchronously";
1133421b778SAidan Thornton 		break;
1143421b778SAidan Thornton 	case -ECONNRESET:
115b436e26eSColin Ian King 		errmsg = "unlinked asynchronously";
1163421b778SAidan Thornton 		break;
1173421b778SAidan Thornton 	case -ENOSR:
1183421b778SAidan Thornton 		errmsg = "Buffer error (overrun)";
1193421b778SAidan Thornton 		break;
1203421b778SAidan Thornton 	case -EPIPE:
1213421b778SAidan Thornton 		errmsg = "Stalled (device not responding)";
1223421b778SAidan Thornton 		break;
1233421b778SAidan Thornton 	case -EOVERFLOW:
1243421b778SAidan Thornton 		errmsg = "Babble (bad cable?)";
1253421b778SAidan Thornton 		break;
1263421b778SAidan Thornton 	case -EPROTO:
1273421b778SAidan Thornton 		errmsg = "Bit-stuff error (bad cable?)";
1283421b778SAidan Thornton 		break;
1293421b778SAidan Thornton 	case -EILSEQ:
1303421b778SAidan Thornton 		errmsg = "CRC/Timeout (could be anything)";
1313421b778SAidan Thornton 		break;
1323421b778SAidan Thornton 	case -ETIME:
1333421b778SAidan Thornton 		errmsg = "Device does not respond";
1343421b778SAidan Thornton 		break;
1353421b778SAidan Thornton 	}
1363421b778SAidan Thornton 	if (packet < 0) {
1373421b778SAidan Thornton 		dprintk(1, "URB status %d [%s].\n", status, errmsg);
1383421b778SAidan Thornton 	} else {
1396ea54d93SDouglas Schilling Landgraf 		dprintk(1, "URB packet %d, status %d [%s].\n",
1406ea54d93SDouglas Schilling Landgraf 			packet, status, errmsg);
1413421b778SAidan Thornton 	}
1423421b778SAidan Thornton }
1433aefb79aSMauro Carvalho Chehab 
em28xx_dvb_urb_data_copy(struct em28xx * dev,struct urb * urb)144a950e4a7SFrank Schaefer static inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb)
1453421b778SAidan Thornton {
146a950e4a7SFrank Schaefer 	int xfer_bulk, num_packets, i;
1473aefb79aSMauro Carvalho Chehab 
1483421b778SAidan Thornton 	if (!dev)
1493421b778SAidan Thornton 		return 0;
1503421b778SAidan Thornton 
1512665c299SFrank Schaefer 	if (dev->disconnected)
1523421b778SAidan Thornton 		return 0;
1533421b778SAidan Thornton 
1541653cb0cSFrank Schaefer 	if (urb->status < 0)
1553421b778SAidan Thornton 		print_err_status(dev, -1, urb->status);
1563421b778SAidan Thornton 
157a950e4a7SFrank Schaefer 	xfer_bulk = usb_pipebulk(urb->pipe);
1583421b778SAidan Thornton 
159a950e4a7SFrank Schaefer 	if (xfer_bulk) /* bulk */
160a950e4a7SFrank Schaefer 		num_packets = 1;
161a950e4a7SFrank Schaefer 	else /* isoc */
162a950e4a7SFrank Schaefer 		num_packets = urb->number_of_packets;
163a950e4a7SFrank Schaefer 
164a950e4a7SFrank Schaefer 	for (i = 0; i < num_packets; i++) {
165a950e4a7SFrank Schaefer 		if (xfer_bulk) {
166a950e4a7SFrank Schaefer 			if (urb->status < 0) {
167a950e4a7SFrank Schaefer 				print_err_status(dev, i, urb->status);
168a950e4a7SFrank Schaefer 				if (urb->status != -EPROTO)
169a950e4a7SFrank Schaefer 					continue;
170a950e4a7SFrank Schaefer 			}
171ffdeca88SMauro Carvalho Chehab 			if (!urb->actual_length)
172ffdeca88SMauro Carvalho Chehab 				continue;
173a950e4a7SFrank Schaefer 			dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
174a950e4a7SFrank Schaefer 					 urb->actual_length);
175a950e4a7SFrank Schaefer 		} else {
176a950e4a7SFrank Schaefer 			if (urb->iso_frame_desc[i].status < 0) {
177a950e4a7SFrank Schaefer 				print_err_status(dev, i,
178a950e4a7SFrank Schaefer 						 urb->iso_frame_desc[i].status);
1793421b778SAidan Thornton 				if (urb->iso_frame_desc[i].status != -EPROTO)
1803421b778SAidan Thornton 					continue;
1813421b778SAidan Thornton 			}
182ffdeca88SMauro Carvalho Chehab 			if (!urb->iso_frame_desc[i].actual_length)
183ffdeca88SMauro Carvalho Chehab 				continue;
184a950e4a7SFrank Schaefer 			dvb_dmx_swfilter(&dev->dvb->demux,
185a950e4a7SFrank Schaefer 					 urb->transfer_buffer +
1863421b778SAidan Thornton 					 urb->iso_frame_desc[i].offset,
1873421b778SAidan Thornton 					 urb->iso_frame_desc[i].actual_length);
1883421b778SAidan Thornton 		}
189a950e4a7SFrank Schaefer 	}
1903aefb79aSMauro Carvalho Chehab 
1913aefb79aSMauro Carvalho Chehab 	return 0;
1923aefb79aSMauro Carvalho Chehab }
1933aefb79aSMauro Carvalho Chehab 
em28xx_start_streaming(struct em28xx_dvb * dvb)194f2d0c1c6SJarod Wilson static int em28xx_start_streaming(struct em28xx_dvb *dvb)
1956ea54d93SDouglas Schilling Landgraf {
196c67ec53fSMauro Carvalho Chehab 	int rc;
1973de09fbbSHans Verkuil 	struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv;
1983de09fbbSHans Verkuil 	struct em28xx *dev = i2c_bus->dev;
199509f8965SMauro Carvalho Chehab 	struct usb_device *udev = interface_to_usbdev(dev->intf);
200c647a91aSFrank Schaefer 	int dvb_max_packet_size, packet_multiplier, dvb_alt;
2013421b778SAidan Thornton 
202c647a91aSFrank Schaefer 	if (dev->dvb_xfer_bulk) {
203c647a91aSFrank Schaefer 		if (!dev->dvb_ep_bulk)
204c647a91aSFrank Schaefer 			return -ENODEV;
205c647a91aSFrank Schaefer 		dvb_max_packet_size = 512; /* USB 2.0 spec */
206c647a91aSFrank Schaefer 		packet_multiplier = EM28XX_DVB_BULK_PACKET_MULTIPLIER;
207c647a91aSFrank Schaefer 		dvb_alt = 0;
208c647a91aSFrank Schaefer 	} else { /* isoc */
209c647a91aSFrank Schaefer 		if (!dev->dvb_ep_isoc)
210c647a91aSFrank Schaefer 			return -ENODEV;
211c647a91aSFrank Schaefer 		dvb_max_packet_size = dev->dvb_max_pkt_size_isoc;
212c647a91aSFrank Schaefer 		if (dvb_max_packet_size < 0)
213c647a91aSFrank Schaefer 			return dvb_max_packet_size;
214c647a91aSFrank Schaefer 		packet_multiplier = EM28XX_DVB_NUM_ISOC_PACKETS;
215c647a91aSFrank Schaefer 		dvb_alt = dev->dvb_alt_isoc;
216c647a91aSFrank Schaefer 	}
217c647a91aSFrank Schaefer 
218a7853c25SBrad Love 	if (!dev->board.has_dual_ts)
219509f8965SMauro Carvalho Chehab 		usb_set_interface(udev, dev->ifnum, dvb_alt);
220a7853c25SBrad Love 
221c67ec53fSMauro Carvalho Chehab 	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
222c67ec53fSMauro Carvalho Chehab 	if (rc < 0)
223c67ec53fSMauro Carvalho Chehab 		return rc;
2243421b778SAidan Thornton 
22552f7b00eSMauro Carvalho Chehab 	dprintk(1, "Using %d buffers each with %d x %d bytes, alternate %d\n",
226f7acc4bbSMauro Carvalho Chehab 		EM28XX_DVB_NUM_BUFS,
227c647a91aSFrank Schaefer 		packet_multiplier,
22852f7b00eSMauro Carvalho Chehab 		dvb_max_packet_size, dvb_alt);
229d18e2fdaSDevin Heitmueller 
230c647a91aSFrank Schaefer 	return em28xx_init_usb_xfer(dev, EM28XX_DIGITAL_MODE,
231c647a91aSFrank Schaefer 				    dev->dvb_xfer_bulk,
232515688a8SFrank Schaefer 				    EM28XX_DVB_NUM_BUFS,
233c647a91aSFrank Schaefer 				    dvb_max_packet_size,
234c647a91aSFrank Schaefer 				    packet_multiplier,
235a950e4a7SFrank Schaefer 				    em28xx_dvb_urb_data_copy);
2363421b778SAidan Thornton }
2373421b778SAidan Thornton 
em28xx_stop_streaming(struct em28xx_dvb * dvb)238f2d0c1c6SJarod Wilson static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
2396ea54d93SDouglas Schilling Landgraf {
2403de09fbbSHans Verkuil 	struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv;
2413de09fbbSHans Verkuil 	struct em28xx *dev = i2c_bus->dev;
2423421b778SAidan Thornton 
2435f5f147fSGianluca Gennari 	em28xx_stop_urbs(dev);
244c67ec53fSMauro Carvalho Chehab 
2453421b778SAidan Thornton 	return 0;
2463421b778SAidan Thornton }
2473421b778SAidan Thornton 
em28xx_start_feed(struct dvb_demux_feed * feed)248f2d0c1c6SJarod Wilson static int em28xx_start_feed(struct dvb_demux_feed *feed)
2493421b778SAidan Thornton {
2503421b778SAidan Thornton 	struct dvb_demux *demux  = feed->demux;
2513421b778SAidan Thornton 	struct em28xx_dvb *dvb = demux->priv;
2523421b778SAidan Thornton 	int rc, ret;
2533421b778SAidan Thornton 
2543421b778SAidan Thornton 	if (!demux->dmx.frontend)
2553421b778SAidan Thornton 		return -EINVAL;
2563421b778SAidan Thornton 
2573421b778SAidan Thornton 	mutex_lock(&dvb->lock);
2583421b778SAidan Thornton 	dvb->nfeeds++;
2593421b778SAidan Thornton 	rc = dvb->nfeeds;
2603421b778SAidan Thornton 
2613421b778SAidan Thornton 	if (dvb->nfeeds == 1) {
262f2d0c1c6SJarod Wilson 		ret = em28xx_start_streaming(dvb);
2636ea54d93SDouglas Schilling Landgraf 		if (ret < 0)
2646ea54d93SDouglas Schilling Landgraf 			rc = ret;
2653421b778SAidan Thornton 	}
2663421b778SAidan Thornton 
2673421b778SAidan Thornton 	mutex_unlock(&dvb->lock);
2683421b778SAidan Thornton 	return rc;
2693421b778SAidan Thornton }
2703421b778SAidan Thornton 
em28xx_stop_feed(struct dvb_demux_feed * feed)271f2d0c1c6SJarod Wilson static int em28xx_stop_feed(struct dvb_demux_feed *feed)
2723421b778SAidan Thornton {
2733421b778SAidan Thornton 	struct dvb_demux *demux  = feed->demux;
2743421b778SAidan Thornton 	struct em28xx_dvb *dvb = demux->priv;
2753421b778SAidan Thornton 	int err = 0;
2763421b778SAidan Thornton 
2773421b778SAidan Thornton 	mutex_lock(&dvb->lock);
2783421b778SAidan Thornton 	dvb->nfeeds--;
2796ea54d93SDouglas Schilling Landgraf 
280fe8d54f0SMauro Carvalho Chehab 	if (!dvb->nfeeds)
281f2d0c1c6SJarod Wilson 		err = em28xx_stop_streaming(dvb);
2826ea54d93SDouglas Schilling Landgraf 
2833421b778SAidan Thornton 	mutex_unlock(&dvb->lock);
2843421b778SAidan Thornton 	return err;
2853421b778SAidan Thornton }
2863421b778SAidan Thornton 
287e3569abcSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
em28xx_dvb_bus_ctrl(struct dvb_frontend * fe,int acquire)288e3569abcSMauro Carvalho Chehab static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
289e3569abcSMauro Carvalho Chehab {
290a3b60209SMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv;
291a3b60209SMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
292e3569abcSMauro Carvalho Chehab 
293e3569abcSMauro Carvalho Chehab 	if (acquire)
294e3569abcSMauro Carvalho Chehab 		return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
295e3569abcSMauro Carvalho Chehab 	else
2962fe3e2eeSMauro Carvalho Chehab 		return em28xx_set_mode(dev, EM28XX_SUSPEND);
297e3569abcSMauro Carvalho Chehab }
298e3569abcSMauro Carvalho Chehab 
2993aefb79aSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
3003aefb79aSMauro Carvalho Chehab 
301227ad4abSMauro Carvalho Chehab static struct lgdt330x_config em2880_lgdt3303_dev = {
302227ad4abSMauro Carvalho Chehab 	.demod_chip = LGDT3303,
303227ad4abSMauro Carvalho Chehab };
3043aefb79aSMauro Carvalho Chehab 
3057e48b30aSJarod Wilson static struct lgdt3305_config em2870_lgdt3304_dev = {
3067e48b30aSJarod Wilson 	.i2c_addr           = 0x0e,
3077e48b30aSJarod Wilson 	.demod_chip         = LGDT3304,
3087e48b30aSJarod Wilson 	.spectral_inversion = 1,
3097e48b30aSJarod Wilson 	.deny_i2c_rptr      = 1,
3107e48b30aSJarod Wilson 	.mpeg_mode          = LGDT3305_MPEG_PARALLEL,
3117e48b30aSJarod Wilson 	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
3127e48b30aSJarod Wilson 	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
3137e48b30aSJarod Wilson 	.vsb_if_khz         = 3250,
3147e48b30aSJarod Wilson 	.qam_if_khz         = 4000,
3157e48b30aSJarod Wilson };
3167e48b30aSJarod Wilson 
3176dbea9f0SJean-Francois Thibert static struct lgdt3305_config em2874_lgdt3305_dev = {
3186dbea9f0SJean-Francois Thibert 	.i2c_addr           = 0x0e,
3196dbea9f0SJean-Francois Thibert 	.demod_chip         = LGDT3305,
3206dbea9f0SJean-Francois Thibert 	.spectral_inversion = 1,
3216dbea9f0SJean-Francois Thibert 	.deny_i2c_rptr      = 0,
3226dbea9f0SJean-Francois Thibert 	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
3236dbea9f0SJean-Francois Thibert 	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
3246dbea9f0SJean-Francois Thibert 	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
3256dbea9f0SJean-Francois Thibert 	.vsb_if_khz         = 3250,
3266dbea9f0SJean-Francois Thibert 	.qam_if_khz         = 4000,
3276dbea9f0SJean-Francois Thibert };
3286dbea9f0SJean-Francois Thibert 
32902bc1f55SMauro Carvalho Chehab static struct lgdt3305_config em2874_lgdt3305_nogate_dev = {
33002bc1f55SMauro Carvalho Chehab 	.i2c_addr           = 0x0e,
33102bc1f55SMauro Carvalho Chehab 	.demod_chip         = LGDT3305,
33202bc1f55SMauro Carvalho Chehab 	.spectral_inversion = 1,
33302bc1f55SMauro Carvalho Chehab 	.deny_i2c_rptr      = 1,
33402bc1f55SMauro Carvalho Chehab 	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
33502bc1f55SMauro Carvalho Chehab 	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
33602bc1f55SMauro Carvalho Chehab 	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
33702bc1f55SMauro Carvalho Chehab 	.vsb_if_khz         = 3600,
33802bc1f55SMauro Carvalho Chehab 	.qam_if_khz         = 3600,
33902bc1f55SMauro Carvalho Chehab };
34002bc1f55SMauro Carvalho Chehab 
341ca3dfd6aSMauro Carvalho Chehab static struct s921_config sharp_isdbt = {
342ca3dfd6aSMauro Carvalho Chehab 	.demod_address = 0x30 >> 1
343ca3dfd6aSMauro Carvalho Chehab };
344ca3dfd6aSMauro Carvalho Chehab 
3457e6388a1SAidan Thornton static struct zl10353_config em28xx_zl10353_with_xc3028 = {
3467e6388a1SAidan Thornton 	.demod_address = (0x1e >> 1),
3477e6388a1SAidan Thornton 	.no_tuner = 1,
3487e6388a1SAidan Thornton 	.parallel_ts = 1,
3497e6388a1SAidan Thornton 	.if2 = 45600,
3507e6388a1SAidan Thornton };
3517e6388a1SAidan Thornton 
3526e7b9ea0SRobert Krakora static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
3536e7b9ea0SRobert Krakora 	.demod_address = 0x32 >> 1,
3546e7b9ea0SRobert Krakora 	.output_mode   = S5H1409_PARALLEL_OUTPUT,
3556e7b9ea0SRobert Krakora 	.gpio          = S5H1409_GPIO_OFF,
3566e7b9ea0SRobert Krakora 	.inversion     = S5H1409_INVERSION_OFF,
3576e7b9ea0SRobert Krakora 	.status_mode   = S5H1409_DEMODLOCKING,
358ad05ff09SMauro Carvalho Chehab 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK
3596e7b9ea0SRobert Krakora };
3606e7b9ea0SRobert Krakora 
3617e48b30aSJarod Wilson static struct tda18271_std_map kworld_a340_std_map = {
3627e48b30aSJarod Wilson 	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 0,
3637e48b30aSJarod Wilson 		      .if_lvl = 1, .rfagc_top = 0x37, },
3647e48b30aSJarod Wilson 	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 1,
3657e48b30aSJarod Wilson 		      .if_lvl = 1, .rfagc_top = 0x37, },
3667e48b30aSJarod Wilson };
3677e48b30aSJarod Wilson 
3687e48b30aSJarod Wilson static struct tda18271_config kworld_a340_config = {
3697e48b30aSJarod Wilson 	.std_map           = &kworld_a340_std_map,
3707e48b30aSJarod Wilson };
3717e48b30aSJarod Wilson 
3726dbea9f0SJean-Francois Thibert static struct tda18271_config kworld_ub435q_v2_config = {
3736dbea9f0SJean-Francois Thibert 	.std_map	= &kworld_a340_std_map,
3746dbea9f0SJean-Francois Thibert 	.gate		= TDA18271_GATE_DIGITAL,
3756dbea9f0SJean-Francois Thibert };
3766dbea9f0SJean-Francois Thibert 
37702bc1f55SMauro Carvalho Chehab static struct tda18212_config kworld_ub435q_v3_config = {
37802bc1f55SMauro Carvalho Chehab 	.if_atsc_vsb	= 3600,
37902bc1f55SMauro Carvalho Chehab 	.if_atsc_qam	= 3600,
38002bc1f55SMauro Carvalho Chehab };
38102bc1f55SMauro Carvalho Chehab 
382a84f79aeSDevin Heitmueller static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
383f797608cSDevin Heitmueller 	.demod_address = (0x1e >> 1),
384f797608cSDevin Heitmueller 	.no_tuner = 1,
385f797608cSDevin Heitmueller 	.disable_i2c_gate_ctrl = 1,
386f797608cSDevin Heitmueller 	.parallel_ts = 1,
387f797608cSDevin Heitmueller 	.if2 = 45600,
388f797608cSDevin Heitmueller };
389f797608cSDevin Heitmueller 
39075e2b869SDevin Heitmueller static struct drxd_config em28xx_drxd = {
391aac865f7SMauro Carvalho Chehab 	.demod_address = 0x70,
392aac865f7SMauro Carvalho Chehab 	.demod_revision = 0xa2,
393aac865f7SMauro Carvalho Chehab 	.pll_type = DRXD_PLL_NONE,
394aac865f7SMauro Carvalho Chehab 	.clock = 12000,
395aac865f7SMauro Carvalho Chehab 	.insert_rs_byte = 1,
396aac865f7SMauro Carvalho Chehab 	.IF = 42800000,
3976b142b3cSDevin Heitmueller 	.disable_i2c_gate_ctrl = 1,
39817d9d558SDevin Heitmueller };
39917d9d558SDevin Heitmueller 
40061bdbef0SEzequiel García static struct drxk_config terratec_h5_drxk = {
401fec528b7SMauro Carvalho Chehab 	.adr = 0x29,
402e4f4f875SMauro Carvalho Chehab 	.single_master = 1,
403f1fe1b75SMauro Carvalho Chehab 	.no_i2c_bridge = 1,
4048b9456aeSMauro Carvalho Chehab 	.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
4059e23f50aSMartin Blumenstingl 	.qam_demod_parameter_count = 2,
406fec528b7SMauro Carvalho Chehab };
407fec528b7SMauro Carvalho Chehab 
40861bdbef0SEzequiel García static struct drxk_config hauppauge_930c_drxk = {
40982e7dbbdSEddi De Pieri 	.adr = 0x29,
41082e7dbbdSEddi De Pieri 	.single_master = 1,
41182e7dbbdSEddi De Pieri 	.no_i2c_bridge = 1,
41282e7dbbdSEddi De Pieri 	.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
41382e7dbbdSEddi De Pieri 	.chunk_size = 56,
4149e23f50aSMartin Blumenstingl 	.qam_demod_parameter_count = 2,
41582e7dbbdSEddi De Pieri };
41682e7dbbdSEddi De Pieri 
41789040136SMartin Blumenstingl static struct drxk_config terratec_htc_stick_drxk = {
418c8dce008SMartin Blumenstingl 	.adr = 0x29,
419c8dce008SMartin Blumenstingl 	.single_master = 1,
420c8dce008SMartin Blumenstingl 	.no_i2c_bridge = 1,
421c8dce008SMartin Blumenstingl 	.microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
422c8dce008SMartin Blumenstingl 	.chunk_size = 54,
4239e23f50aSMartin Blumenstingl 	.qam_demod_parameter_count = 2,
424c8dce008SMartin Blumenstingl 	/* Required for the antenna_gpio to disable LNA. */
425c8dce008SMartin Blumenstingl 	.antenna_dvbt = true,
426c8dce008SMartin Blumenstingl 	/* The windows driver uses the same. This will disable LNA. */
427c8dce008SMartin Blumenstingl 	.antenna_gpio = 0x6,
428c8dce008SMartin Blumenstingl };
429c8dce008SMartin Blumenstingl 
43061bdbef0SEzequiel García static struct drxk_config maxmedia_ub425_tc_drxk = {
4313553085cSAntti Palosaari 	.adr = 0x29,
4323553085cSAntti Palosaari 	.single_master = 1,
4333553085cSAntti Palosaari 	.no_i2c_bridge = 1,
4348d100b27SAntti Palosaari 	.microcode_name = "dvb-demod-drxk-01.fw",
4358d100b27SAntti Palosaari 	.chunk_size = 62,
436de0fc463SAntti Palosaari 	.qam_demod_parameter_count = 2,
4373553085cSAntti Palosaari };
4383553085cSAntti Palosaari 
43961bdbef0SEzequiel García static struct drxk_config pctv_520e_drxk = {
440c247d7b1SAntti Palosaari 	.adr = 0x29,
441c247d7b1SAntti Palosaari 	.single_master = 1,
442c247d7b1SAntti Palosaari 	.microcode_name = "dvb-demod-drxk-pctv.fw",
4439e23f50aSMartin Blumenstingl 	.qam_demod_parameter_count = 2,
444c247d7b1SAntti Palosaari 	.chunk_size = 58,
445f6f379dfSAntti Palosaari 	.antenna_dvbt = true, /* disable LNA */
446f6f379dfSAntti Palosaari 	.antenna_gpio = (1 << 2), /* disable LNA */
447c247d7b1SAntti Palosaari };
448c247d7b1SAntti Palosaari 
drxk_gate_ctrl(struct dvb_frontend * fe,int enable)449fec528b7SMauro Carvalho Chehab static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
450fec528b7SMauro Carvalho Chehab {
451fec528b7SMauro Carvalho Chehab 	struct em28xx_dvb *dvb = fe->sec_priv;
452fec528b7SMauro Carvalho Chehab 	int status;
453fec528b7SMauro Carvalho Chehab 
454fec528b7SMauro Carvalho Chehab 	if (!dvb)
455fec528b7SMauro Carvalho Chehab 		return -EINVAL;
456fec528b7SMauro Carvalho Chehab 
457fec528b7SMauro Carvalho Chehab 	if (enable) {
458fec528b7SMauro Carvalho Chehab 		down(&dvb->pll_mutex);
459fec528b7SMauro Carvalho Chehab 		status = dvb->gate_ctrl(fe, 1);
460fec528b7SMauro Carvalho Chehab 	} else {
461fec528b7SMauro Carvalho Chehab 		status = dvb->gate_ctrl(fe, 0);
462fec528b7SMauro Carvalho Chehab 		up(&dvb->pll_mutex);
463fec528b7SMauro Carvalho Chehab 	}
464fec528b7SMauro Carvalho Chehab 	return status;
465fec528b7SMauro Carvalho Chehab }
466fec528b7SMauro Carvalho Chehab 
hauppauge_hvr930c_init(struct em28xx * dev)46782e7dbbdSEddi De Pieri static void hauppauge_hvr930c_init(struct em28xx *dev)
46882e7dbbdSEddi De Pieri {
46982e7dbbdSEddi De Pieri 	int i;
47082e7dbbdSEddi De Pieri 
471ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
472907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xff,	0xff,	0x65},
473907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xfb,	0xff,	0x32},
474907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xff,	0xff,	0xb8},
47582e7dbbdSEddi De Pieri 		{	-1,			-1,	-1,	-1},
47682e7dbbdSEddi De Pieri 	};
477ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
478907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x01},
479907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xaf,	0xff,	0x65},
480907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x76},
481907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x01},
482907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xcf,	0xff,	0x0b},
483907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x40},
48482e7dbbdSEddi De Pieri 
485907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xcf,	0xff,	0x65},
486907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x65},
487907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xcf,	0xff,	0x0b},
488907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xef,	0xff,	0x65},
48982e7dbbdSEddi De Pieri 
49082e7dbbdSEddi De Pieri 		{	-1,			-1,	-1,	-1},
49182e7dbbdSEddi De Pieri 	};
49282e7dbbdSEddi De Pieri 
493ba0c8e6eSColin Ian King 	static const struct {
49482e7dbbdSEddi De Pieri 		unsigned char r[4];
49582e7dbbdSEddi De Pieri 		int len;
49682e7dbbdSEddi De Pieri 	} regs[] = {
49782e7dbbdSEddi De Pieri 		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
49882e7dbbdSEddi De Pieri 		{{ 0x01, 0x02 }, 2},
49982e7dbbdSEddi De Pieri 		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
50082e7dbbdSEddi De Pieri 		{{ 0x01, 0x00 }, 2},
50182e7dbbdSEddi De Pieri 		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
50282e7dbbdSEddi De Pieri 		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
50382e7dbbdSEddi De Pieri 		{{ 0x01, 0x00 }, 2},
50482e7dbbdSEddi De Pieri 		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
50582e7dbbdSEddi De Pieri 		{{ 0x04, 0x00 }, 2},
50682e7dbbdSEddi De Pieri 		{{ 0x00, 0x04 }, 2},
50782e7dbbdSEddi De Pieri 		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
50882e7dbbdSEddi De Pieri 		{{ 0x04, 0x14 }, 2},
50982e7dbbdSEddi De Pieri 		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
51082e7dbbdSEddi De Pieri 	};
51182e7dbbdSEddi De Pieri 
51282e7dbbdSEddi De Pieri 	em28xx_gpio_set(dev, hauppauge_hvr930c_init);
51382e7dbbdSEddi De Pieri 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
514fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
51582e7dbbdSEddi De Pieri 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
516fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
51782e7dbbdSEddi De Pieri 
518c7a45e5bSMauro Carvalho Chehab 	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
51982e7dbbdSEddi De Pieri 
52082e7dbbdSEddi De Pieri 	for (i = 0; i < ARRAY_SIZE(regs); i++)
521fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
522fe8d54f0SMauro Carvalho Chehab 				regs[i].r, regs[i].len);
52382e7dbbdSEddi De Pieri 	em28xx_gpio_set(dev, hauppauge_hvr930c_end);
52482e7dbbdSEddi De Pieri 
52582e7dbbdSEddi De Pieri 	msleep(100);
52682e7dbbdSEddi De Pieri 
52782e7dbbdSEddi De Pieri 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
52882e7dbbdSEddi De Pieri 	msleep(30);
52982e7dbbdSEddi De Pieri 
53082e7dbbdSEddi De Pieri 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
531fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
53282e7dbbdSEddi De Pieri }
53382e7dbbdSEddi De Pieri 
terratec_h5_init(struct em28xx * dev)534fec528b7SMauro Carvalho Chehab static void terratec_h5_init(struct em28xx *dev)
535fec528b7SMauro Carvalho Chehab {
536fec528b7SMauro Carvalho Chehab 	int i;
537ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_h5_init[] = {
538c074fc4cSFrank Schaefer 		{EM2820_R08_GPIO_CTRL,		0xff,	0xff,	10},
539907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	100},
540907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf2,	0xff,	50},
541907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	100},
542fec528b7SMauro Carvalho Chehab 		{	-1,			-1,	-1,	-1},
543fec528b7SMauro Carvalho Chehab 	};
544ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_h5_end[] = {
545907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	100},
546907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xa6,	0xff,	50},
547907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	100},
548fec528b7SMauro Carvalho Chehab 		{	-1,			-1,	-1,	-1},
549fec528b7SMauro Carvalho Chehab 	};
550ba0c8e6eSColin Ian King 	static const struct {
551fec528b7SMauro Carvalho Chehab 		unsigned char r[4];
552fec528b7SMauro Carvalho Chehab 		int len;
553fec528b7SMauro Carvalho Chehab 	} regs[] = {
554fec528b7SMauro Carvalho Chehab 		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
555fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x02 }, 2},
556fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
557fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x00 }, 2},
558fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
559fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
560fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x00 }, 2},
561fec528b7SMauro Carvalho Chehab 		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
562fec528b7SMauro Carvalho Chehab 		{{ 0x04, 0x00 }, 2},
563fec528b7SMauro Carvalho Chehab 		{{ 0x00, 0x04 }, 2},
564fec528b7SMauro Carvalho Chehab 		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
565fec528b7SMauro Carvalho Chehab 		{{ 0x04, 0x14 }, 2},
566fec528b7SMauro Carvalho Chehab 		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
567fec528b7SMauro Carvalho Chehab 	};
568fec528b7SMauro Carvalho Chehab 
569fec528b7SMauro Carvalho Chehab 	em28xx_gpio_set(dev, terratec_h5_init);
570fec528b7SMauro Carvalho Chehab 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
571fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
572fec528b7SMauro Carvalho Chehab 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
573fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
574fec528b7SMauro Carvalho Chehab 
575c7a45e5bSMauro Carvalho Chehab 	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
576fec528b7SMauro Carvalho Chehab 
577fec528b7SMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(regs); i++)
578fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
579fe8d54f0SMauro Carvalho Chehab 				regs[i].r, regs[i].len);
580fec528b7SMauro Carvalho Chehab 	em28xx_gpio_set(dev, terratec_h5_end);
581fec528b7SMauro Carvalho Chehab };
582fec528b7SMauro Carvalho Chehab 
terratec_htc_stick_init(struct em28xx * dev)583c8dce008SMartin Blumenstingl static void terratec_htc_stick_init(struct em28xx *dev)
584c8dce008SMartin Blumenstingl {
585c8dce008SMartin Blumenstingl 	int i;
586c8dce008SMartin Blumenstingl 
587c8dce008SMartin Blumenstingl 	/*
588c8dce008SMartin Blumenstingl 	 * GPIO configuration:
589c8dce008SMartin Blumenstingl 	 * 0xff: unknown (does not affect DVB-T).
590c8dce008SMartin Blumenstingl 	 * 0xf6: DRX-K (demodulator).
591c8dce008SMartin Blumenstingl 	 * 0xe6: unknown (does not affect DVB-T).
592c8dce008SMartin Blumenstingl 	 * 0xb6: unknown (does not affect DVB-T).
593c8dce008SMartin Blumenstingl 	 */
594ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_htc_stick_init[] = {
595c074fc4cSFrank Schaefer 		{EM2820_R08_GPIO_CTRL,		0xff,	0xff,	10},
596907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	100},
597907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	50},
598907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	100},
599c8dce008SMartin Blumenstingl 		{	-1,			-1,	-1,	-1},
600c8dce008SMartin Blumenstingl 	};
601ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_htc_stick_end[] = {
602907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xb6,	0xff,	100},
603907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	50},
604c8dce008SMartin Blumenstingl 		{	-1,			-1,	-1,	-1},
605c8dce008SMartin Blumenstingl 	};
606c8dce008SMartin Blumenstingl 
60789040136SMartin Blumenstingl 	/*
60889040136SMartin Blumenstingl 	 * Init the analog decoder (not yet supported), but
60989040136SMartin Blumenstingl 	 * it's probably still a good idea.
61089040136SMartin Blumenstingl 	 */
611ba0c8e6eSColin Ian King 	static const struct {
612c8dce008SMartin Blumenstingl 		unsigned char r[4];
613c8dce008SMartin Blumenstingl 		int len;
614c8dce008SMartin Blumenstingl 	} regs[] = {
615c8dce008SMartin Blumenstingl 		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
616c8dce008SMartin Blumenstingl 		{{ 0x01, 0x02 }, 2},
617c8dce008SMartin Blumenstingl 		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
618c8dce008SMartin Blumenstingl 		{{ 0x01, 0x00 }, 2},
619c8dce008SMartin Blumenstingl 		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
620c8dce008SMartin Blumenstingl 	};
621c8dce008SMartin Blumenstingl 
622c8dce008SMartin Blumenstingl 	em28xx_gpio_set(dev, terratec_htc_stick_init);
623c8dce008SMartin Blumenstingl 
624c8dce008SMartin Blumenstingl 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
625fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
626c8dce008SMartin Blumenstingl 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
627fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
628c8dce008SMartin Blumenstingl 
629c7a45e5bSMauro Carvalho Chehab 	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
630c8dce008SMartin Blumenstingl 
631c8dce008SMartin Blumenstingl 	for (i = 0; i < ARRAY_SIZE(regs); i++)
632fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
633fe8d54f0SMauro Carvalho Chehab 				regs[i].r, regs[i].len);
634c8dce008SMartin Blumenstingl 
635c8dce008SMartin Blumenstingl 	em28xx_gpio_set(dev, terratec_htc_stick_end);
636c8dce008SMartin Blumenstingl };
637c8dce008SMartin Blumenstingl 
terratec_htc_usb_xs_init(struct em28xx * dev)63889040136SMartin Blumenstingl static void terratec_htc_usb_xs_init(struct em28xx *dev)
63989040136SMartin Blumenstingl {
64089040136SMartin Blumenstingl 	int i;
64189040136SMartin Blumenstingl 
642ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_htc_usb_xs_init[] = {
643c074fc4cSFrank Schaefer 		{EM2820_R08_GPIO_CTRL,		0xff,	0xff,	10},
644907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xb2,	0xff,	100},
645907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xb2,	0xff,	50},
646907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xb6,	0xff,	100},
64789040136SMartin Blumenstingl 		{	-1,			-1,	-1,	-1},
64889040136SMartin Blumenstingl 	};
649ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq terratec_htc_usb_xs_end[] = {
650907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xa6,	0xff,	100},
651907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xa6,	0xff,	50},
652907d109bSFrank Schaefer 		{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	100},
65389040136SMartin Blumenstingl 		{	-1,			-1,	-1,	-1},
65489040136SMartin Blumenstingl 	};
65589040136SMartin Blumenstingl 
65689040136SMartin Blumenstingl 	/*
65789040136SMartin Blumenstingl 	 * Init the analog decoder (not yet supported), but
65889040136SMartin Blumenstingl 	 * it's probably still a good idea.
65989040136SMartin Blumenstingl 	 */
660ba0c8e6eSColin Ian King 	static const struct {
66189040136SMartin Blumenstingl 		unsigned char r[4];
66289040136SMartin Blumenstingl 		int len;
66389040136SMartin Blumenstingl 	} regs[] = {
66489040136SMartin Blumenstingl 		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
66589040136SMartin Blumenstingl 		{{ 0x01, 0x02 }, 2},
66689040136SMartin Blumenstingl 		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
66789040136SMartin Blumenstingl 		{{ 0x01, 0x00 }, 2},
66889040136SMartin Blumenstingl 		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
66989040136SMartin Blumenstingl 		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
67089040136SMartin Blumenstingl 		{{ 0x01, 0x00 }, 2},
67189040136SMartin Blumenstingl 		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
67289040136SMartin Blumenstingl 		{{ 0x04, 0x00 }, 2},
67389040136SMartin Blumenstingl 		{{ 0x00, 0x04 }, 2},
67489040136SMartin Blumenstingl 		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
67589040136SMartin Blumenstingl 		{{ 0x04, 0x14 }, 2},
67689040136SMartin Blumenstingl 		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
67789040136SMartin Blumenstingl 	};
67889040136SMartin Blumenstingl 
67989040136SMartin Blumenstingl 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
68089040136SMartin Blumenstingl 
68189040136SMartin Blumenstingl 	em28xx_gpio_set(dev, terratec_htc_usb_xs_init);
68289040136SMartin Blumenstingl 
68389040136SMartin Blumenstingl 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
684fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
68589040136SMartin Blumenstingl 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
686fe8d54f0SMauro Carvalho Chehab 	usleep_range(10000, 11000);
68789040136SMartin Blumenstingl 
688c7a45e5bSMauro Carvalho Chehab 	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
68989040136SMartin Blumenstingl 
69089040136SMartin Blumenstingl 	for (i = 0; i < ARRAY_SIZE(regs); i++)
691fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
692fe8d54f0SMauro Carvalho Chehab 				regs[i].r, regs[i].len);
69389040136SMartin Blumenstingl 
69489040136SMartin Blumenstingl 	em28xx_gpio_set(dev, terratec_htc_usb_xs_end);
69589040136SMartin Blumenstingl };
69689040136SMartin Blumenstingl 
pctv_520e_init(struct em28xx * dev)697c247d7b1SAntti Palosaari static void pctv_520e_init(struct em28xx *dev)
698c247d7b1SAntti Palosaari {
699c247d7b1SAntti Palosaari 	/*
70026c8a729SAntti Palosaari 	 * Init AVF4910B analog decoder. Looks like I2C traffic to
70126c8a729SAntti Palosaari 	 * digital demodulator and tuner are routed via AVF4910B.
702c247d7b1SAntti Palosaari 	 */
703c247d7b1SAntti Palosaari 	int i;
704ba0c8e6eSColin Ian King 	static const struct {
705c247d7b1SAntti Palosaari 		unsigned char r[4];
706c247d7b1SAntti Palosaari 		int len;
707c247d7b1SAntti Palosaari 	} regs[] = {
708c247d7b1SAntti Palosaari 		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
709c247d7b1SAntti Palosaari 		{{ 0x01, 0x02 }, 2},
710c247d7b1SAntti Palosaari 		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
711c247d7b1SAntti Palosaari 		{{ 0x01, 0x00 }, 2},
712c247d7b1SAntti Palosaari 		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
713c247d7b1SAntti Palosaari 		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
714c247d7b1SAntti Palosaari 		{{ 0x01, 0x00 }, 2},
715c247d7b1SAntti Palosaari 		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
716c247d7b1SAntti Palosaari 	};
717c247d7b1SAntti Palosaari 
718c7a45e5bSMauro Carvalho Chehab 	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; /* 0x41 */
719c247d7b1SAntti Palosaari 
720c247d7b1SAntti Palosaari 	for (i = 0; i < ARRAY_SIZE(regs); i++)
721fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
722fe8d54f0SMauro Carvalho Chehab 				regs[i].r, regs[i].len);
723c247d7b1SAntti Palosaari };
724c247d7b1SAntti Palosaari 
em28xx_pctv_290e_set_lna(struct dvb_frontend * fe)72533eebec5SAntti Palosaari static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe)
72613a5336eSAntti Palosaari {
72733eebec5SAntti Palosaari 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
7283ec40dcfSAntti Palosaari 	struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv;
7293ec40dcfSAntti Palosaari 	struct em28xx *dev = i2c_bus->dev;
73013a5336eSAntti Palosaari #ifdef CONFIG_GPIOLIB
73113a5336eSAntti Palosaari 	struct em28xx_dvb *dvb = dev->dvb;
73213a5336eSAntti Palosaari 	int ret;
73313a5336eSAntti Palosaari 	unsigned long flags;
73413a5336eSAntti Palosaari 
73533eebec5SAntti Palosaari 	if (c->lna == 1)
73633eebec5SAntti Palosaari 		flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */
73713a5336eSAntti Palosaari 	else
73833eebec5SAntti Palosaari 		flags = GPIOF_OUT_INIT_LOW; /* disable LNA */
73913a5336eSAntti Palosaari 
74013a5336eSAntti Palosaari 	ret = gpio_request_one(dvb->lna_gpio, flags, NULL);
74113a5336eSAntti Palosaari 	if (ret)
74229b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev, "gpio request failed %d\n", ret);
74313a5336eSAntti Palosaari 	else
74413a5336eSAntti Palosaari 		gpio_free(dvb->lna_gpio);
74513a5336eSAntti Palosaari 
74613a5336eSAntti Palosaari 	return ret;
74713a5336eSAntti Palosaari #else
74829b05e22SMauro Carvalho Chehab 	dev_warn(&dev->intf->dev, "%s: LNA control is disabled (lna=%u)\n",
74933eebec5SAntti Palosaari 		 KBUILD_MODNAME, c->lna);
75013a5336eSAntti Palosaari 	return 0;
75113a5336eSAntti Palosaari #endif
75213a5336eSAntti Palosaari }
75313a5336eSAntti Palosaari 
em28xx_pctv_292e_set_lna(struct dvb_frontend * fe)754ffb9948eSAntti Palosaari static int em28xx_pctv_292e_set_lna(struct dvb_frontend *fe)
755ffb9948eSAntti Palosaari {
756ffb9948eSAntti Palosaari 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
757ffb9948eSAntti Palosaari 	struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv;
758ffb9948eSAntti Palosaari 	struct em28xx *dev = i2c_bus->dev;
759ffb9948eSAntti Palosaari 	u8 lna;
760ffb9948eSAntti Palosaari 
761ffb9948eSAntti Palosaari 	if (c->lna == 1)
762ffb9948eSAntti Palosaari 		lna = 0x01;
763ffb9948eSAntti Palosaari 	else
764ffb9948eSAntti Palosaari 		lna = 0x00;
765ffb9948eSAntti Palosaari 
766ffb9948eSAntti Palosaari 	return em28xx_write_reg_bits(dev, EM2874_R80_GPIO_P0_CTRL, lna, 0x01);
767ffb9948eSAntti Palosaari }
768ffb9948eSAntti Palosaari 
em28xx_mt352_terratec_xs_init(struct dvb_frontend * fe)769f2d0c1c6SJarod Wilson static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
7704fb202a8SDevin Heitmueller {
7714fb202a8SDevin Heitmueller 	/* Values extracted from a USB trace of the Terratec Windows driver */
7724fb202a8SDevin Heitmueller 	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
7734fb202a8SDevin Heitmueller 	static u8 reset[]          = { RESET,      0x80 };
7744fb202a8SDevin Heitmueller 	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
7754fb202a8SDevin Heitmueller 	static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
7764fb202a8SDevin Heitmueller 	static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
7774fb202a8SDevin Heitmueller 	static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
7784fb202a8SDevin Heitmueller 	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
7794fb202a8SDevin Heitmueller 	static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
7804fb202a8SDevin Heitmueller 	static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
781ff69786bSDevin Heitmueller 	static u8 tuner_go[]       = { TUNER_GO, 0x01};
7824fb202a8SDevin Heitmueller 
7834fb202a8SDevin Heitmueller 	mt352_write(fe, clock_config,   sizeof(clock_config));
784fe8d54f0SMauro Carvalho Chehab 	usleep_range(200, 250);
7854fb202a8SDevin Heitmueller 	mt352_write(fe, reset,          sizeof(reset));
7864fb202a8SDevin Heitmueller 	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
7874fb202a8SDevin Heitmueller 	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
7884fb202a8SDevin Heitmueller 	mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
7894fb202a8SDevin Heitmueller 	mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
7904fb202a8SDevin Heitmueller 	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
7914fb202a8SDevin Heitmueller 	mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
7924fb202a8SDevin Heitmueller 	mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
7934fb202a8SDevin Heitmueller 	mt352_write(fe, tuner_go,       sizeof(tuner_go));
7944fb202a8SDevin Heitmueller 	return 0;
7954fb202a8SDevin Heitmueller }
7964fb202a8SDevin Heitmueller 
px_bcud_init(struct em28xx * dev)797ab4d1452SSatoshi Nagahama static void px_bcud_init(struct em28xx *dev)
798ab4d1452SSatoshi Nagahama {
799ab4d1452SSatoshi Nagahama 	int i;
800ba0c8e6eSColin Ian King 	static const struct {
801ab4d1452SSatoshi Nagahama 		unsigned char r[4];
802ab4d1452SSatoshi Nagahama 		int len;
803ab4d1452SSatoshi Nagahama 	} regs1[] = {
804ab4d1452SSatoshi Nagahama 		{{ 0x0e, 0x77 }, 2},
805ab4d1452SSatoshi Nagahama 		{{ 0x0f, 0x77 }, 2},
806ab4d1452SSatoshi Nagahama 		{{ 0x03, 0x90 }, 2},
807ab4d1452SSatoshi Nagahama 	}, regs2[] = {
808ab4d1452SSatoshi Nagahama 		{{ 0x07, 0x01 }, 2},
809ab4d1452SSatoshi Nagahama 		{{ 0x08, 0x10 }, 2},
810ab4d1452SSatoshi Nagahama 		{{ 0x13, 0x00 }, 2},
811ab4d1452SSatoshi Nagahama 		{{ 0x17, 0x00 }, 2},
812ab4d1452SSatoshi Nagahama 		{{ 0x03, 0x01 }, 2},
813ab4d1452SSatoshi Nagahama 		{{ 0x10, 0xb1 }, 2},
814ab4d1452SSatoshi Nagahama 		{{ 0x11, 0x40 }, 2},
815ab4d1452SSatoshi Nagahama 		{{ 0x85, 0x7a }, 2},
816ab4d1452SSatoshi Nagahama 		{{ 0x87, 0x04 }, 2},
817ab4d1452SSatoshi Nagahama 	};
818ba0c8e6eSColin Ian King 	static const struct em28xx_reg_seq gpio[] = {
819ab4d1452SSatoshi Nagahama 		{EM28XX_R06_I2C_CLK,		0x40,	0xff,	300},
820ab4d1452SSatoshi Nagahama 		{EM2874_R80_GPIO_P0_CTRL,	0xfd,	0xff,	60},
821ab4d1452SSatoshi Nagahama 		{EM28XX_R15_RGAIN,		0x20,	0xff,	0},
822ab4d1452SSatoshi Nagahama 		{EM28XX_R16_GGAIN,		0x20,	0xff,	0},
823ab4d1452SSatoshi Nagahama 		{EM28XX_R17_BGAIN,		0x20,	0xff,	0},
824ab4d1452SSatoshi Nagahama 		{EM28XX_R18_ROFFSET,		0x00,	0xff,	0},
825ab4d1452SSatoshi Nagahama 		{EM28XX_R19_GOFFSET,		0x00,	0xff,	0},
826ab4d1452SSatoshi Nagahama 		{EM28XX_R1A_BOFFSET,		0x00,	0xff,	0},
827ab4d1452SSatoshi Nagahama 		{EM28XX_R23_UOFFSET,		0x00,	0xff,	0},
828ab4d1452SSatoshi Nagahama 		{EM28XX_R24_VOFFSET,		0x00,	0xff,	0},
829ab4d1452SSatoshi Nagahama 		{EM28XX_R26_COMPR,		0x00,	0xff,	0},
830ab4d1452SSatoshi Nagahama 		{0x13,				0x08,	0xff,	0},
831ab4d1452SSatoshi Nagahama 		{EM28XX_R12_VINENABLE,		0x27,	0xff,	0},
832ab4d1452SSatoshi Nagahama 		{EM28XX_R0C_USBSUSP,		0x10,	0xff,	0},
833ab4d1452SSatoshi Nagahama 		{EM28XX_R27_OUTFMT,		0x00,	0xff,	0},
834ab4d1452SSatoshi Nagahama 		{EM28XX_R10_VINMODE,		0x00,	0xff,	0},
835ab4d1452SSatoshi Nagahama 		{EM28XX_R11_VINCTRL,		0x11,	0xff,	0},
836ab4d1452SSatoshi Nagahama 		{EM2874_R50_IR_CONFIG,		0x01,	0xff,	0},
837ab4d1452SSatoshi Nagahama 		{EM2874_R5F_TS_ENABLE,		0x80,	0xff,	0},
838ab4d1452SSatoshi Nagahama 		{EM28XX_R06_I2C_CLK,		0x46,	0xff,	0},
839ab4d1452SSatoshi Nagahama 	};
840ab4d1452SSatoshi Nagahama 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46);
841ab4d1452SSatoshi Nagahama 	/* sleeping ISDB-T */
842ab4d1452SSatoshi Nagahama 	dev->dvb->i2c_client_demod->addr = 0x14;
843ab4d1452SSatoshi Nagahama 	for (i = 0; i < ARRAY_SIZE(regs1); i++)
844fe8d54f0SMauro Carvalho Chehab 		i2c_master_send(dev->dvb->i2c_client_demod,
845fe8d54f0SMauro Carvalho Chehab 				regs1[i].r, regs1[i].len);
846ab4d1452SSatoshi Nagahama 	/* sleeping ISDB-S */
847ab4d1452SSatoshi Nagahama 	dev->dvb->i2c_client_demod->addr = 0x15;
848ab4d1452SSatoshi Nagahama 	for (i = 0; i < ARRAY_SIZE(regs2); i++)
849ab4d1452SSatoshi Nagahama 		i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r,
850ab4d1452SSatoshi Nagahama 				regs2[i].len);
851ab4d1452SSatoshi Nagahama 	for (i = 0; i < ARRAY_SIZE(gpio); i++) {
852ab4d1452SSatoshi Nagahama 		em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val,
853ab4d1452SSatoshi Nagahama 				      gpio[i].mask);
854ab4d1452SSatoshi Nagahama 		if (gpio[i].sleep > 0)
855ab4d1452SSatoshi Nagahama 			msleep(gpio[i].sleep);
856ab4d1452SSatoshi Nagahama 	}
857ab4d1452SSatoshi Nagahama };
858ab4d1452SSatoshi Nagahama 
8594fb202a8SDevin Heitmueller static struct mt352_config terratec_xs_mt352_cfg = {
8604fb202a8SDevin Heitmueller 	.demod_address = (0x1e >> 1),
8614fb202a8SDevin Heitmueller 	.no_tuner = 1,
8624fb202a8SDevin Heitmueller 	.if2 = 45600,
863f2d0c1c6SJarod Wilson 	.demod_init = em28xx_mt352_terratec_xs_init,
8644fb202a8SDevin Heitmueller };
8654fb202a8SDevin Heitmueller 
866285eb1a4SAntti Palosaari static struct tda10023_config em28xx_tda10023_config = {
867285eb1a4SAntti Palosaari 	.demod_address = 0x0c,
868285eb1a4SAntti Palosaari 	.invert = 1,
869285eb1a4SAntti Palosaari };
870285eb1a4SAntti Palosaari 
871d6a5f921SAntti Palosaari static struct cxd2820r_config em28xx_cxd2820r_config = {
872d6a5f921SAntti Palosaari 	.i2c_address = (0xd8 >> 1),
873d6a5f921SAntti Palosaari 	.ts_mode = CXD2820R_TS_SERIAL,
874d6a5f921SAntti Palosaari };
875d6a5f921SAntti Palosaari 
876d6a5f921SAntti Palosaari static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
877d6a5f921SAntti Palosaari 	.output_opt = TDA18271_OUTPUT_LT_OFF,
8780db4bf42SSteve Kerrison 	.gate = TDA18271_GATE_DIGITAL,
879d6a5f921SAntti Palosaari };
880d6a5f921SAntti Palosaari 
8811985f6fbSAivar Päkk static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
8821985f6fbSAivar Päkk 	.demod_address = (0x1e >> 1),
8831985f6fbSAivar Päkk 	.disable_i2c_gate_ctrl = 1,
8841985f6fbSAivar Päkk 	.no_tuner = 1,
8851985f6fbSAivar Päkk 	.parallel_ts = 1,
8861985f6fbSAivar Päkk };
887fdf1bc9fSMauro Carvalho Chehab 
8888c47311dSAlberto Mardegan static struct mt2060_config em28xx_mt2060_config = {
8898c47311dSAlberto Mardegan 	.i2c_address = 0x60,
8908c47311dSAlberto Mardegan };
8918c47311dSAlberto Mardegan 
8921985f6fbSAivar Päkk static struct qt1010_config em28xx_qt1010_config = {
8931985f6fbSAivar Päkk 	.i2c_address = 0x62
8941985f6fbSAivar Päkk };
8951985f6fbSAivar Päkk 
8964159d01bSMauro Carvalho Chehab static const struct mb86a20s_config c3tech_duo_mb86a20s_config = {
8974159d01bSMauro Carvalho Chehab 	.demod_address = 0x10,
8984159d01bSMauro Carvalho Chehab 	.is_serial = true,
8994159d01bSMauro Carvalho Chehab };
9004159d01bSMauro Carvalho Chehab 
9014159d01bSMauro Carvalho Chehab static struct tda18271_std_map mb86a20s_tda18271_config = {
9024159d01bSMauro Carvalho Chehab 	.dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
9034159d01bSMauro Carvalho Chehab 		      .if_lvl = 1, .rfagc_top = 0x37, },
9044159d01bSMauro Carvalho Chehab };
9054159d01bSMauro Carvalho Chehab 
9064159d01bSMauro Carvalho Chehab static struct tda18271_config c3tech_duo_tda18271_config = {
9074159d01bSMauro Carvalho Chehab 	.std_map = &mb86a20s_tda18271_config,
9084159d01bSMauro Carvalho Chehab 	.gate    = TDA18271_GATE_DIGITAL,
9094159d01bSMauro Carvalho Chehab 	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
9104159d01bSMauro Carvalho Chehab };
9114159d01bSMauro Carvalho Chehab 
91238b2df95SDevin Heitmueller static struct tda18271_std_map drx_j_std_map = {
91338b2df95SDevin Heitmueller 	.atsc_6   = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1,
91438b2df95SDevin Heitmueller 		      .rfagc_top = 0x37, },
91538b2df95SDevin Heitmueller 	.qam_6    = { .if_freq = 5380, .agc_mode = 3, .std = 3, .if_lvl = 1,
91638b2df95SDevin Heitmueller 		      .rfagc_top = 0x37, },
91738b2df95SDevin Heitmueller };
91838b2df95SDevin Heitmueller 
91938b2df95SDevin Heitmueller static struct tda18271_config pinnacle_80e_dvb_config = {
92038b2df95SDevin Heitmueller 	.std_map = &drx_j_std_map,
92138b2df95SDevin Heitmueller 	.gate    = TDA18271_GATE_DIGITAL,
92238b2df95SDevin Heitmueller 	.role    = TDA18271_MASTER,
92338b2df95SDevin Heitmueller };
92438b2df95SDevin Heitmueller 
9251586342eSKevin Cheng static struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = {
9261586342eSKevin Cheng 	.qam_if_khz         = 4000,
9271586342eSKevin Cheng 	.vsb_if_khz         = 3250,
9281586342eSKevin Cheng 	.spectral_inversion = 0,
9291586342eSKevin Cheng 	.deny_i2c_rptr      = 0,
9301586342eSKevin Cheng 	.mpeg_mode          = LGDT3306A_MPEG_SERIAL,
9311586342eSKevin Cheng 	.tpclk_edge         = LGDT3306A_TPCLK_RISING_EDGE,
9321586342eSKevin Cheng 	.tpvalid_polarity   = LGDT3306A_TP_VALID_HIGH,
9331586342eSKevin Cheng 	.xtalMHz            = 25,
9341586342eSKevin Cheng };
9351586342eSKevin Cheng 
9363aefb79aSMauro Carvalho Chehab /* ------------------------------------------------------------------ */
9373aefb79aSMauro Carvalho Chehab 
em28xx_attach_xc3028(u8 addr,struct em28xx * dev)938f410b409SArnd Bergmann static noinline_for_stack int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
9393aefb79aSMauro Carvalho Chehab {
9403aefb79aSMauro Carvalho Chehab 	struct dvb_frontend *fe;
9413ca9c093SMauro Carvalho Chehab 	struct xc2028_config cfg;
942ee97207cSMauro Carvalho Chehab 	struct xc2028_ctrl ctl;
9433ca9c093SMauro Carvalho Chehab 
9443ca9c093SMauro Carvalho Chehab 	memset(&cfg, 0, sizeof(cfg));
945c7a45e5bSMauro Carvalho Chehab 	cfg.i2c_adap  = &dev->i2c_adap[dev->def_i2c_bus];
9463ca9c093SMauro Carvalho Chehab 	cfg.i2c_addr  = addr;
9473ca9c093SMauro Carvalho Chehab 
948ee97207cSMauro Carvalho Chehab 	memset(&ctl, 0, sizeof(ctl));
949ee97207cSMauro Carvalho Chehab 	em28xx_setup_xc3028(dev, &ctl);
950ee97207cSMauro Carvalho Chehab 	cfg.ctrl  = &ctl;
951ee97207cSMauro Carvalho Chehab 
952f71095beSAntti Palosaari 	if (!dev->dvb->fe[0]) {
95329b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev,
954ce8591ffSMauro Carvalho Chehab 			"dvb frontend not attached. Can't attach xc3028\n");
9553aefb79aSMauro Carvalho Chehab 		return -EINVAL;
9563aefb79aSMauro Carvalho Chehab 	}
9573aefb79aSMauro Carvalho Chehab 
958f71095beSAntti Palosaari 	fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
9593aefb79aSMauro Carvalho Chehab 	if (!fe) {
96029b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev, "xc3028 attach failed\n");
961f71095beSAntti Palosaari 		dvb_frontend_detach(dev->dvb->fe[0]);
962f71095beSAntti Palosaari 		dev->dvb->fe[0] = NULL;
9633aefb79aSMauro Carvalho Chehab 		return -EINVAL;
9643aefb79aSMauro Carvalho Chehab 	}
9653aefb79aSMauro Carvalho Chehab 
96629b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "xc3028 attached\n");
9673aefb79aSMauro Carvalho Chehab 
9683aefb79aSMauro Carvalho Chehab 	return 0;
9693aefb79aSMauro Carvalho Chehab }
9703aefb79aSMauro Carvalho Chehab 
9713421b778SAidan Thornton /* ------------------------------------------------------------------ */
9723421b778SAidan Thornton 
em28xx_register_dvb(struct em28xx_dvb * dvb,struct module * module,struct em28xx * dev,struct device * device)973f2d0c1c6SJarod Wilson static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
974f2d0c1c6SJarod Wilson 			       struct em28xx *dev, struct device *device)
9753421b778SAidan Thornton {
9763421b778SAidan Thornton 	int result;
977e9ef88bdSMauro Carvalho Chehab 	bool create_rf_connector = false;
9783421b778SAidan Thornton 
9793421b778SAidan Thornton 	mutex_init(&dvb->lock);
9803421b778SAidan Thornton 
9813421b778SAidan Thornton 	/* register adapter */
982ce8591ffSMauro Carvalho Chehab 	result = dvb_register_adapter(&dvb->adapter,
98329b05e22SMauro Carvalho Chehab 				      dev_name(&dev->intf->dev), module,
984ce8591ffSMauro Carvalho Chehab 				      device, adapter_nr);
9853421b778SAidan Thornton 	if (result < 0) {
98629b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
987ce8591ffSMauro Carvalho Chehab 			 "dvb_register_adapter failed (errno = %d)\n",
9882a96f60eSMauro Carvalho Chehab 			 result);
9893421b778SAidan Thornton 		goto fail_adapter;
9903421b778SAidan Thornton 	}
99137ecc7b1SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER_DVB
99237ecc7b1SMauro Carvalho Chehab 	dvb->adapter.mdev = dev->media_dev;
99337ecc7b1SMauro Carvalho Chehab #endif
994e3569abcSMauro Carvalho Chehab 
995e3569abcSMauro Carvalho Chehab 	/* Ensure all frontends negotiate bus access */
996f71095beSAntti Palosaari 	dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
997f71095beSAntti Palosaari 	if (dvb->fe[1])
998f71095beSAntti Palosaari 		dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
999e3569abcSMauro Carvalho Chehab 
10003de09fbbSHans Verkuil 	dvb->adapter.priv = &dev->i2c_bus[dev->def_i2c_bus];
10013421b778SAidan Thornton 
10023421b778SAidan Thornton 	/* register frontend */
1003f71095beSAntti Palosaari 	result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
10043421b778SAidan Thornton 	if (result < 0) {
100529b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1006ce8591ffSMauro Carvalho Chehab 			 "dvb_register_frontend failed (errno = %d)\n",
10072a96f60eSMauro Carvalho Chehab 			 result);
1008f71095beSAntti Palosaari 		goto fail_frontend0;
1009f71095beSAntti Palosaari 	}
1010f71095beSAntti Palosaari 
1011f71095beSAntti Palosaari 	/* register 2nd frontend */
1012f71095beSAntti Palosaari 	if (dvb->fe[1]) {
1013f71095beSAntti Palosaari 		result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
1014f71095beSAntti Palosaari 		if (result < 0) {
101529b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
1016ce8591ffSMauro Carvalho Chehab 				 "2nd dvb_register_frontend failed (errno = %d)\n",
10172a96f60eSMauro Carvalho Chehab 				 result);
1018f71095beSAntti Palosaari 			goto fail_frontend1;
1019f71095beSAntti Palosaari 		}
10203421b778SAidan Thornton 	}
10213421b778SAidan Thornton 
10223421b778SAidan Thornton 	/* register demux stuff */
10233421b778SAidan Thornton 	dvb->demux.dmx.capabilities =
10243421b778SAidan Thornton 		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
10253421b778SAidan Thornton 		DMX_MEMORY_BASED_FILTERING;
10263421b778SAidan Thornton 	dvb->demux.priv       = dvb;
10273421b778SAidan Thornton 	dvb->demux.filternum  = 256;
10283421b778SAidan Thornton 	dvb->demux.feednum    = 256;
1029f2d0c1c6SJarod Wilson 	dvb->demux.start_feed = em28xx_start_feed;
1030f2d0c1c6SJarod Wilson 	dvb->demux.stop_feed  = em28xx_stop_feed;
1031e3569abcSMauro Carvalho Chehab 
10323421b778SAidan Thornton 	result = dvb_dmx_init(&dvb->demux);
10333421b778SAidan Thornton 	if (result < 0) {
103429b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1035ce8591ffSMauro Carvalho Chehab 			 "dvb_dmx_init failed (errno = %d)\n",
1036ce8591ffSMauro Carvalho Chehab 			 result);
10373421b778SAidan Thornton 		goto fail_dmx;
10383421b778SAidan Thornton 	}
10393421b778SAidan Thornton 
10403421b778SAidan Thornton 	dvb->dmxdev.filternum    = 256;
10413421b778SAidan Thornton 	dvb->dmxdev.demux        = &dvb->demux.dmx;
10423421b778SAidan Thornton 	dvb->dmxdev.capabilities = 0;
10433421b778SAidan Thornton 	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
10443421b778SAidan Thornton 	if (result < 0) {
104529b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1046ce8591ffSMauro Carvalho Chehab 			 "dvb_dmxdev_init failed (errno = %d)\n",
1047ce8591ffSMauro Carvalho Chehab 			 result);
10483421b778SAidan Thornton 		goto fail_dmxdev;
10493421b778SAidan Thornton 	}
10503421b778SAidan Thornton 
10513421b778SAidan Thornton 	dvb->fe_hw.source = DMX_FRONTEND_0;
10523421b778SAidan Thornton 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
10533421b778SAidan Thornton 	if (result < 0) {
105429b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1055ce8591ffSMauro Carvalho Chehab 			 "add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
10562a96f60eSMauro Carvalho Chehab 			 result);
10573421b778SAidan Thornton 		goto fail_fe_hw;
10583421b778SAidan Thornton 	}
10593421b778SAidan Thornton 
10603421b778SAidan Thornton 	dvb->fe_mem.source = DMX_MEMORY_FE;
10613421b778SAidan Thornton 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
10623421b778SAidan Thornton 	if (result < 0) {
106329b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1064ce8591ffSMauro Carvalho Chehab 			 "add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
10652a96f60eSMauro Carvalho Chehab 			 result);
10663421b778SAidan Thornton 		goto fail_fe_mem;
10673421b778SAidan Thornton 	}
10683421b778SAidan Thornton 
10693421b778SAidan Thornton 	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
10703421b778SAidan Thornton 	if (result < 0) {
107129b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
1072ce8591ffSMauro Carvalho Chehab 			 "connect_frontend failed (errno = %d)\n",
1073ce8591ffSMauro Carvalho Chehab 			 result);
10743421b778SAidan Thornton 		goto fail_fe_conn;
10753421b778SAidan Thornton 	}
10763421b778SAidan Thornton 
10773421b778SAidan Thornton 	/* register network adapter */
10783421b778SAidan Thornton 	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
107937ecc7b1SMauro Carvalho Chehab 
1080e9ef88bdSMauro Carvalho Chehab 	/* If the analog part won't create RF connectors, DVB will do it */
1081fe8d54f0SMauro Carvalho Chehab 	if (!dev->has_video || dev->tuner_type == TUNER_ABSENT)
1082e9ef88bdSMauro Carvalho Chehab 		create_rf_connector = true;
1083e9ef88bdSMauro Carvalho Chehab 
1084e9ef88bdSMauro Carvalho Chehab 	result = dvb_create_media_graph(&dvb->adapter, create_rf_connector);
108537ecc7b1SMauro Carvalho Chehab 	if (result < 0)
108637ecc7b1SMauro Carvalho Chehab 		goto fail_create_graph;
108737ecc7b1SMauro Carvalho Chehab 
10883421b778SAidan Thornton 	return 0;
10893421b778SAidan Thornton 
109037ecc7b1SMauro Carvalho Chehab fail_create_graph:
109137ecc7b1SMauro Carvalho Chehab 	dvb_net_release(&dvb->net);
10923421b778SAidan Thornton fail_fe_conn:
10933421b778SAidan Thornton 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
10943421b778SAidan Thornton fail_fe_mem:
10953421b778SAidan Thornton 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
10963421b778SAidan Thornton fail_fe_hw:
10973421b778SAidan Thornton 	dvb_dmxdev_release(&dvb->dmxdev);
10983421b778SAidan Thornton fail_dmxdev:
10993421b778SAidan Thornton 	dvb_dmx_release(&dvb->demux);
11003421b778SAidan Thornton fail_dmx:
1101f71095beSAntti Palosaari 	if (dvb->fe[1])
1102f71095beSAntti Palosaari 		dvb_unregister_frontend(dvb->fe[1]);
1103f71095beSAntti Palosaari 	dvb_unregister_frontend(dvb->fe[0]);
1104f71095beSAntti Palosaari fail_frontend1:
1105f71095beSAntti Palosaari 	if (dvb->fe[1])
1106f71095beSAntti Palosaari 		dvb_frontend_detach(dvb->fe[1]);
1107f71095beSAntti Palosaari fail_frontend0:
1108f71095beSAntti Palosaari 	dvb_frontend_detach(dvb->fe[0]);
11093421b778SAidan Thornton 	dvb_unregister_adapter(&dvb->adapter);
11103421b778SAidan Thornton fail_adapter:
11113421b778SAidan Thornton 	return result;
11123421b778SAidan Thornton }
11133421b778SAidan Thornton 
em28xx_unregister_dvb(struct em28xx_dvb * dvb)1114f2d0c1c6SJarod Wilson static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
11153421b778SAidan Thornton {
11163421b778SAidan Thornton 	dvb_net_release(&dvb->net);
11173421b778SAidan Thornton 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
11183421b778SAidan Thornton 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
11193421b778SAidan Thornton 	dvb_dmxdev_release(&dvb->dmxdev);
11203421b778SAidan Thornton 	dvb_dmx_release(&dvb->demux);
1121f71095beSAntti Palosaari 	if (dvb->fe[1])
1122f71095beSAntti Palosaari 		dvb_unregister_frontend(dvb->fe[1]);
1123f71095beSAntti Palosaari 	dvb_unregister_frontend(dvb->fe[0]);
1124c4c3a3d3SMauro Carvalho Chehab 	if (dvb->fe[1] && !dvb->dont_attach_fe1)
1125f71095beSAntti Palosaari 		dvb_frontend_detach(dvb->fe[1]);
1126f71095beSAntti Palosaari 	dvb_frontend_detach(dvb->fe[0]);
11273421b778SAidan Thornton 	dvb_unregister_adapter(&dvb->adapter);
11283421b778SAidan Thornton }
11293421b778SAidan Thornton 
em28174_dvb_init_pctv_460e(struct em28xx * dev)1130ad32495bSMauro Carvalho Chehab static int em28174_dvb_init_pctv_460e(struct em28xx *dev)
1131f410b409SArnd Bergmann {
1132f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1133f410b409SArnd Bergmann 	struct tda10071_platform_data tda10071_pdata = {};
1134f410b409SArnd Bergmann 	struct a8293_platform_data a8293_pdata = {};
1135f410b409SArnd Bergmann 
1136f410b409SArnd Bergmann 	/* attach demod + tuner combo */
1137ad32495bSMauro Carvalho Chehab 	tda10071_pdata.clk = 40444000; /* 40.444 MHz */
1138ad32495bSMauro Carvalho Chehab 	tda10071_pdata.i2c_wr_max = 64;
1139ad32495bSMauro Carvalho Chehab 	tda10071_pdata.ts_mode = TDA10071_TS_SERIAL;
1140ad32495bSMauro Carvalho Chehab 	tda10071_pdata.pll_multiplier = 20;
1141ad32495bSMauro Carvalho Chehab 	tda10071_pdata.tuner_i2c_addr = 0x14;
1142ad32495bSMauro Carvalho Chehab 
1143ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("tda10071", "tda10071_cx24118",
1144ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1145ad32495bSMauro Carvalho Chehab 						 0x55, &tda10071_pdata);
1146ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1147ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1148ad32495bSMauro Carvalho Chehab 
1149ad32495bSMauro Carvalho Chehab 	dvb->fe[0] = tda10071_pdata.get_dvb_frontend(dvb->i2c_client_demod);
1150f410b409SArnd Bergmann 
1151f410b409SArnd Bergmann 	/* attach SEC */
1152f410b409SArnd Bergmann 	a8293_pdata.dvb_frontend = dvb->fe[0];
1153ad32495bSMauro Carvalho Chehab 
1154ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
1155ad32495bSMauro Carvalho Chehab 					       &dev->i2c_adap[dev->def_i2c_bus],
1156ad32495bSMauro Carvalho Chehab 					       0x08, &a8293_pdata);
1157ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_sec) {
1158ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1159ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1160f410b409SArnd Bergmann 	}
1161f410b409SArnd Bergmann 
1162ad32495bSMauro Carvalho Chehab 	return 0;
1163ad32495bSMauro Carvalho Chehab }
1164ad32495bSMauro Carvalho Chehab 
em28178_dvb_init_pctv_461e(struct em28xx * dev)1165ad32495bSMauro Carvalho Chehab static int em28178_dvb_init_pctv_461e(struct em28xx *dev)
1166f410b409SArnd Bergmann {
1167f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1168f410b409SArnd Bergmann 	struct i2c_adapter *i2c_adapter;
1169f410b409SArnd Bergmann 	struct m88ds3103_platform_data m88ds3103_pdata = {};
1170f410b409SArnd Bergmann 	struct ts2020_config ts2020_config = {};
1171f410b409SArnd Bergmann 	struct a8293_platform_data a8293_pdata = {};
1172f410b409SArnd Bergmann 
1173f410b409SArnd Bergmann 	/* attach demod */
1174f410b409SArnd Bergmann 	m88ds3103_pdata.clk = 27000000;
1175f410b409SArnd Bergmann 	m88ds3103_pdata.i2c_wr_max = 33;
1176f410b409SArnd Bergmann 	m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
1177f410b409SArnd Bergmann 	m88ds3103_pdata.ts_clk = 16000;
1178f410b409SArnd Bergmann 	m88ds3103_pdata.ts_clk_pol = 1;
1179f410b409SArnd Bergmann 	m88ds3103_pdata.agc = 0x99;
1180ad32495bSMauro Carvalho Chehab 
1181ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("m88ds3103", NULL,
1182ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1183ad32495bSMauro Carvalho Chehab 						 0x68, &m88ds3103_pdata);
1184ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1185ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1186ad32495bSMauro Carvalho Chehab 
1187ad32495bSMauro Carvalho Chehab 	dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod);
1188ad32495bSMauro Carvalho Chehab 	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod);
1189f410b409SArnd Bergmann 
1190f410b409SArnd Bergmann 	/* attach tuner */
1191f410b409SArnd Bergmann 	ts2020_config.fe = dvb->fe[0];
1192ad32495bSMauro Carvalho Chehab 
1193ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022",
1194ad32495bSMauro Carvalho Chehab 						 i2c_adapter,
1195ad32495bSMauro Carvalho Chehab 						 0x60, &ts2020_config);
1196ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1197ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1198ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1199f410b409SArnd Bergmann 	}
1200ad32495bSMauro Carvalho Chehab 
1201f410b409SArnd Bergmann 	/* delegate signal strength measurement to tuner */
1202f410b409SArnd Bergmann 	dvb->fe[0]->ops.read_signal_strength =
1203f410b409SArnd Bergmann 			dvb->fe[0]->ops.tuner_ops.get_rf_strength;
1204f410b409SArnd Bergmann 
1205f410b409SArnd Bergmann 	/* attach SEC */
1206f410b409SArnd Bergmann 	a8293_pdata.dvb_frontend = dvb->fe[0];
1207*e6431a0cSChuck Ritola 	/*
1208*e6431a0cSChuck Ritola 	 * 461e has a tendency to have vIN undervoltage troubles.
1209*e6431a0cSChuck Ritola 	 * Slew mitigates this.
1210*e6431a0cSChuck Ritola 	 */
1211*e6431a0cSChuck Ritola 	a8293_pdata.volt_slew_nanos_per_mv = 20;
1212*e6431a0cSChuck Ritola 
1213ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
1214ad32495bSMauro Carvalho Chehab 					       &dev->i2c_adap[dev->def_i2c_bus],
1215ad32495bSMauro Carvalho Chehab 					       0x08, &a8293_pdata);
1216ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_sec) {
1217ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_tuner);
1218ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1219ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1220f410b409SArnd Bergmann 	}
1221f410b409SArnd Bergmann 
1222ad32495bSMauro Carvalho Chehab 	return 0;
1223ad32495bSMauro Carvalho Chehab }
1224ad32495bSMauro Carvalho Chehab 
em28178_dvb_init_pctv_461e_v2(struct em28xx * dev)1225985b0edeSBrad Love static int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev)
1226985b0edeSBrad Love {
1227985b0edeSBrad Love 	struct em28xx_dvb *dvb = dev->dvb;
1228985b0edeSBrad Love 	struct i2c_adapter *i2c_adapter;
1229985b0edeSBrad Love 	struct m88ds3103_platform_data m88ds3103_pdata = {};
1230985b0edeSBrad Love 	struct ts2020_config ts2020_config = {};
1231985b0edeSBrad Love 	struct a8293_platform_data a8293_pdata = {};
1232985b0edeSBrad Love 
1233985b0edeSBrad Love 	/* attach demod */
1234985b0edeSBrad Love 	m88ds3103_pdata.clk = 27000000;
1235985b0edeSBrad Love 	m88ds3103_pdata.i2c_wr_max = 33;
1236985b0edeSBrad Love 	m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
1237985b0edeSBrad Love 	m88ds3103_pdata.ts_clk = 16000;
1238985b0edeSBrad Love 	m88ds3103_pdata.ts_clk_pol = 0;
1239985b0edeSBrad Love 	m88ds3103_pdata.agc = 0x99;
1240985b0edeSBrad Love 	m88ds3103_pdata.agc_inv = 0;
1241985b0edeSBrad Love 	m88ds3103_pdata.spec_inv = 0;
1242985b0edeSBrad Love 	dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b",
1243985b0edeSBrad Love 						 &dev->i2c_adap[dev->def_i2c_bus],
1244985b0edeSBrad Love 						 0x6a, &m88ds3103_pdata);
1245985b0edeSBrad Love 
1246985b0edeSBrad Love 	if (!dvb->i2c_client_demod)
1247985b0edeSBrad Love 		return -ENODEV;
1248985b0edeSBrad Love 
1249985b0edeSBrad Love 	dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod);
1250985b0edeSBrad Love 	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod);
1251985b0edeSBrad Love 
1252985b0edeSBrad Love 	/* attach tuner */
1253985b0edeSBrad Love 	ts2020_config.fe = dvb->fe[0];
1254985b0edeSBrad Love 	dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022",
1255985b0edeSBrad Love 						 i2c_adapter,
1256985b0edeSBrad Love 						 0x60, &ts2020_config);
1257985b0edeSBrad Love 	if (!dvb->i2c_client_tuner) {
1258985b0edeSBrad Love 		dvb_module_release(dvb->i2c_client_demod);
1259985b0edeSBrad Love 		return -ENODEV;
1260985b0edeSBrad Love 	}
1261985b0edeSBrad Love 
1262985b0edeSBrad Love 	/* delegate signal strength measurement to tuner */
1263985b0edeSBrad Love 	dvb->fe[0]->ops.read_signal_strength =
1264985b0edeSBrad Love 			dvb->fe[0]->ops.tuner_ops.get_rf_strength;
1265985b0edeSBrad Love 
1266985b0edeSBrad Love 	/* attach SEC */
1267985b0edeSBrad Love 	a8293_pdata.dvb_frontend = dvb->fe[0];
1268985b0edeSBrad Love 	dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
1269985b0edeSBrad Love 					       &dev->i2c_adap[dev->def_i2c_bus],
1270985b0edeSBrad Love 					       0x08, &a8293_pdata);
1271985b0edeSBrad Love 	if (!dvb->i2c_client_sec) {
1272985b0edeSBrad Love 		dvb_module_release(dvb->i2c_client_tuner);
1273985b0edeSBrad Love 		dvb_module_release(dvb->i2c_client_demod);
1274985b0edeSBrad Love 		return -ENODEV;
1275985b0edeSBrad Love 	}
1276985b0edeSBrad Love 
1277985b0edeSBrad Love 	return 0;
1278985b0edeSBrad Love }
1279985b0edeSBrad Love 
em28178_dvb_init_pctv_292e(struct em28xx * dev)1280ad32495bSMauro Carvalho Chehab static int em28178_dvb_init_pctv_292e(struct em28xx *dev)
1281f410b409SArnd Bergmann {
1282f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1283f410b409SArnd Bergmann 	struct i2c_adapter *adapter;
1284ad32495bSMauro Carvalho Chehab 	struct si2168_config si2168_config = {};
1285ad32495bSMauro Carvalho Chehab 	struct si2157_config si2157_config = {};
1286f410b409SArnd Bergmann 
1287f410b409SArnd Bergmann 	/* attach demod */
1288f410b409SArnd Bergmann 	si2168_config.i2c_adapter = &adapter;
1289f410b409SArnd Bergmann 	si2168_config.fe = &dvb->fe[0];
1290f410b409SArnd Bergmann 	si2168_config.ts_mode = SI2168_TS_PARALLEL;
1291309d4c4cSBrad Love 	si2168_config.spectral_inversion = true;
1292f410b409SArnd Bergmann 
1293ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
1294ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1295ad32495bSMauro Carvalho Chehab 						 0x64, &si2168_config);
1296ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1297ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1298f410b409SArnd Bergmann 
1299f410b409SArnd Bergmann 	/* attach tuner */
1300f410b409SArnd Bergmann 	si2157_config.fe = dvb->fe[0];
1301f410b409SArnd Bergmann 	si2157_config.if_port = 1;
1302f410b409SArnd Bergmann #ifdef CONFIG_MEDIA_CONTROLLER_DVB
1303f410b409SArnd Bergmann 	si2157_config.mdev = dev->media_dev;
1304f410b409SArnd Bergmann #endif
1305ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
1306ad32495bSMauro Carvalho Chehab 						 adapter,
1307ad32495bSMauro Carvalho Chehab 						 0x60, &si2157_config);
1308ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1309ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1310ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1311f410b409SArnd Bergmann 	}
1312f410b409SArnd Bergmann 	dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
1313ad32495bSMauro Carvalho Chehab 
1314ad32495bSMauro Carvalho Chehab 	return 0;
1315f410b409SArnd Bergmann }
1316f410b409SArnd Bergmann 
em28178_dvb_init_terratec_t2_stick_hd(struct em28xx * dev)1317ad32495bSMauro Carvalho Chehab static int em28178_dvb_init_terratec_t2_stick_hd(struct em28xx *dev)
1318f410b409SArnd Bergmann {
1319f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1320f410b409SArnd Bergmann 	struct i2c_adapter *adapter;
1321ad32495bSMauro Carvalho Chehab 	struct si2168_config si2168_config = {};
1322ad32495bSMauro Carvalho Chehab 	struct si2157_config si2157_config = {};
1323f410b409SArnd Bergmann 
1324f410b409SArnd Bergmann 	/* attach demod */
1325f410b409SArnd Bergmann 	si2168_config.i2c_adapter = &adapter;
1326f410b409SArnd Bergmann 	si2168_config.fe = &dvb->fe[0];
1327f410b409SArnd Bergmann 	si2168_config.ts_mode = SI2168_TS_PARALLEL;
1328f410b409SArnd Bergmann 
1329ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
1330ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1331ad32495bSMauro Carvalho Chehab 						 0x64, &si2168_config);
1332ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1333ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1334f410b409SArnd Bergmann 
1335f410b409SArnd Bergmann 	/* attach tuner */
1336f410b409SArnd Bergmann 	memset(&si2157_config, 0, sizeof(si2157_config));
1337f410b409SArnd Bergmann 	si2157_config.fe = dvb->fe[0];
1338f410b409SArnd Bergmann 	si2157_config.if_port = 0;
1339f410b409SArnd Bergmann #ifdef CONFIG_MEDIA_CONTROLLER_DVB
1340f410b409SArnd Bergmann 	si2157_config.mdev = dev->media_dev;
1341f410b409SArnd Bergmann #endif
1342ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("si2157", "si2146",
1343ad32495bSMauro Carvalho Chehab 						 adapter,
1344ad32495bSMauro Carvalho Chehab 						 0x60, &si2157_config);
1345ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1346ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1347ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1348f410b409SArnd Bergmann 	}
1349f410b409SArnd Bergmann 
1350ad32495bSMauro Carvalho Chehab 	return 0;
1351f410b409SArnd Bergmann }
1352f410b409SArnd Bergmann 
em28178_dvb_init_plex_px_bcud(struct em28xx * dev)1353ad32495bSMauro Carvalho Chehab static int em28178_dvb_init_plex_px_bcud(struct em28xx *dev)
1354f410b409SArnd Bergmann {
1355f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1356ad32495bSMauro Carvalho Chehab 	struct tc90522_config tc90522_config = {};
1357ad32495bSMauro Carvalho Chehab 	struct qm1d1c0042_config qm1d1c0042_config = {};
1358f410b409SArnd Bergmann 
1359f410b409SArnd Bergmann 	/* attach demod */
1360ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("tc90522", "tc90522sat",
1361ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1362ad32495bSMauro Carvalho Chehab 						 0x15, &tc90522_config);
1363ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1364ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1365f410b409SArnd Bergmann 
1366f410b409SArnd Bergmann 	/* attach tuner */
1367f410b409SArnd Bergmann 	qm1d1c0042_config.fe = tc90522_config.fe;
1368f410b409SArnd Bergmann 	qm1d1c0042_config.lpf = 1;
1369ad32495bSMauro Carvalho Chehab 
1370ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("qm1d1c0042", NULL,
1371ad32495bSMauro Carvalho Chehab 						 tc90522_config.tuner_i2c,
1372ad32495bSMauro Carvalho Chehab 						 0x61, &qm1d1c0042_config);
1373ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1374ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1375ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1376f410b409SArnd Bergmann 	}
1377f410b409SArnd Bergmann 
1378ad32495bSMauro Carvalho Chehab 	dvb->fe[0] = tc90522_config.fe;
1379ad32495bSMauro Carvalho Chehab 	px_bcud_init(dev);
1380ad32495bSMauro Carvalho Chehab 
1381ad32495bSMauro Carvalho Chehab 	return 0;
1382ad32495bSMauro Carvalho Chehab }
1383ad32495bSMauro Carvalho Chehab 
em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx * dev)1384ad32495bSMauro Carvalho Chehab static int em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx *dev)
1385f410b409SArnd Bergmann {
1386f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1387f410b409SArnd Bergmann 	struct i2c_adapter *adapter;
1388ad32495bSMauro Carvalho Chehab 	struct si2168_config si2168_config = {};
1389ad32495bSMauro Carvalho Chehab 	struct si2157_config si2157_config = {};
1390ad32495bSMauro Carvalho Chehab 	unsigned char addr;
1391f410b409SArnd Bergmann 
1392f410b409SArnd Bergmann 	/* attach demod */
1393f410b409SArnd Bergmann 	si2168_config.i2c_adapter = &adapter;
1394f410b409SArnd Bergmann 	si2168_config.fe = &dvb->fe[0];
1395f410b409SArnd Bergmann 	si2168_config.ts_mode = SI2168_TS_SERIAL;
1396309d4c4cSBrad Love 	si2168_config.spectral_inversion = true;
1397ad32495bSMauro Carvalho Chehab 	addr = (dev->ts == PRIMARY_TS) ? 0x64 : 0x67;
1398f410b409SArnd Bergmann 
1399ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
1400ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1401ad32495bSMauro Carvalho Chehab 						 addr, &si2168_config);
1402ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1403ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1404f410b409SArnd Bergmann 
1405f410b409SArnd Bergmann 	/* attach tuner */
1406f410b409SArnd Bergmann 	memset(&si2157_config, 0, sizeof(si2157_config));
1407f410b409SArnd Bergmann 	si2157_config.fe = dvb->fe[0];
1408f410b409SArnd Bergmann 	si2157_config.if_port = 1;
1409f410b409SArnd Bergmann #ifdef CONFIG_MEDIA_CONTROLLER_DVB
1410f410b409SArnd Bergmann 	si2157_config.mdev = dev->media_dev;
1411f410b409SArnd Bergmann #endif
1412ad32495bSMauro Carvalho Chehab 	addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63;
1413ad32495bSMauro Carvalho Chehab 
1414ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
1415ad32495bSMauro Carvalho Chehab 						 adapter,
1416ad32495bSMauro Carvalho Chehab 						 addr, &si2157_config);
1417ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1418ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1419ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1420f410b409SArnd Bergmann 	}
1421f410b409SArnd Bergmann 
1422ad32495bSMauro Carvalho Chehab 	return 0;
1423f410b409SArnd Bergmann }
1424f410b409SArnd Bergmann 
em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx * dev)1425f410b409SArnd Bergmann static int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev)
1426f410b409SArnd Bergmann {
1427f410b409SArnd Bergmann 	struct em28xx_dvb *dvb = dev->dvb;
1428f410b409SArnd Bergmann 	struct i2c_adapter *adapter;
1429ad32495bSMauro Carvalho Chehab 	struct lgdt3306a_config lgdt3306a_config =  {};
1430f410b409SArnd Bergmann 	struct si2157_config si2157_config = {};
1431ad32495bSMauro Carvalho Chehab 	unsigned char addr;
1432f410b409SArnd Bergmann 
1433f410b409SArnd Bergmann 	/* attach demod */
1434f410b409SArnd Bergmann 	lgdt3306a_config = hauppauge_01595_lgdt3306a_config;
1435f410b409SArnd Bergmann 	lgdt3306a_config.fe = &dvb->fe[0];
1436f410b409SArnd Bergmann 	lgdt3306a_config.i2c_adapter = &adapter;
1437ad32495bSMauro Carvalho Chehab 	addr = (dev->ts == PRIMARY_TS) ? 0x59 : 0x0e;
1438f410b409SArnd Bergmann 
1439ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_demod = dvb_module_probe("lgdt3306a", NULL,
1440ad32495bSMauro Carvalho Chehab 						 &dev->i2c_adap[dev->def_i2c_bus],
1441ad32495bSMauro Carvalho Chehab 						 addr, &lgdt3306a_config);
1442ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_demod)
1443ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1444f410b409SArnd Bergmann 
1445f410b409SArnd Bergmann 	/* attach tuner */
1446f410b409SArnd Bergmann 	si2157_config.fe = dvb->fe[0];
1447f410b409SArnd Bergmann 	si2157_config.if_port = 1;
1448f410b409SArnd Bergmann 	si2157_config.inversion = 1;
1449f410b409SArnd Bergmann #ifdef CONFIG_MEDIA_CONTROLLER_DVB
1450f410b409SArnd Bergmann 	si2157_config.mdev = dev->media_dev;
1451f410b409SArnd Bergmann #endif
1452ad32495bSMauro Carvalho Chehab 	addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x62;
1453f410b409SArnd Bergmann 
1454ad32495bSMauro Carvalho Chehab 	dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
1455ad32495bSMauro Carvalho Chehab 						 adapter,
145601affb00SBrad Love 						 addr, &si2157_config);
1457ad32495bSMauro Carvalho Chehab 	if (!dvb->i2c_client_tuner) {
1458ad32495bSMauro Carvalho Chehab 		dvb_module_release(dvb->i2c_client_demod);
1459ad32495bSMauro Carvalho Chehab 		return -ENODEV;
1460f410b409SArnd Bergmann 	}
1461f410b409SArnd Bergmann 
1462ad32495bSMauro Carvalho Chehab 	return 0;
1463f410b409SArnd Bergmann }
1464ad32495bSMauro Carvalho Chehab 
em2874_dvb_init_hauppauge_usb_quadhd(struct em28xx * dev)14652e74a01fSBrad Love static int em2874_dvb_init_hauppauge_usb_quadhd(struct em28xx *dev)
14662e74a01fSBrad Love {
14672e74a01fSBrad Love 	struct em28xx_dvb *dvb = dev->dvb;
14682e74a01fSBrad Love 	struct mxl692_config mxl692_config = {};
14692e74a01fSBrad Love 	unsigned char addr;
14702e74a01fSBrad Love 
14712e74a01fSBrad Love 	/* attach demod/tuner combo */
14722e74a01fSBrad Love 	mxl692_config.id = (dev->ts == PRIMARY_TS) ? 0 : 1;
14732e74a01fSBrad Love 	mxl692_config.fe = &dvb->fe[0];
14742e74a01fSBrad Love 	addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63;
14752e74a01fSBrad Love 
14762e74a01fSBrad Love 	dvb->i2c_client_demod = dvb_module_probe("mxl692", NULL,
14772e74a01fSBrad Love 						 &dev->i2c_adap[dev->def_i2c_bus],
14782e74a01fSBrad Love 						 addr, &mxl692_config);
14792e74a01fSBrad Love 	if (!dvb->i2c_client_demod)
14802e74a01fSBrad Love 		return -ENODEV;
14812e74a01fSBrad Love 
14822e74a01fSBrad Love 	return 0;
14832e74a01fSBrad Love }
14842e74a01fSBrad Love 
em28xx_dvb_init(struct em28xx * dev)1485f2d0c1c6SJarod Wilson static int em28xx_dvb_init(struct em28xx *dev)
14863aefb79aSMauro Carvalho Chehab {
1487be7fd3c3SBrad Love 	int result = 0, dvb_alt = 0;
14883421b778SAidan Thornton 	struct em28xx_dvb *dvb;
1489be7fd3c3SBrad Love 	struct usb_device *udev;
14903aefb79aSMauro Carvalho Chehab 
1491822b8deaSMauro Carvalho Chehab 	if (dev->is_audio_only) {
1492822b8deaSMauro Carvalho Chehab 		/* Shouldn't initialize IR for this interface */
1493822b8deaSMauro Carvalho Chehab 		return 0;
1494822b8deaSMauro Carvalho Chehab 	}
1495822b8deaSMauro Carvalho Chehab 
1496505b6d0bSMauro Carvalho Chehab 	if (!dev->board.has_dvb) {
1497df619181SDevin Heitmueller 		/* This device does not support the extension */
1498df619181SDevin Heitmueller 		return 0;
1499df619181SDevin Heitmueller 	}
1500df619181SDevin Heitmueller 
150129b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "Binding DVB extension\n");
15029634614fSMauro Carvalho Chehab 
1503fe8d54f0SMauro Carvalho Chehab 	dvb = kzalloc(sizeof(*dvb), GFP_KERNEL);
15048314d402SMauro Carvalho Chehab 	if (!dvb)
15053421b778SAidan Thornton 		return -ENOMEM;
15068314d402SMauro Carvalho Chehab 
15073421b778SAidan Thornton 	dev->dvb = dvb;
1508fe8d54f0SMauro Carvalho Chehab 	dvb->fe[0] = NULL;
1509fe8d54f0SMauro Carvalho Chehab 	dvb->fe[1] = NULL;
15103aefb79aSMauro Carvalho Chehab 
151127ba0dacSFrank Schaefer 	/* pre-allocate DVB usb transfer buffers */
151227ba0dacSFrank Schaefer 	if (dev->dvb_xfer_bulk) {
151327ba0dacSFrank Schaefer 		result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE,
151427ba0dacSFrank Schaefer 					   dev->dvb_xfer_bulk,
151527ba0dacSFrank Schaefer 					   EM28XX_DVB_NUM_BUFS,
151627ba0dacSFrank Schaefer 					   512,
151727ba0dacSFrank Schaefer 					   EM28XX_DVB_BULK_PACKET_MULTIPLIER);
151827ba0dacSFrank Schaefer 	} else {
151927ba0dacSFrank Schaefer 		result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE,
152027ba0dacSFrank Schaefer 					   dev->dvb_xfer_bulk,
152127ba0dacSFrank Schaefer 					   EM28XX_DVB_NUM_BUFS,
152227ba0dacSFrank Schaefer 					   dev->dvb_max_pkt_size_isoc,
152327ba0dacSFrank Schaefer 					   EM28XX_DVB_NUM_ISOC_PACKETS);
152427ba0dacSFrank Schaefer 	}
152527ba0dacSFrank Schaefer 	if (result) {
152629b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev,
1527ce8591ffSMauro Carvalho Chehab 			"failed to pre-allocate USB transfer buffers for DVB.\n");
152827ba0dacSFrank Schaefer 		kfree(dvb);
152927ba0dacSFrank Schaefer 		dev->dvb = NULL;
153027ba0dacSFrank Schaefer 		return result;
153127ba0dacSFrank Schaefer 	}
153227ba0dacSFrank Schaefer 
15335013318cSMauro Carvalho Chehab 	mutex_lock(&dev->lock);
1534c67ec53fSMauro Carvalho Chehab 	em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
15353aefb79aSMauro Carvalho Chehab 	/* init frontend */
15363aefb79aSMauro Carvalho Chehab 	switch (dev->model) {
1537ebaefdb7SMauro Carvalho Chehab 	case EM2874_BOARD_LEADERSHIP_ISDBT:
1538f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(s921_attach,
1539fe8d54f0SMauro Carvalho Chehab 					&sharp_isdbt,
1540fe8d54f0SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1541ca3dfd6aSMauro Carvalho Chehab 
1542f71095beSAntti Palosaari 		if (!dvb->fe[0]) {
1543ca3dfd6aSMauro Carvalho Chehab 			result = -EINVAL;
1544ca3dfd6aSMauro Carvalho Chehab 			goto out_free;
1545ca3dfd6aSMauro Carvalho Chehab 		}
1546ca3dfd6aSMauro Carvalho Chehab 
1547ca3dfd6aSMauro Carvalho Chehab 		break;
1548f89bc329SDouglas Schilling Landgraf 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
154910ac6603SMauro Carvalho Chehab 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
15504fd305b2SDevin Heitmueller 	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
1551e14b3658SDevin Heitmueller 	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
1552f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
1553227ad4abSMauro Carvalho Chehab 					&em2880_lgdt3303_dev,
155423ba635dSMauro Carvalho Chehab 					0x0e,
1555c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1556f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
15573421b778SAidan Thornton 			result = -EINVAL;
15583421b778SAidan Thornton 			goto out_free;
15593421b778SAidan Thornton 		}
1560227ad4abSMauro Carvalho Chehab 		break;
156146510b56SThierry MERLE 	case EM2880_BOARD_KWORLD_DVB_310U:
1562f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(zl10353_attach,
15637e6388a1SAidan Thornton 					&em28xx_zl10353_with_xc3028,
1564c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1565f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
15663421b778SAidan Thornton 			result = -EINVAL;
15673421b778SAidan Thornton 			goto out_free;
15683421b778SAidan Thornton 		}
15697e6388a1SAidan Thornton 		break;
1570a84f79aeSDevin Heitmueller 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
1571ec994d05SUroš Vampl 	case EM2882_BOARD_TERRATEC_HYBRID_XS:
157201a5fd6fSDevin Heitmueller 	case EM2880_BOARD_EMPIRE_DUAL_TV:
1573acf43845SMarcel Stork 	case EM2882_BOARD_ZOLID_HYBRID_TV_STICK:
1574f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(zl10353_attach,
1575a84f79aeSDevin Heitmueller 					&em28xx_zl10353_xc3028_no_i2c_gate,
1576c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1577f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
1578a84f79aeSDevin Heitmueller 			result = -EINVAL;
1579a84f79aeSDevin Heitmueller 			goto out_free;
1580a84f79aeSDevin Heitmueller 		}
1581a84f79aeSDevin Heitmueller 		break;
1582f797608cSDevin Heitmueller 	case EM2880_BOARD_TERRATEC_HYBRID_XS:
158365638011SCatimimi 	case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
1584d5b3ba9cSDevin Heitmueller 	case EM2881_BOARD_PINNACLE_HYBRID_PRO:
15857ca7ef60SAndrea.Amorosi76@gmail.com 	case EM2882_BOARD_DIKOM_DK300:
1586811fab62SAntonio Larrosa 	case EM2882_BOARD_KWORLD_VS_DVBT:
1587fe8d54f0SMauro Carvalho Chehab 		/*
1588fe8d54f0SMauro Carvalho Chehab 		 * Those boards could have either a zl10353 or a mt352.
1589fe8d54f0SMauro Carvalho Chehab 		 * If the chip id isn't for zl10353, try mt352.
1590fe8d54f0SMauro Carvalho Chehab 		 */
1591f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(zl10353_attach,
1592a84f79aeSDevin Heitmueller 					&em28xx_zl10353_xc3028_no_i2c_gate,
1593c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1594fe8d54f0SMauro Carvalho Chehab 		if (!dvb->fe[0])
1595f71095beSAntti Palosaari 			dvb->fe[0] = dvb_attach(mt352_attach,
15964fb202a8SDevin Heitmueller 						&terratec_xs_mt352_cfg,
1597c7a45e5bSMauro Carvalho Chehab 						&dev->i2c_adap[dev->def_i2c_bus]);
15984fb202a8SDevin Heitmueller 
1599f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
1600f797608cSDevin Heitmueller 			result = -EINVAL;
1601f797608cSDevin Heitmueller 			goto out_free;
1602f797608cSDevin Heitmueller 		}
1603f797608cSDevin Heitmueller 		break;
16048c47311dSAlberto Mardegan 	case EM2870_BOARD_TERRATEC_XS_MT2060:
16058c47311dSAlberto Mardegan 		dvb->fe[0] = dvb_attach(zl10353_attach,
16068c47311dSAlberto Mardegan 					&em28xx_zl10353_no_i2c_gate_dev,
16078c47311dSAlberto Mardegan 					&dev->i2c_adap[dev->def_i2c_bus]);
1608fe8d54f0SMauro Carvalho Chehab 		if (dvb->fe[0]) {
16098c47311dSAlberto Mardegan 			dvb_attach(mt2060_attach, dvb->fe[0],
16108c47311dSAlberto Mardegan 				   &dev->i2c_adap[dev->def_i2c_bus],
16118c47311dSAlberto Mardegan 				   &em28xx_mt2060_config, 1220);
16128c47311dSAlberto Mardegan 		}
16138c47311dSAlberto Mardegan 		break;
16141985f6fbSAivar Päkk 	case EM2870_BOARD_KWORLD_355U:
16151985f6fbSAivar Päkk 		dvb->fe[0] = dvb_attach(zl10353_attach,
16161985f6fbSAivar Päkk 					&em28xx_zl10353_no_i2c_gate_dev,
1617c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1618fe8d54f0SMauro Carvalho Chehab 		if (dvb->fe[0])
16191985f6fbSAivar Päkk 			dvb_attach(qt1010_attach, dvb->fe[0],
1620fe8d54f0SMauro Carvalho Chehab 				   &dev->i2c_adap[dev->def_i2c_bus],
1621fe8d54f0SMauro Carvalho Chehab 				   &em28xx_qt1010_config);
16221985f6fbSAivar Päkk 		break;
16236e7b9ea0SRobert Krakora 	case EM2883_BOARD_KWORLD_HYBRID_330U:
162419859229SDevin Heitmueller 	case EM2882_BOARD_EVGA_INDTUBE:
1625f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(s5h1409_attach,
16266e7b9ea0SRobert Krakora 					&em28xx_s5h1409_with_xc3028,
1627c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1628f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
16296e7b9ea0SRobert Krakora 			result = -EINVAL;
16306e7b9ea0SRobert Krakora 			goto out_free;
16316e7b9ea0SRobert Krakora 		}
16326e7b9ea0SRobert Krakora 		break;
1633d7de5d8fSFranklin Meng 	case EM2882_BOARD_KWORLD_ATSC_315U:
1634f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
1635d7de5d8fSFranklin Meng 					&em2880_lgdt3303_dev,
163623ba635dSMauro Carvalho Chehab 					0x0e,
1637c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1638fe8d54f0SMauro Carvalho Chehab 		if (dvb->fe[0]) {
1639f71095beSAntti Palosaari 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
1640fdf1bc9fSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
1641fdf1bc9fSMauro Carvalho Chehab 					0x61, TUNER_THOMSON_DTT761X)) {
1642d7de5d8fSFranklin Meng 				result = -EINVAL;
1643d7de5d8fSFranklin Meng 				goto out_free;
1644d7de5d8fSFranklin Meng 			}
1645d7de5d8fSFranklin Meng 		}
1646d7de5d8fSFranklin Meng 		break;
164717d9d558SDevin Heitmueller 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
1648ad9b4bb2SDevin Heitmueller 	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
1649f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
165029b05e22SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
165129b05e22SMauro Carvalho Chehab 					&dev->intf->dev);
1652f2d0c1c6SJarod Wilson 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
165317d9d558SDevin Heitmueller 			result = -EINVAL;
165417d9d558SDevin Heitmueller 			goto out_free;
165517d9d558SDevin Heitmueller 		}
165617d9d558SDevin Heitmueller 		break;
1657285eb1a4SAntti Palosaari 	case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
1658285eb1a4SAntti Palosaari 		/* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
1659f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(tda10023_attach,
1660285eb1a4SAntti Palosaari 					&em28xx_tda10023_config,
1661fe8d54f0SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
1662fe8d54f0SMauro Carvalho Chehab 					0x48);
1663f71095beSAntti Palosaari 		if (dvb->fe[0]) {
1664f71095beSAntti Palosaari 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
1665fdf1bc9fSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
1666fdf1bc9fSMauro Carvalho Chehab 					0x60, TUNER_PHILIPS_CU1216L)) {
1667285eb1a4SAntti Palosaari 				result = -EINVAL;
1668285eb1a4SAntti Palosaari 				goto out_free;
1669285eb1a4SAntti Palosaari 			}
1670285eb1a4SAntti Palosaari 		}
1671285eb1a4SAntti Palosaari 		break;
16727e48b30aSJarod Wilson 	case EM2870_BOARD_KWORLD_A340:
1673f71095beSAntti Palosaari 		dvb->fe[0] = dvb_attach(lgdt3305_attach,
16747e48b30aSJarod Wilson 					&em2870_lgdt3304_dev,
1675c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
16764db8954aSShuah Khan 		if (!dvb->fe[0]) {
16774db8954aSShuah Khan 			result = -EINVAL;
16784db8954aSShuah Khan 			goto out_free;
16794db8954aSShuah Khan 		}
16804db8954aSShuah Khan 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
16814db8954aSShuah Khan 				&dev->i2c_adap[dev->def_i2c_bus],
16824db8954aSShuah Khan 				&kworld_a340_config)) {
16834db8954aSShuah Khan 			dvb_frontend_detach(dvb->fe[0]);
16844db8954aSShuah Khan 			result = -EINVAL;
16854db8954aSShuah Khan 			goto out_free;
16864db8954aSShuah Khan 		}
16877e48b30aSJarod Wilson 		break;
1688d6a5f921SAntti Palosaari 	case EM28174_BOARD_PCTV_290E:
1689a36a66d7SAntti Palosaari 		/* set default GPIO0 for LNA, used if GPIOLIB is undefined */
1690a36a66d7SAntti Palosaari 		dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O |
1691a36a66d7SAntti Palosaari 				CXD2820R_GPIO_L;
1692d6a5f921SAntti Palosaari 		dvb->fe[0] = dvb_attach(cxd2820r_attach,
16937e7b8287SManu Abraham 					&em28xx_cxd2820r_config,
1694c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
169513a5336eSAntti Palosaari 					&dvb->lna_gpio);
1696d6a5f921SAntti Palosaari 		if (dvb->fe[0]) {
1697d6a5f921SAntti Palosaari 			/* FE 0 attach tuner */
16987e7b8287SManu Abraham 			if (!dvb_attach(tda18271_attach,
16997e7b8287SManu Abraham 					dvb->fe[0],
17007e7b8287SManu Abraham 					0x60,
1701c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
17027e7b8287SManu Abraham 					&em28xx_cxd2820r_tda18271_config)) {
1703d6a5f921SAntti Palosaari 				dvb_frontend_detach(dvb->fe[0]);
1704d6a5f921SAntti Palosaari 				result = -EINVAL;
1705d6a5f921SAntti Palosaari 				goto out_free;
1706d6a5f921SAntti Palosaari 			}
17071e8f31f3SAntti Palosaari 
170813a5336eSAntti Palosaari #ifdef CONFIG_GPIOLIB
17091e8f31f3SAntti Palosaari 			/* enable LNA for DVB-T, DVB-T2 and DVB-C */
17100c42a55cSAntti Palosaari 			result = gpio_request_one(dvb->lna_gpio,
17110c42a55cSAntti Palosaari 						  GPIOF_OUT_INIT_LOW, NULL);
17121e8f31f3SAntti Palosaari 			if (result)
171329b05e22SMauro Carvalho Chehab 				dev_err(&dev->intf->dev,
1714ce8591ffSMauro Carvalho Chehab 					"gpio request failed %d\n",
17150c42a55cSAntti Palosaari 					result);
17161e8f31f3SAntti Palosaari 			else
171713a5336eSAntti Palosaari 				gpio_free(dvb->lna_gpio);
17181e8f31f3SAntti Palosaari 
17191e8f31f3SAntti Palosaari 			result = 0; /* continue even set LNA fails */
172013a5336eSAntti Palosaari #endif
172113a5336eSAntti Palosaari 			dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna;
17220c42a55cSAntti Palosaari 		}
17230c42a55cSAntti Palosaari 
1724d6a5f921SAntti Palosaari 		break;
172582e7dbbdSEddi De Pieri 	case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
17268503232fSMauro Carvalho Chehab 	{
1727ad32495bSMauro Carvalho Chehab 		struct xc5000_config cfg = {};
1728fdf1bc9fSMauro Carvalho Chehab 
172982e7dbbdSEddi De Pieri 		hauppauge_hvr930c_init(dev);
173082e7dbbdSEddi De Pieri 
1731de72405fSMauro Carvalho Chehab 		dvb->fe[0] = dvb_attach(drxk_attach,
1732fe8d54f0SMauro Carvalho Chehab 					&hauppauge_930c_drxk,
1733fe8d54f0SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
173482e7dbbdSEddi De Pieri 		if (!dvb->fe[0]) {
173582e7dbbdSEddi De Pieri 			result = -EINVAL;
173682e7dbbdSEddi De Pieri 			goto out_free;
173782e7dbbdSEddi De Pieri 		}
173882e7dbbdSEddi De Pieri 		/* FIXME: do we need a pll semaphore? */
173982e7dbbdSEddi De Pieri 		dvb->fe[0]->sec_priv = dvb;
174082e7dbbdSEddi De Pieri 		sema_init(&dvb->pll_mutex, 1);
174182e7dbbdSEddi De Pieri 		dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
174282e7dbbdSEddi De Pieri 		dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
174382e7dbbdSEddi De Pieri 
174482e7dbbdSEddi De Pieri 		/* Attach xc5000 */
174582e7dbbdSEddi De Pieri 		cfg.i2c_address  = 0x61;
1746de72405fSMauro Carvalho Chehab 		cfg.if_khz = 4000;
174782e7dbbdSEddi De Pieri 
174882e7dbbdSEddi De Pieri 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
174982e7dbbdSEddi De Pieri 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
1750fe8d54f0SMauro Carvalho Chehab 		if (!dvb_attach(xc5000_attach, dvb->fe[0],
1751fe8d54f0SMauro Carvalho Chehab 				&dev->i2c_adap[dev->def_i2c_bus], &cfg)) {
175282e7dbbdSEddi De Pieri 			result = -EINVAL;
175382e7dbbdSEddi De Pieri 			goto out_free;
175482e7dbbdSEddi De Pieri 		}
175582e7dbbdSEddi De Pieri 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
175682e7dbbdSEddi De Pieri 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
175782e7dbbdSEddi De Pieri 
175882e7dbbdSEddi De Pieri 		break;
17598503232fSMauro Carvalho Chehab 	}
1760fec528b7SMauro Carvalho Chehab 	case EM2884_BOARD_TERRATEC_H5:
1761fec528b7SMauro Carvalho Chehab 		terratec_h5_init(dev);
1762fec528b7SMauro Carvalho Chehab 
1763fe8d54f0SMauro Carvalho Chehab 		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk,
1764fe8d54f0SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1765c4c3a3d3SMauro Carvalho Chehab 		if (!dvb->fe[0]) {
1766fec528b7SMauro Carvalho Chehab 			result = -EINVAL;
1767fec528b7SMauro Carvalho Chehab 			goto out_free;
1768fec528b7SMauro Carvalho Chehab 		}
1769fec528b7SMauro Carvalho Chehab 		/* FIXME: do we need a pll semaphore? */
1770fec528b7SMauro Carvalho Chehab 		dvb->fe[0]->sec_priv = dvb;
1771fec528b7SMauro Carvalho Chehab 		sema_init(&dvb->pll_mutex, 1);
1772fec528b7SMauro Carvalho Chehab 		dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
1773fec528b7SMauro Carvalho Chehab 		dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
1774fec528b7SMauro Carvalho Chehab 
1775c4c3a3d3SMauro Carvalho Chehab 		/* Attach tda18271 to DVB-C frontend */
1776fec528b7SMauro Carvalho Chehab 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
1777fec528b7SMauro Carvalho Chehab 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
1778fe8d54f0SMauro Carvalho Chehab 		if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0],
1779fe8d54f0SMauro Carvalho Chehab 				&dev->i2c_adap[dev->def_i2c_bus], 0x60)) {
1780fec528b7SMauro Carvalho Chehab 			result = -EINVAL;
1781fec528b7SMauro Carvalho Chehab 			goto out_free;
1782fec528b7SMauro Carvalho Chehab 		}
1783fec528b7SMauro Carvalho Chehab 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
1784fec528b7SMauro Carvalho Chehab 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
1785c4c3a3d3SMauro Carvalho Chehab 
1786fec528b7SMauro Carvalho Chehab 		break;
17874159d01bSMauro Carvalho Chehab 	case EM2884_BOARD_C3TECH_DIGITAL_DUO:
17884159d01bSMauro Carvalho Chehab 		dvb->fe[0] = dvb_attach(mb86a20s_attach,
17894159d01bSMauro Carvalho Chehab 					&c3tech_duo_mb86a20s_config,
17904159d01bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1791fe8d54f0SMauro Carvalho Chehab 		if (dvb->fe[0])
17924159d01bSMauro Carvalho Chehab 			dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
17934159d01bSMauro Carvalho Chehab 				   &dev->i2c_adap[dev->def_i2c_bus],
17944159d01bSMauro Carvalho Chehab 				   &c3tech_duo_tda18271_config);
17954159d01bSMauro Carvalho Chehab 		break;
1796f410b409SArnd Bergmann 	case EM28174_BOARD_PCTV_460E:
1797f410b409SArnd Bergmann 		result = em28174_dvb_init_pctv_460e(dev);
1798f410b409SArnd Bergmann 		if (result)
17998022f9afSAntti Palosaari 			goto out_free;
180036588715SAntti Palosaari 		break;
18017c1dfdb0SJakob Haufe 	case EM2874_BOARD_DELOCK_61959:
18023553085cSAntti Palosaari 	case EM2874_BOARD_MAXMEDIA_UB425_TC:
18033553085cSAntti Palosaari 		/* attach demodulator */
18043553085cSAntti Palosaari 		dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk,
1805c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
18063553085cSAntti Palosaari 
18073553085cSAntti Palosaari 		if (dvb->fe[0]) {
18083553085cSAntti Palosaari 			/* disable I2C-gate */
18093553085cSAntti Palosaari 			dvb->fe[0]->ops.i2c_gate_ctrl = NULL;
18103553085cSAntti Palosaari 
18113553085cSAntti Palosaari 			/* attach tuner */
1812b6c7abb1SAntti Palosaari 			if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
1813b6c7abb1SAntti Palosaari 					&dev->i2c_adap[dev->def_i2c_bus],
1814b6c7abb1SAntti Palosaari 					&em28xx_cxd2820r_tda18271_config)) {
18153553085cSAntti Palosaari 				dvb_frontend_detach(dvb->fe[0]);
18163553085cSAntti Palosaari 				result = -EINVAL;
18173553085cSAntti Palosaari 				goto out_free;
18183553085cSAntti Palosaari 			}
18193553085cSAntti Palosaari 		}
18203553085cSAntti Palosaari 		break;
1821fa5527cdSIvan Kalvachev 	case EM2884_BOARD_PCTV_510E:
1822fa5527cdSIvan Kalvachev 	case EM2884_BOARD_PCTV_520E:
1823fa5527cdSIvan Kalvachev 		pctv_520e_init(dev);
1824fa5527cdSIvan Kalvachev 
1825fa5527cdSIvan Kalvachev 		/* attach demodulator */
1826fa5527cdSIvan Kalvachev 		dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk,
1827c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1828fa5527cdSIvan Kalvachev 
1829fa5527cdSIvan Kalvachev 		if (dvb->fe[0]) {
1830fa5527cdSIvan Kalvachev 			/* attach tuner */
1831fa5527cdSIvan Kalvachev 			if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
1832c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus],
1833fa5527cdSIvan Kalvachev 					&em28xx_cxd2820r_tda18271_config)) {
1834fa5527cdSIvan Kalvachev 				dvb_frontend_detach(dvb->fe[0]);
1835fa5527cdSIvan Kalvachev 				result = -EINVAL;
1836fa5527cdSIvan Kalvachev 				goto out_free;
1837fa5527cdSIvan Kalvachev 			}
1838fa5527cdSIvan Kalvachev 		}
1839fa5527cdSIvan Kalvachev 		break;
18401fe0fbd6SGilles Risch 	case EM2884_BOARD_ELGATO_EYETV_HYBRID_2008:
1841c8dce008SMartin Blumenstingl 	case EM2884_BOARD_CINERGY_HTC_STICK:
1842d6a64327SMauro Carvalho Chehab 	case EM2884_BOARD_TERRATEC_H6:
1843c8dce008SMartin Blumenstingl 		terratec_htc_stick_init(dev);
1844c8dce008SMartin Blumenstingl 
1845c8dce008SMartin Blumenstingl 		/* attach demodulator */
1846c8dce008SMartin Blumenstingl 		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
1847c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1848c8dce008SMartin Blumenstingl 		if (!dvb->fe[0]) {
1849c8dce008SMartin Blumenstingl 			result = -EINVAL;
1850c8dce008SMartin Blumenstingl 			goto out_free;
1851c8dce008SMartin Blumenstingl 		}
1852c8dce008SMartin Blumenstingl 
1853c8dce008SMartin Blumenstingl 		/* Attach the demodulator. */
1854c8dce008SMartin Blumenstingl 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
1855c7a45e5bSMauro Carvalho Chehab 				&dev->i2c_adap[dev->def_i2c_bus],
1856c8dce008SMartin Blumenstingl 				&em28xx_cxd2820r_tda18271_config)) {
1857c8dce008SMartin Blumenstingl 			result = -EINVAL;
1858c8dce008SMartin Blumenstingl 			goto out_free;
1859c8dce008SMartin Blumenstingl 		}
1860c8dce008SMartin Blumenstingl 		break;
186189040136SMartin Blumenstingl 	case EM2884_BOARD_TERRATEC_HTC_USB_XS:
186289040136SMartin Blumenstingl 		terratec_htc_usb_xs_init(dev);
186389040136SMartin Blumenstingl 
186489040136SMartin Blumenstingl 		/* attach demodulator */
186589040136SMartin Blumenstingl 		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
1866c7a45e5bSMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
186789040136SMartin Blumenstingl 		if (!dvb->fe[0]) {
186889040136SMartin Blumenstingl 			result = -EINVAL;
186989040136SMartin Blumenstingl 			goto out_free;
187089040136SMartin Blumenstingl 		}
187189040136SMartin Blumenstingl 
187289040136SMartin Blumenstingl 		/* Attach the demodulator. */
187389040136SMartin Blumenstingl 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
1874c7a45e5bSMauro Carvalho Chehab 				&dev->i2c_adap[dev->def_i2c_bus],
187589040136SMartin Blumenstingl 				&em28xx_cxd2820r_tda18271_config)) {
187689040136SMartin Blumenstingl 			result = -EINVAL;
187789040136SMartin Blumenstingl 			goto out_free;
187889040136SMartin Blumenstingl 		}
187989040136SMartin Blumenstingl 		break;
18806dbea9f0SJean-Francois Thibert 	case EM2874_BOARD_KWORLD_UB435Q_V2:
18816dbea9f0SJean-Francois Thibert 		dvb->fe[0] = dvb_attach(lgdt3305_attach,
18826dbea9f0SJean-Francois Thibert 					&em2874_lgdt3305_dev,
18836dbea9f0SJean-Francois Thibert 					&dev->i2c_adap[dev->def_i2c_bus]);
18846dbea9f0SJean-Francois Thibert 		if (!dvb->fe[0]) {
18856dbea9f0SJean-Francois Thibert 			result = -EINVAL;
18866dbea9f0SJean-Francois Thibert 			goto out_free;
18876dbea9f0SJean-Francois Thibert 		}
18886dbea9f0SJean-Francois Thibert 
18896dbea9f0SJean-Francois Thibert 		/* Attach the demodulator. */
18906dbea9f0SJean-Francois Thibert 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
18916dbea9f0SJean-Francois Thibert 				&dev->i2c_adap[dev->def_i2c_bus],
18926dbea9f0SJean-Francois Thibert 				&kworld_ub435q_v2_config)) {
18936dbea9f0SJean-Francois Thibert 			result = -EINVAL;
18946dbea9f0SJean-Francois Thibert 			goto out_free;
18956dbea9f0SJean-Francois Thibert 		}
18966dbea9f0SJean-Francois Thibert 		break;
189702bc1f55SMauro Carvalho Chehab 	case EM2874_BOARD_KWORLD_UB435Q_V3:
1898ac7a24fbSAntti Palosaari 	{
1899ac7a24fbSAntti Palosaari 		struct i2c_adapter *adapter = &dev->i2c_adap[dev->def_i2c_bus];
1900ac7a24fbSAntti Palosaari 
190102bc1f55SMauro Carvalho Chehab 		dvb->fe[0] = dvb_attach(lgdt3305_attach,
190202bc1f55SMauro Carvalho Chehab 					&em2874_lgdt3305_nogate_dev,
190302bc1f55SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
190402bc1f55SMauro Carvalho Chehab 		if (!dvb->fe[0]) {
190502bc1f55SMauro Carvalho Chehab 			result = -EINVAL;
190602bc1f55SMauro Carvalho Chehab 			goto out_free;
190702bc1f55SMauro Carvalho Chehab 		}
190802bc1f55SMauro Carvalho Chehab 
1909ac7a24fbSAntti Palosaari 		/* attach tuner */
1910ac7a24fbSAntti Palosaari 		kworld_ub435q_v3_config.fe = dvb->fe[0];
1911ad32495bSMauro Carvalho Chehab 
1912ad32495bSMauro Carvalho Chehab 		dvb->i2c_client_tuner = dvb_module_probe("tda18212", NULL,
1913fe8d54f0SMauro Carvalho Chehab 							 adapter, 0x60,
1914ad32495bSMauro Carvalho Chehab 							 &kworld_ub435q_v3_config);
1915ad32495bSMauro Carvalho Chehab 		if (!dvb->i2c_client_tuner) {
1916ac7a24fbSAntti Palosaari 			dvb_frontend_detach(dvb->fe[0]);
1917ac7a24fbSAntti Palosaari 			result = -ENODEV;
191802bc1f55SMauro Carvalho Chehab 			goto out_free;
191902bc1f55SMauro Carvalho Chehab 		}
192002bc1f55SMauro Carvalho Chehab 		break;
1921ac7a24fbSAntti Palosaari 	}
192238b2df95SDevin Heitmueller 	case EM2874_BOARD_PCTV_HD_MINI_80E:
1923fe8d54f0SMauro Carvalho Chehab 		dvb->fe[0] = dvb_attach(drx39xxj_attach,
1924fe8d54f0SMauro Carvalho Chehab 					&dev->i2c_adap[dev->def_i2c_bus]);
1925fe8d54f0SMauro Carvalho Chehab 		if (dvb->fe[0]) {
1926fe8d54f0SMauro Carvalho Chehab 			dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0],
1927fe8d54f0SMauro Carvalho Chehab 						0x60,
192838b2df95SDevin Heitmueller 						&dev->i2c_adap[dev->def_i2c_bus],
192938b2df95SDevin Heitmueller 						&pinnacle_80e_dvb_config);
193038b2df95SDevin Heitmueller 			if (!dvb->fe[0]) {
193138b2df95SDevin Heitmueller 				result = -EINVAL;
193238b2df95SDevin Heitmueller 				goto out_free;
193338b2df95SDevin Heitmueller 			}
193438b2df95SDevin Heitmueller 		}
193538b2df95SDevin Heitmueller 		break;
1936f410b409SArnd Bergmann 	case EM28178_BOARD_PCTV_461E:
1937f410b409SArnd Bergmann 		result = em28178_dvb_init_pctv_461e(dev);
1938f410b409SArnd Bergmann 		if (result)
1939ec573362SAntti Palosaari 			goto out_free;
1940ec573362SAntti Palosaari 		break;
1941985b0edeSBrad Love 	case EM28178_BOARD_PCTV_461E_V2:
1942985b0edeSBrad Love 		result = em28178_dvb_init_pctv_461e_v2(dev);
1943985b0edeSBrad Love 		if (result)
1944985b0edeSBrad Love 			goto out_free;
1945985b0edeSBrad Love 		break;
194619229240SAntti Palosaari 	case EM28178_BOARD_PCTV_292E:
1947f410b409SArnd Bergmann 		result = em28178_dvb_init_pctv_292e(dev);
1948f410b409SArnd Bergmann 		if (result)
194919229240SAntti Palosaari 			goto out_free;
195019229240SAntti Palosaari 		break;
1951fc30dd76SOlli Salonen 	case EM28178_BOARD_TERRATEC_T2_STICK_HD:
1952f410b409SArnd Bergmann 		result = em28178_dvb_init_terratec_t2_stick_hd(dev);
1953f410b409SArnd Bergmann 		if (result)
1954fc30dd76SOlli Salonen 			goto out_free;
1955fc30dd76SOlli Salonen 		break;
1956ab4d1452SSatoshi Nagahama 	case EM28178_BOARD_PLEX_PX_BCUD:
1957f410b409SArnd Bergmann 		result = em28178_dvb_init_plex_px_bcud(dev);
1958f410b409SArnd Bergmann 		if (result)
1959ab4d1452SSatoshi Nagahama 			goto out_free;
1960ab4d1452SSatoshi Nagahama 		break;
196111a2a949SOlli Salonen 	case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
1962f410b409SArnd Bergmann 		result = em28174_dvb_init_hauppauge_wintv_dualhd_dvb(dev);
1963f410b409SArnd Bergmann 		if (result)
196411a2a949SOlli Salonen 			goto out_free;
196511a2a949SOlli Salonen 		break;
19661586342eSKevin Cheng 	case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595:
1967f410b409SArnd Bergmann 		result = em28174_dvb_init_hauppauge_wintv_dualhd_01595(dev);
1968f410b409SArnd Bergmann 		if (result)
19691586342eSKevin Cheng 			goto out_free;
19701586342eSKevin Cheng 		break;
19712e74a01fSBrad Love 	case EM2874_BOARD_HAUPPAUGE_USB_QUADHD:
19722e74a01fSBrad Love 		result = em2874_dvb_init_hauppauge_usb_quadhd(dev);
19732e74a01fSBrad Love 		if (result)
19742e74a01fSBrad Love 			goto out_free;
19752e74a01fSBrad Love 		break;
19763aefb79aSMauro Carvalho Chehab 	default:
197729b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev,
1978ce8591ffSMauro Carvalho Chehab 			"The frontend of your DVB/ATSC card isn't supported yet\n");
19793aefb79aSMauro Carvalho Chehab 		break;
19803aefb79aSMauro Carvalho Chehab 	}
1981fe8d54f0SMauro Carvalho Chehab 	if (!dvb->fe[0]) {
198229b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev, "frontend initialization failed\n");
19833421b778SAidan Thornton 		result = -EINVAL;
19843421b778SAidan Thornton 		goto out_free;
19853aefb79aSMauro Carvalho Chehab 	}
1986d7cba043SMichael Krufky 	/* define general-purpose callback pointer */
1987f71095beSAntti Palosaari 	dvb->fe[0]->callback = em28xx_tuner_callback;
198882e7dbbdSEddi De Pieri 	if (dvb->fe[1])
198982e7dbbdSEddi De Pieri 		dvb->fe[1]->callback = em28xx_tuner_callback;
19903aefb79aSMauro Carvalho Chehab 
19913aefb79aSMauro Carvalho Chehab 	/* register everything */
199229b05e22SMauro Carvalho Chehab 	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->intf->dev);
19933421b778SAidan Thornton 
19946ea54d93SDouglas Schilling Landgraf 	if (result < 0)
19953421b778SAidan Thornton 		goto out_free;
19963421b778SAidan Thornton 
1997be7fd3c3SBrad Love 	if (dev->dvb_xfer_bulk) {
1998be7fd3c3SBrad Love 		dvb_alt = 0;
1999be7fd3c3SBrad Love 	} else { /* isoc */
2000be7fd3c3SBrad Love 		dvb_alt = dev->dvb_alt_isoc;
2001be7fd3c3SBrad Love 	}
2002be7fd3c3SBrad Love 
2003be7fd3c3SBrad Love 	udev = interface_to_usbdev(dev->intf);
2004be7fd3c3SBrad Love 	usb_set_interface(udev, dev->ifnum, dvb_alt);
200529b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "DVB extension successfully initialized\n");
200647677e51SMauro Carvalho Chehab 
200747677e51SMauro Carvalho Chehab 	kref_get(&dev->ref);
200847677e51SMauro Carvalho Chehab 
20095013318cSMauro Carvalho Chehab ret:
20105013318cSMauro Carvalho Chehab 	em28xx_set_mode(dev, EM28XX_SUSPEND);
20115013318cSMauro Carvalho Chehab 	mutex_unlock(&dev->lock);
20125013318cSMauro Carvalho Chehab 	return result;
20133421b778SAidan Thornton 
20143421b778SAidan Thornton out_free:
20150ae10a7dSMuhammad Usama Anjum 	em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
20163421b778SAidan Thornton 	kfree(dvb);
20173421b778SAidan Thornton 	dev->dvb = NULL;
20185013318cSMauro Carvalho Chehab 	goto ret;
20193aefb79aSMauro Carvalho Chehab }
20203aefb79aSMauro Carvalho Chehab 
prevent_sleep(struct dvb_frontend_ops * ops)20210b8bd83cSChris Rankin static inline void prevent_sleep(struct dvb_frontend_ops *ops)
20220b8bd83cSChris Rankin {
20230b8bd83cSChris Rankin 	ops->set_voltage = NULL;
20240b8bd83cSChris Rankin 	ops->sleep = NULL;
20250b8bd83cSChris Rankin 	ops->tuner_ops.sleep = NULL;
20260b8bd83cSChris Rankin }
20270b8bd83cSChris Rankin 
em28xx_dvb_fini(struct em28xx * dev)2028f2d0c1c6SJarod Wilson static int em28xx_dvb_fini(struct em28xx *dev)
20293aefb79aSMauro Carvalho Chehab {
2030b45e34f2SMauro Carvalho Chehab 	struct em28xx_dvb *dvb;
2031b45e34f2SMauro Carvalho Chehab 
2032822b8deaSMauro Carvalho Chehab 	if (dev->is_audio_only) {
2033822b8deaSMauro Carvalho Chehab 		/* Shouldn't initialize IR for this interface */
2034822b8deaSMauro Carvalho Chehab 		return 0;
2035822b8deaSMauro Carvalho Chehab 	}
2036822b8deaSMauro Carvalho Chehab 
2037505b6d0bSMauro Carvalho Chehab 	if (!dev->board.has_dvb) {
2038df619181SDevin Heitmueller 		/* This device does not support the extension */
2039df619181SDevin Heitmueller 		return 0;
2040df619181SDevin Heitmueller 	}
2041df619181SDevin Heitmueller 
2042b45e34f2SMauro Carvalho Chehab 	if (!dev->dvb)
2043b45e34f2SMauro Carvalho Chehab 		return 0;
2044b45e34f2SMauro Carvalho Chehab 
204529b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "Closing DVB extension\n");
2046aa929ad7SMauro Carvalho Chehab 
2047b45e34f2SMauro Carvalho Chehab 	dvb = dev->dvb;
20480b8bd83cSChris Rankin 
204927ba0dacSFrank Schaefer 	em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
205027ba0dacSFrank Schaefer 
20512665c299SFrank Schaefer 	if (dev->disconnected) {
2052fe8d54f0SMauro Carvalho Chehab 		/*
2053fe8d54f0SMauro Carvalho Chehab 		 * We cannot tell the device to sleep
2054fe8d54f0SMauro Carvalho Chehab 		 * once it has been unplugged.
2055fe8d54f0SMauro Carvalho Chehab 		 */
2056f68e35afSShuah Khan 		if (dvb->fe[0]) {
20570b8bd83cSChris Rankin 			prevent_sleep(&dvb->fe[0]->ops);
2058f68e35afSShuah Khan 			dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED;
2059f68e35afSShuah Khan 		}
2060f68e35afSShuah Khan 		if (dvb->fe[1]) {
20610b8bd83cSChris Rankin 			prevent_sleep(&dvb->fe[1]->ops);
2062f68e35afSShuah Khan 			dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED;
2063f68e35afSShuah Khan 		}
20640b8bd83cSChris Rankin 	}
20650b8bd83cSChris Rankin 
2066910b0797SMatthias Schwarzott 	em28xx_unregister_dvb(dvb);
2067910b0797SMatthias Schwarzott 
2068ad32495bSMauro Carvalho Chehab 	/* release I2C module bindings */
2069ad32495bSMauro Carvalho Chehab 	dvb_module_release(dvb->i2c_client_sec);
2070ad32495bSMauro Carvalho Chehab 	dvb_module_release(dvb->i2c_client_tuner);
2071ad32495bSMauro Carvalho Chehab 	dvb_module_release(dvb->i2c_client_demod);
207219229240SAntti Palosaari 
20730b8bd83cSChris Rankin 	kfree(dvb);
20743421b778SAidan Thornton 	dev->dvb = NULL;
207547677e51SMauro Carvalho Chehab 	kref_put(&dev->ref, em28xx_free_device);
20763aefb79aSMauro Carvalho Chehab 
20773aefb79aSMauro Carvalho Chehab 	return 0;
20783aefb79aSMauro Carvalho Chehab }
20793aefb79aSMauro Carvalho Chehab 
em28xx_dvb_suspend(struct em28xx * dev)2080ca2b46daSShuah Khan static int em28xx_dvb_suspend(struct em28xx *dev)
2081ca2b46daSShuah Khan {
2082ca2b46daSShuah Khan 	int ret = 0;
2083ca2b46daSShuah Khan 
2084ca2b46daSShuah Khan 	if (dev->is_audio_only)
2085ca2b46daSShuah Khan 		return 0;
2086ca2b46daSShuah Khan 
2087ca2b46daSShuah Khan 	if (!dev->board.has_dvb)
2088ca2b46daSShuah Khan 		return 0;
2089ca2b46daSShuah Khan 
209029b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "Suspending DVB extension\n");
2091ca2b46daSShuah Khan 	if (dev->dvb) {
2092ca2b46daSShuah Khan 		struct em28xx_dvb *dvb = dev->dvb;
2093ca2b46daSShuah Khan 
2094ca2b46daSShuah Khan 		if (dvb->fe[0]) {
2095ca2b46daSShuah Khan 			ret = dvb_frontend_suspend(dvb->fe[0]);
209629b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev, "fe0 suspend %d\n", ret);
2097ca2b46daSShuah Khan 		}
2098ca2b46daSShuah Khan 		if (dvb->fe[1]) {
2099ca2b46daSShuah Khan 			dvb_frontend_suspend(dvb->fe[1]);
210029b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev, "fe1 suspend %d\n", ret);
2101ca2b46daSShuah Khan 		}
2102ca2b46daSShuah Khan 	}
2103ca2b46daSShuah Khan 
2104ca2b46daSShuah Khan 	return 0;
2105ca2b46daSShuah Khan }
2106ca2b46daSShuah Khan 
em28xx_dvb_resume(struct em28xx * dev)2107ca2b46daSShuah Khan static int em28xx_dvb_resume(struct em28xx *dev)
2108ca2b46daSShuah Khan {
2109ca2b46daSShuah Khan 	int ret = 0;
2110ca2b46daSShuah Khan 
2111ca2b46daSShuah Khan 	if (dev->is_audio_only)
2112ca2b46daSShuah Khan 		return 0;
2113ca2b46daSShuah Khan 
2114ca2b46daSShuah Khan 	if (!dev->board.has_dvb)
2115ca2b46daSShuah Khan 		return 0;
2116ca2b46daSShuah Khan 
211729b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev, "Resuming DVB extension\n");
2118ca2b46daSShuah Khan 	if (dev->dvb) {
2119ca2b46daSShuah Khan 		struct em28xx_dvb *dvb = dev->dvb;
2120ca2b46daSShuah Khan 
2121ca2b46daSShuah Khan 		if (dvb->fe[0]) {
2122ca2b46daSShuah Khan 			ret = dvb_frontend_resume(dvb->fe[0]);
212329b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev, "fe0 resume %d\n", ret);
2124ca2b46daSShuah Khan 		}
2125ca2b46daSShuah Khan 
2126ca2b46daSShuah Khan 		if (dvb->fe[1]) {
2127ca2b46daSShuah Khan 			ret = dvb_frontend_resume(dvb->fe[1]);
212829b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev, "fe1 resume %d\n", ret);
2129ca2b46daSShuah Khan 		}
2130ca2b46daSShuah Khan 	}
2131ca2b46daSShuah Khan 
2132ca2b46daSShuah Khan 	return 0;
2133ca2b46daSShuah Khan }
2134ca2b46daSShuah Khan 
21353aefb79aSMauro Carvalho Chehab static struct em28xx_ops dvb_ops = {
21363aefb79aSMauro Carvalho Chehab 	.id   = EM28XX_DVB,
21373aefb79aSMauro Carvalho Chehab 	.name = "Em28xx dvb Extension",
2138f2d0c1c6SJarod Wilson 	.init = em28xx_dvb_init,
2139f2d0c1c6SJarod Wilson 	.fini = em28xx_dvb_fini,
2140ca2b46daSShuah Khan 	.suspend = em28xx_dvb_suspend,
2141ca2b46daSShuah Khan 	.resume = em28xx_dvb_resume,
21423aefb79aSMauro Carvalho Chehab };
21433aefb79aSMauro Carvalho Chehab 
em28xx_dvb_register(void)21443aefb79aSMauro Carvalho Chehab static int __init em28xx_dvb_register(void)
21453aefb79aSMauro Carvalho Chehab {
21463aefb79aSMauro Carvalho Chehab 	return em28xx_register_extension(&dvb_ops);
21473aefb79aSMauro Carvalho Chehab }
21483aefb79aSMauro Carvalho Chehab 
em28xx_dvb_unregister(void)21493aefb79aSMauro Carvalho Chehab static void __exit em28xx_dvb_unregister(void)
21503aefb79aSMauro Carvalho Chehab {
21513aefb79aSMauro Carvalho Chehab 	em28xx_unregister_extension(&dvb_ops);
21523aefb79aSMauro Carvalho Chehab }
21533aefb79aSMauro Carvalho Chehab 
21543aefb79aSMauro Carvalho Chehab module_init(em28xx_dvb_register);
21553aefb79aSMauro Carvalho Chehab module_exit(em28xx_dvb_unregister);
2156