13aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/*
23aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab DVB device driver for em28xx
33aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
4fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
53aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
6bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
7bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller	- Fixes for the driver to properly work with HVR-950
84fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller	- Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
9e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller	- Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
10bdfbf9520372daf2b4d6941474c92310848ccb27Devin Heitmueller
113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton (c) 2008 Aidan Thornton <makosoft@googlemail.com>
123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
143aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	(c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
153aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify
183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab it under the terms of the GNU General Public License as published by
193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab the Free Software Foundation; either version 2 of the License.
203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab */
213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/kernel.h>
235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <linux/usb.h>
253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "em28xx.h"
273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/v4l2-common.h>
283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include <media/videobuf-vmalloc.h>
29d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng#include <media/tuner.h>
30d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng#include "tuner-simple.h"
313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
323aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#include "lgdt330x.h"
337e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson#include "lgdt3305.h"
347e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton#include "zl10353.h"
356e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora#include "s5h1409.h"
364fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller#include "mt352.h"
374fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller#include "mt352_priv.h" /* FIXME */
38285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari#include "tda1002x.h"
397e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson#include "tda18271.h"
40ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab#include "s921.h"
4175e2b8694f0b1f8faea1851a39cb7ba07640aa7dDevin Heitmueller#include "drxd.h"
42d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari#include "cxd2820r.h"
43fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab#include "tda18271c2dd.h"
44fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab#include "drxk.h"
4536588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari#include "tda10071.h"
4636588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari#include "a8293.h"
471985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk#include "qt1010.h"
483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
493aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_DESCRIPTION("driver for em28xx based DVB cards");
503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
513aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_LICENSE("GPL");
523aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic unsigned int debug;
543aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_param(debug, int, 0644);
553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabMODULE_PARM_DESC(debug, "enable debug messages [dvb]");
563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho ChehabDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
583aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab#define dprintk(level, fmt, arg...) do {			\
603aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabif (debug >= level) 						\
613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg);	\
623aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab} while (0)
633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_NUM_BUFS 5
653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton#define EM28XX_DVB_MAX_PACKETS 64
663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstruct em28xx_dvb {
68f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	struct dvb_frontend        *fe[2];
693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* feed count management */
713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct mutex               lock;
723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	int                        nfeeds;
733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* general boilerplate stuff */
753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dvb_adapter         adapter;
763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dvb_demux           demux;
773421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dmxdev              dmxdev;
783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dmx_frontend        fe_hw;
793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dmx_frontend        fe_mem;
803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dvb_net             net;
81fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
82c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab	/* Due to DRX-K - probably need changes */
83fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	int (*gate_ctrl)(struct dvb_frontend *, int);
84fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	struct semaphore      pll_mutex;
85c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab	bool			dont_attach_fe1;
863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton};
873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonstatic inline void print_err_status(struct em28xx *dev,
903421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton				     int packet, int status)
913aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	char *errmsg = "Unknown";
933aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	switch (status) {
953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -ENOENT:
963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "unlinked synchronuously";
973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -ECONNRESET:
993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "unlinked asynchronuously";
1003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -ENOSR:
1023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "Buffer error (overrun)";
1033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -EPIPE:
1053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "Stalled (device not responding)";
1063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -EOVERFLOW:
1083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "Babble (bad cable?)";
1093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -EPROTO:
1113421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "Bit-stuff error (bad cable?)";
1123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -EILSEQ:
1143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "CRC/Timeout (could be anything)";
1153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	case -ETIME:
1173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		errmsg = "Device does not respond";
1183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		break;
1193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
1203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (packet < 0) {
1213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		dprintk(1, "URB status %d [%s].\n", status, errmsg);
1223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	} else {
1236ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		dprintk(1, "URB packet %d, status %d [%s].\n",
1246ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf			packet, status, errmsg);
1253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
1263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
1273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
128f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
1293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{
1303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	int i;
1313aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (!dev)
1333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		return 0;
1343aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
1353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
1363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		return 0;
1373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (urb->status < 0) {
1393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		print_err_status(dev, -1, urb->status);
1403421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		if (urb->status == -ENOENT)
1413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			return 0;
1423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
1433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	for (i = 0; i < urb->number_of_packets; i++) {
1453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		int status = urb->iso_frame_desc[i].status;
1463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		if (status < 0) {
1483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			print_err_status(dev, i, status);
1493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			if (urb->iso_frame_desc[i].status != -EPROTO)
1503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton				continue;
1513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		}
1523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
1543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton				 urb->iso_frame_desc[i].offset,
1553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton				 urb->iso_frame_desc[i].actual_length);
1563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
1573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return 0;
1593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
1603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
161f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_start_streaming(struct em28xx_dvb *dvb)
1626ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{
163c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab	int rc;
1643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct em28xx *dev = dvb->adapter.priv;
165d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller	int max_dvb_packet_size;
1663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1678ab3362665a699bd54fc489ff7fb6372678b94c1Holger Nelson	usb_set_interface(dev->udev, 0, dev->dvb_alt);
168c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
169c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab	if (rc < 0)
170c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab		return rc;
1713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1728ab3362665a699bd54fc489ff7fb6372678b94c1Holger Nelson	max_dvb_packet_size = dev->dvb_max_pkt_size;
173f7acc4bb86594d78aa41c07b7670df3e03738b18Mauro Carvalho Chehab	if (max_dvb_packet_size < 0)
174f7acc4bb86594d78aa41c07b7670df3e03738b18Mauro Carvalho Chehab		return max_dvb_packet_size;
175f7acc4bb86594d78aa41c07b7670df3e03738b18Mauro Carvalho Chehab	dprintk(1, "Using %d buffers each with %d bytes\n",
176f7acc4bb86594d78aa41c07b7670df3e03738b18Mauro Carvalho Chehab		EM28XX_DVB_NUM_BUFS,
177f7acc4bb86594d78aa41c07b7670df3e03738b18Mauro Carvalho Chehab		max_dvb_packet_size);
178d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller
1793421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
180d18e2fda7133287bf8a81809816e646cf17c332eDevin Heitmueller				EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
181f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson				em28xx_dvb_isoc_copy);
1823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
1833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
184f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_stop_streaming(struct em28xx_dvb *dvb)
1856ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf{
1863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct em28xx *dev = dvb->adapter.priv;
1873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
1883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	em28xx_uninit_isoc(dev);
189c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab
1902fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab	em28xx_set_mode(dev, EM28XX_SUSPEND);
191c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab
1923aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
1933aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
1943aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
195f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_start_feed(struct dvb_demux_feed *feed)
1963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{
1973421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dvb_demux *demux  = feed->demux;
1983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct em28xx_dvb *dvb = demux->priv;
1993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	int rc, ret;
2003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2013421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (!demux->dmx.frontend)
2023421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		return -EINVAL;
2033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	mutex_lock(&dvb->lock);
2053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->nfeeds++;
2063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	rc = dvb->nfeeds;
2073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2083421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (dvb->nfeeds == 1) {
209f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		ret = em28xx_start_streaming(dvb);
2106ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		if (ret < 0)
2116ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf			rc = ret;
2123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
2133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	mutex_unlock(&dvb->lock);
2153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return rc;
2163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
2173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
218f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_stop_feed(struct dvb_demux_feed *feed)
2193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{
2203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct dvb_demux *demux  = feed->demux;
2213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct em28xx_dvb *dvb = demux->priv;
2223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	int err = 0;
2233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	mutex_lock(&dvb->lock);
2253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->nfeeds--;
2266ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
2276ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (0 == dvb->nfeeds)
228f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		err = em28xx_stop_streaming(dvb);
2296ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
2303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	mutex_unlock(&dvb->lock);
2313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return err;
2323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
2333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
2343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
235e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
236e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab/* ------------------------------------------------------------------ */
237e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehabstatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
238e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab{
239e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab	struct em28xx *dev = fe->dvb->priv;
240e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
241e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab	if (acquire)
242e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab		return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
243e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab	else
2442fe3e2ee72ef17daad1d3769321bb7dd69a003a9Mauro Carvalho Chehab		return em28xx_set_mode(dev, EM28XX_SUSPEND);
245e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab}
246e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
2473aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */
2483aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
249227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehabstatic struct lgdt330x_config em2880_lgdt3303_dev = {
250227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab	.demod_address = 0x0e,
251227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab	.demod_chip = LGDT3303,
252227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab};
2533aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
2547e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilsonstatic struct lgdt3305_config em2870_lgdt3304_dev = {
2557e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.i2c_addr           = 0x0e,
2567e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.demod_chip         = LGDT3304,
2577e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.spectral_inversion = 1,
2587e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.deny_i2c_rptr      = 1,
2597e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.mpeg_mode          = LGDT3305_MPEG_PARALLEL,
2607e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
2617e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
2627e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.vsb_if_khz         = 3250,
2637e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.qam_if_khz         = 4000,
2647e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson};
2657e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson
266ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehabstatic struct s921_config sharp_isdbt = {
267ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab	.demod_address = 0x30 >> 1
268ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab};
269ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab
2707e6388a1b97cca57a1906df6104feb4001721576Aidan Thorntonstatic struct zl10353_config em28xx_zl10353_with_xc3028 = {
2717e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton	.demod_address = (0x1e >> 1),
2727e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton	.no_tuner = 1,
2737e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton	.parallel_ts = 1,
2747e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton	.if2 = 45600,
2757e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton};
2767e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton
2776e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakorastatic struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
2786e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.demod_address = 0x32 >> 1,
2796e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.output_mode   = S5H1409_PARALLEL_OUTPUT,
2806e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.gpio          = S5H1409_GPIO_OFF,
2816e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.inversion     = S5H1409_INVERSION_OFF,
2826e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.status_mode   = S5H1409_DEMODLOCKING,
2836e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
2846e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora};
2856e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora
2867e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilsonstatic struct tda18271_std_map kworld_a340_std_map = {
2877e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 0,
2887e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson		      .if_lvl = 1, .rfagc_top = 0x37, },
2897e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 1,
2907e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson		      .if_lvl = 1, .rfagc_top = 0x37, },
2917e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson};
2927e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson
2937e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilsonstatic struct tda18271_config kworld_a340_config = {
2947e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	.std_map           = &kworld_a340_std_map,
2957e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson};
2967e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson
297a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmuellerstatic struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
298f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	.demod_address = (0x1e >> 1),
299f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	.no_tuner = 1,
300f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	.disable_i2c_gate_ctrl = 1,
301f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	.parallel_ts = 1,
302f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	.if2 = 45600,
303f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller};
304f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller
30575e2b8694f0b1f8faea1851a39cb7ba07640aa7dDevin Heitmuellerstatic struct drxd_config em28xx_drxd = {
306aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.demod_address = 0x70,
307aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.demod_revision = 0xa2,
308aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.pll_type = DRXD_PLL_NONE,
309aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.clock = 12000,
310aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.insert_rs_byte = 1,
311aac865f7c92990f2db17cfe9e9ef89a8706253f7Mauro Carvalho Chehab	.IF = 42800000,
3126b142b3c81e6e532dfad7256fcc7e75fded49245Devin Heitmueller	.disable_i2c_gate_ctrl = 1,
31317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller};
31417d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller
315fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehabstruct drxk_config terratec_h5_drxk = {
316fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	.adr = 0x29,
317e4f4f8758b4c3702761e46f24ee99e34823a0f28Mauro Carvalho Chehab	.single_master = 1,
318f1fe1b75d64046b693075045fe9fc5cafed9c981Mauro Carvalho Chehab	.no_i2c_bridge = 1,
3198b9456ae04b1cb7adcaa57735324f7b518eae07dMauro Carvalho Chehab	.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
320fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab};
321fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
32282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieristruct drxk_config hauppauge_930c_drxk = {
32382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	.adr = 0x29,
32482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	.single_master = 1,
32582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	.no_i2c_bridge = 1,
32682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
32782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	.chunk_size = 56,
32882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri};
32982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
330fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehabstatic int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
331fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab{
332fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	struct em28xx_dvb *dvb = fe->sec_priv;
333fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	int status;
334fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
335fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	if (!dvb)
336fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		return -EINVAL;
337fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
338fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	if (enable) {
339fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		down(&dvb->pll_mutex);
340fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		status = dvb->gate_ctrl(fe, 1);
341fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	} else {
342fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		status = dvb->gate_ctrl(fe, 0);
343fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		up(&dvb->pll_mutex);
344fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	}
345fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	return status;
346fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab}
347fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
34882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieristatic void hauppauge_hvr930c_init(struct em28xx *dev)
34982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri{
35082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	int i;
35182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
35282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
353de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xff,	0xff,	0x65},
354de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xfb,	0xff,	0x32},
355de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xff,	0xff,	0xb8},
35682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{ -1,                   -1,     -1,     -1},
35782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	};
35882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
359de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x01},
360de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xaf,	0xff,	0x65},
361de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x76},
362de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x01},
363de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xcf,	0xff,	0x0b},
364de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x40},
365de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab
366de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xcf,	0xff,	0x65},
367de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x65},
368de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xcf,	0xff,	0x0b},
369de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		{EM2874_R80_GPIO,	0xef,	0xff,	0x65},
37082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
37182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{ -1,                   -1,     -1,     -1},
37282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	};
37382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
37482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	struct {
37582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		unsigned char r[4];
37682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		int len;
37782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	} regs[] = {
37882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
37982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x02 }, 2},
38082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
38182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x00 }, 2},
38282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
38382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
38482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x00 }, 2},
38582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
38682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x04, 0x00 }, 2},
38782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x00, 0x04 }, 2},
38882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
38982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x04, 0x14 }, 2},
39082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
39182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	};
39282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
39382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_gpio_set(dev, hauppauge_hvr930c_init);
39482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
39582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	msleep(10);
39682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
39782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	msleep(10);
39882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
39982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	dev->i2c_client.addr = 0x82 >> 1;
40082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
40182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	for (i = 0; i < ARRAY_SIZE(regs); i++)
40282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
40382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_gpio_set(dev, hauppauge_hvr930c_end);
40482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
40582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	msleep(100);
40682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
40782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
40882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	msleep(30);
40982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
41082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
41182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	msleep(10);
41282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
41382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri}
41482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
415fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehabstatic void terratec_h5_init(struct em28xx *dev)
416fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab{
417fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	int i;
418fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	struct em28xx_reg_seq terratec_h5_init[] = {
419fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM28XX_R08_GPIO,	0xff,	0xff,	10},
420fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xf6,	0xff,	100},
421fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xf2,	0xff,	50},
422fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xf6,	0xff,	100},
423fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{ -1,                   -1,     -1,     -1},
424fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	};
425fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	struct em28xx_reg_seq terratec_h5_end[] = {
426fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xe6,	0xff,	100},
427fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xa6,	0xff,	50},
428fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{EM2874_R80_GPIO,	0xe6,	0xff,	100},
429fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{ -1,                   -1,     -1,     -1},
430fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	};
431fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	struct {
432fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		unsigned char r[4];
433fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		int len;
434fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	} regs[] = {
435fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
436fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x02 }, 2},
437fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
438fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x00 }, 2},
439fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
440fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
441fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x00 }, 2},
442fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
443fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x04, 0x00 }, 2},
444fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x00, 0x04 }, 2},
445fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
446fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x04, 0x14 }, 2},
447fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
448fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	};
449fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
450fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	em28xx_gpio_set(dev, terratec_h5_init);
451fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
452fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	msleep(10);
453fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
454fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	msleep(10);
455fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
456fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	dev->i2c_client.addr = 0x82 >> 1;
457fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
458fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	for (i = 0; i < ARRAY_SIZE(regs); i++)
459fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
460fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	em28xx_gpio_set(dev, terratec_h5_end);
461fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab};
462fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
463f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
4644fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller{
4654fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	/* Values extracted from a USB trace of the Terratec Windows driver */
4664fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
4674fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 reset[]          = { RESET,      0x80 };
4684fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
4694fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
4704fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
4714fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
4724fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
4734fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
4744fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
475ff69786b4ccd0d5b99a60ba0be98237f9b7d8f52Devin Heitmueller	static u8 tuner_go[]       = { TUNER_GO, 0x01};
4764fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller
4774fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, clock_config,   sizeof(clock_config));
4784fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	udelay(200);
4794fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, reset,          sizeof(reset));
4804fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
4814fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
4824fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
4834fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
4844fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
4854fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
4864fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
4874fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	mt352_write(fe, tuner_go,       sizeof(tuner_go));
4884fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	return 0;
4894fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller}
4904fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller
4914fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmuellerstatic struct mt352_config terratec_xs_mt352_cfg = {
4924fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	.demod_address = (0x1e >> 1),
4934fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	.no_tuner = 1,
4944fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller	.if2 = 45600,
495f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	.demod_init = em28xx_mt352_terratec_xs_init,
4964fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller};
4974fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller
498285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaaristatic struct tda10023_config em28xx_tda10023_config = {
499285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari	.demod_address = 0x0c,
500285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari	.invert = 1,
501285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari};
502285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari
503d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaaristatic struct cxd2820r_config em28xx_cxd2820r_config = {
504d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	.i2c_address = (0xd8 >> 1),
505d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	.ts_mode = CXD2820R_TS_SERIAL,
506d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari
507d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	/* enable LNA for DVB-T2 and DVB-C */
508d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	.gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
509d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	.gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
510d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari};
511d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari
512d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaaristatic struct tda18271_config em28xx_cxd2820r_tda18271_config = {
513d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	.output_opt = TDA18271_OUTPUT_LT_OFF,
5140db4bf42baae95ddd457b0c4911e851c9169750eSteve Kerrison	.gate = TDA18271_GATE_DIGITAL,
515d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari};
516d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari
51736588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaaristatic const struct tda10071_config em28xx_tda10071_config = {
51836588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.i2c_address = 0x55, /* (0xaa >> 1) */
51936588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.i2c_wr_max = 64,
52036588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.ts_mode = TDA10071_TS_SERIAL,
52136588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.spec_inv = 0,
52236588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.xtal = 40444000, /* 40.444 MHz */
52336588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.pll_multiplier = 20,
52436588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari};
52536588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari
52636588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaaristatic const struct a8293_config em28xx_a8293_config = {
52736588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	.i2c_addr = 0x08, /* (0x10 >> 1) */
52836588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari};
52936588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari
5301985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkkstatic struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
5311985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	.demod_address = (0x1e >> 1),
5321985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	.disable_i2c_gate_ctrl = 1,
5331985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	.no_tuner = 1,
5341985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	.parallel_ts = 1,
5351985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk};
5361985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkkstatic struct qt1010_config em28xx_qt1010_config = {
5371985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	.i2c_address = 0x62
5381985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk
5391985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk};
5401985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk
5413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab/* ------------------------------------------------------------------ */
5423aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
543f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
5443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
5453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	struct dvb_frontend *fe;
5463ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	struct xc2028_config cfg;
5473ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab
5486ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	memset(&cfg, 0, sizeof(cfg));
5493ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.i2c_adap  = &dev->i2c_adap;
5503ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab	cfg.i2c_addr  = addr;
5513ca9c09379e8f3be0744c47f72769457fa46e9f3Mauro Carvalho Chehab
552f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (!dev->dvb->fe[0]) {
553480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset		em28xx_errdev("/2: dvb frontend not attached. "
554480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset				"Can't attach xc3028\n");
5553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		return -EINVAL;
5563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
5573aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
558f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
5593aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	if (!fe) {
560480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset		em28xx_errdev("/2: xc3028 attach failed\n");
561f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb_frontend_detach(dev->dvb->fe[0]);
562f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dev->dvb->fe[0] = NULL;
5633aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		return -EINVAL;
5643aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
5653aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
566480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset	em28xx_info("%s/2: xc3028 attached\n", dev->name);
5673aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
5683aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
5693aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
5703aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
5713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton/* ------------------------------------------------------------------ */
5723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
573f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
574f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson			       struct em28xx *dev, struct device *device)
5753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
5763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	int result;
5773aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
5783421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	mutex_init(&dvb->lock);
5793aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
5803421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* register adapter */
5813421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
5823421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton				      adapter_nr);
5833421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
5843421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
5853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
5863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_adapter;
5873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
588e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
589e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab	/* Ensure all frontends negotiate bus access */
590f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
591f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (dvb->fe[1])
592f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
593e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
5943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->adapter.priv = dev;
5953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
5963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* register frontend */
597f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
5983421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
5993421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
6003421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
601f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		goto fail_frontend0;
602f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	}
603f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari
604f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	/* register 2nd frontend */
605f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (dvb->fe[1]) {
606f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
607f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (result < 0) {
608f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
609f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari				dev->name, result);
610f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			goto fail_frontend1;
611f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		}
6123421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
6133421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6143421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* register demux stuff */
6153421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.dmx.capabilities =
6163421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
6173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		DMX_MEMORY_BASED_FILTERING;
6183421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.priv       = dvb;
6193421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.filternum  = 256;
6203421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.feednum    = 256;
621f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	dvb->demux.start_feed = em28xx_start_feed;
622f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	dvb->demux.stop_feed  = em28xx_stop_feed;
623e3569abc1c51d24f9c64b214f85477e490b156e3Mauro Carvalho Chehab
6243421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb_dmx_init(&dvb->demux);
6253421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
6263421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
6273421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
6283421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_dmx;
6293421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
6303421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6313421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->dmxdev.filternum    = 256;
6323421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->dmxdev.demux        = &dvb->demux.dmx;
6333421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->dmxdev.capabilities = 0;
6343421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
6353421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
6363421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
6373421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
6383421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_dmxdev;
6393421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
64052284c3e47bf502aaff72ab2ede509193b628b1bMauro Carvalho Chehab
6413421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->fe_hw.source = DMX_FRONTEND_0;
6423421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
6433421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
6443421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
6453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
6463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_fe_hw;
6473421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
6483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->fe_mem.source = DMX_MEMORY_FE;
6503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
6513421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
6523421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
6533421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
6543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_fe_mem;
6553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
6563421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
6583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (result < 0) {
6593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
6603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		       dev->name, result);
6613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto fail_fe_conn;
6623421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
6633421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6643421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	/* register network adapter */
6653421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
6663421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return 0;
6673421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
6683421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_conn:
6693421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
6703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_mem:
6713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
6723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_fe_hw:
6733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_dmxdev_release(&dvb->dmxdev);
6743421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmxdev:
6753421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_dmx_release(&dvb->demux);
6763421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_dmx:
677f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (dvb->fe[1])
678f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb_unregister_frontend(dvb->fe[1]);
679f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb_unregister_frontend(dvb->fe[0]);
680f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaarifail_frontend1:
681f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (dvb->fe[1])
682f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb_frontend_detach(dvb->fe[1]);
683f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaarifail_frontend0:
684f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb_frontend_detach(dvb->fe[0]);
6853421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_unregister_adapter(&dvb->adapter);
6863421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonfail_adapter:
6873421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	return result;
6883421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
6893421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
690f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
6913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{
6923421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_net_release(&dvb->net);
6933421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
6943421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
6953421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_dmxdev_release(&dvb->dmxdev);
6963421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_dmx_release(&dvb->demux);
697f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (dvb->fe[1])
698f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb_unregister_frontend(dvb->fe[1]);
699f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb_unregister_frontend(dvb->fe[0]);
700c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab	if (dvb->fe[1] && !dvb->dont_attach_fe1)
701f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb_frontend_detach(dvb->fe[1]);
702f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb_frontend_detach(dvb->fe[0]);
7033421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb_unregister_adapter(&dvb->adapter);
7043421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton}
7053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
706f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_dvb_init(struct em28xx *dev)
7073421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton{
708e36454376a8f4637c0767daa78cf1d96d162d71aAntti Palosaari	int result = 0, mfe_shared = 0;
7093421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	struct em28xx_dvb *dvb;
7103421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
711505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab	if (!dev->board.has_dvb) {
712df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller		/* This device does not support the extension */
713ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab		printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n");
714df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller		return 0;
715df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller	}
716df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller
7173421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
7186ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
7196ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (dvb == NULL) {
720480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset		em28xx_info("em28xx_dvb: memory allocation failed\n");
7213421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		return -ENOMEM;
7223421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
7233421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dev->dvb = dvb;
724f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb->fe[0] = dvb->fe[1] = NULL;
7253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
7265013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehab	mutex_lock(&dev->lock);
727c67ec53f8f4e90ebd482789e2f6d121f41a0bd90Mauro Carvalho Chehab	em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
7283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	/* init frontend */
7293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	switch (dev->model) {
730ebaefdb7651383645f17d2d32398914175d1bcddMauro Carvalho Chehab	case EM2874_BOARD_LEADERSHIP_ISDBT:
731f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(s921_attach,
732ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab				&sharp_isdbt, &dev->i2c_adap);
733ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab
734f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (!dvb->fe[0]) {
735ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab			result = -EINVAL;
736ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab			goto out_free;
737ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab		}
738ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab
739ca3dfd6a6f8364c1d51e548adb4564702f1141e9Mauro Carvalho Chehab		break;
740f89bc32974a4376e8393001484af28d8c3350ab4Douglas Schilling Landgraf	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
74110ac6603613d46a43a4544fbbe9581e50879bd45Mauro Carvalho Chehab	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
7424fd305b2a2c4d16e8d4ebc95c84f946edd3385c5Devin Heitmueller	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
743e14b3658a7651ffd9b1f407eaf07f4dde17ef1e7Devin Heitmueller	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
744f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(lgdt330x_attach,
7453421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton					   &em2880_lgdt3303_dev,
7463421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton					   &dev->i2c_adap);
747f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
7483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			result = -EINVAL;
7493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			goto out_free;
7503421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		}
751227ad4ab9058ef2624934183e8083886cf64bf56Mauro Carvalho Chehab		break;
75246510b56ca56a25ce973d6a6e8490c1109ff94efThierry MERLE	case EM2880_BOARD_KWORLD_DVB_310U:
753f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(zl10353_attach,
7543421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton					   &em28xx_zl10353_with_xc3028,
7553421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton					   &dev->i2c_adap);
756f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
7573421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			result = -EINVAL;
7583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton			goto out_free;
7593421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		}
7607e6388a1b97cca57a1906df6104feb4001721576Aidan Thornton		break;
761a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
762ec994d0505fc3dde5f46203602c76b527e2ac69dUroš Vampl	case EM2882_BOARD_TERRATEC_HYBRID_XS:
76301a5fd6ff3fbae9a599d3334a8cca0f00865e360Devin Heitmueller	case EM2880_BOARD_EMPIRE_DUAL_TV:
764f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(zl10353_attach,
765a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller					   &em28xx_zl10353_xc3028_no_i2c_gate,
766a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller					   &dev->i2c_adap);
767f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
768a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller			result = -EINVAL;
769a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller			goto out_free;
770a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller		}
771a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller		break;
772f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller	case EM2880_BOARD_TERRATEC_HYBRID_XS:
773656380118d1a1c0176e58e4e3e46d736d0dd2000Catimimi	case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
774d5b3ba9cb375620a109d79f2e3a7bc21e9b75d8fDevin Heitmueller	case EM2881_BOARD_PINNACLE_HYBRID_PRO:
7757ca7ef6011e92b52a365ddc78f6668e01793c572Andrea.Amorosi	case EM2882_BOARD_DIKOM_DK300:
776811fab623f435932f2a26aa64b40ec6102618cc6Antonio Larrosa	case EM2882_BOARD_KWORLD_VS_DVBT:
777f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(zl10353_attach,
778a84f79aed688a94197387830df3a2f2068f49dc0Devin Heitmueller					   &em28xx_zl10353_xc3028_no_i2c_gate,
779f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller					   &dev->i2c_adap);
780f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (dvb->fe[0] == NULL) {
781f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller			/* This board could have either a zl10353 or a mt352.
782f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller			   If the chip id isn't for zl10353, try mt352 */
783f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			dvb->fe[0] = dvb_attach(mt352_attach,
7844fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller						   &terratec_xs_mt352_cfg,
7854fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller						   &dev->i2c_adap);
786f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller		}
7874fb202a8d9d936f7080ab631140b447a0625e36cDevin Heitmueller
788f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
789f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller			result = -EINVAL;
790f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller			goto out_free;
791f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller		}
792f797608cc4f19b44b83ec39c87e14af6fa07826dDevin Heitmueller		break;
7931985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk	case EM2870_BOARD_KWORLD_355U:
7941985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk		dvb->fe[0] = dvb_attach(zl10353_attach,
7951985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk					   &em28xx_zl10353_no_i2c_gate_dev,
7961985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk					   &dev->i2c_adap);
7971985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk		if (dvb->fe[0] != NULL)
7981985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk			dvb_attach(qt1010_attach, dvb->fe[0],
7991985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk				   &dev->i2c_adap, &em28xx_qt1010_config);
8001985f6fb8965a813aabd53a6b64ec54dd23bfdfbAivar Päkk		break;
8016e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora	case EM2883_BOARD_KWORLD_HYBRID_330U:
80219859229d7d98bc2d582ff45045dd7f73d649383Devin Heitmueller	case EM2882_BOARD_EVGA_INDTUBE:
803f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(s5h1409_attach,
8046e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora					   &em28xx_s5h1409_with_xc3028,
8056e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora					   &dev->i2c_adap);
806f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
8076e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora			result = -EINVAL;
8086e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora			goto out_free;
8096e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora		}
8106e7b9ea0937eeb75fa166ef7bd22b5f3bb5676d1Robert Krakora		break;
811d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng	case EM2882_BOARD_KWORLD_ATSC_315U:
812f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(lgdt330x_attach,
813d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng					   &em2880_lgdt3303_dev,
814d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng					   &dev->i2c_adap);
815f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (dvb->fe[0] != NULL) {
816f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
817d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng				&dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
818d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng				result = -EINVAL;
819d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng				goto out_free;
820d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng			}
821d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng		}
822d7de5d8ff74efd01916b01af875a0e87419a3599Franklin Meng		break;
82317d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
824ad9b4bb265cecbfc9b0c495741e331ce199964e0Devin Heitmueller	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
825f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
82675e2b8694f0b1f8faea1851a39cb7ba07640aa7dDevin Heitmueller					   &dev->i2c_adap, &dev->udev->dev);
827f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson		if (em28xx_attach_xc3028(0x61, dev) < 0) {
82817d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller			result = -EINVAL;
82917d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller			goto out_free;
83017d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller		}
83117d9d558e818530cc7d210ffea575a36f48eaa1aDevin Heitmueller		break;
832285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari	case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
833285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari		/* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
834f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(tda10023_attach,
835285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari			&em28xx_tda10023_config,
836285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari			&dev->i2c_adap, 0x48);
837f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (dvb->fe[0]) {
838f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
839285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari				&dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) {
840285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari				result = -EINVAL;
841285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari				goto out_free;
842285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari			}
843285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari		}
844285eb1a40242adb3feaf9c73d352cbfeee1bea1cAntti Palosaari		break;
8457e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson	case EM2870_BOARD_KWORLD_A340:
846f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		dvb->fe[0] = dvb_attach(lgdt3305_attach,
8477e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson					   &em2870_lgdt3304_dev,
8487e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson					   &dev->i2c_adap);
849f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari		if (dvb->fe[0] != NULL)
850f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari			dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
8517e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson				   &dev->i2c_adap, &kworld_a340_config);
8527e48b30af033076c85ab48a8306b5588faf5fb4bJarod Wilson		break;
853d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari	case EM28174_BOARD_PCTV_290E:
854d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari		dvb->fe[0] = dvb_attach(cxd2820r_attach,
8557e7b8287af32400daea1e231057b4b75934af347Manu Abraham					&em28xx_cxd2820r_config,
856c2bbbe7b5e79974c5ed1c828690731f6f5106beeAntti Palosaari					&dev->i2c_adap);
857d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari		if (dvb->fe[0]) {
858d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari			/* FE 0 attach tuner */
8597e7b8287af32400daea1e231057b4b75934af347Manu Abraham			if (!dvb_attach(tda18271_attach,
8607e7b8287af32400daea1e231057b4b75934af347Manu Abraham					dvb->fe[0],
8617e7b8287af32400daea1e231057b4b75934af347Manu Abraham					0x60,
8627e7b8287af32400daea1e231057b4b75934af347Manu Abraham					&dev->i2c_adap,
8637e7b8287af32400daea1e231057b4b75934af347Manu Abraham					&em28xx_cxd2820r_tda18271_config)) {
8647e7b8287af32400daea1e231057b4b75934af347Manu Abraham
865d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari				dvb_frontend_detach(dvb->fe[0]);
866d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari				result = -EINVAL;
867d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari				goto out_free;
868d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari			}
869d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari		}
870d6a5f921fb8cbd418b298e5bbe83e5c8c8e1da16Antti Palosaari		break;
87182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
8728503232f2e9604d844d8f52ddea2e55ccc6c38f6Mauro Carvalho Chehab	{
8738503232f2e9604d844d8f52ddea2e55ccc6c38f6Mauro Carvalho Chehab		struct xc5000_config cfg;
87482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		hauppauge_hvr930c_init(dev);
87582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
876de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		dvb->fe[0] = dvb_attach(drxk_attach,
877fa4b2a171d42ffc512b3a86922ad68e1355eb17aMauro Carvalho Chehab					&hauppauge_930c_drxk, &dev->i2c_adap);
87882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		if (!dvb->fe[0]) {
87982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			result = -EINVAL;
88082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			goto out_free;
88182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		}
88282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		/* FIXME: do we need a pll semaphore? */
88382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		dvb->fe[0]->sec_priv = dvb;
88482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		sema_init(&dvb->pll_mutex, 1);
88582e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
88682e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
88782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
88882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		/* Attach xc5000 */
88982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		memset(&cfg, 0, sizeof(cfg));
89082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		cfg.i2c_address  = 0x61;
891de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		cfg.if_khz = 4000;
89282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
89382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		if (dvb->fe[0]->ops.i2c_gate_ctrl)
89482e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
895de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
896de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab				&cfg)) {
89782e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			result = -EINVAL;
89882e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			goto out_free;
89982e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		}
90082e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		if (dvb->fe[0]->ops.i2c_gate_ctrl)
90182e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
90282e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri
90382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri		break;
9048503232f2e9604d844d8f52ddea2e55ccc6c38f6Mauro Carvalho Chehab	}
905fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	case EM2884_BOARD_TERRATEC_H5:
906a1ed02e9f1a0fa34e5b5e978209204033bb9cf4fAndreas Oberritter	case EM2884_BOARD_CINERGY_HTC_STICK:
907fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		terratec_h5_init(dev);
908fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
909fa4b2a171d42ffc512b3a86922ad68e1355eb17aMauro Carvalho Chehab		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
910c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab		if (!dvb->fe[0]) {
911fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			result = -EINVAL;
912fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			goto out_free;
913fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		}
914fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		/* FIXME: do we need a pll semaphore? */
915fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		dvb->fe[0]->sec_priv = dvb;
916fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		sema_init(&dvb->pll_mutex, 1);
917fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
918fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
919fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab
920c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab		/* Attach tda18271 to DVB-C frontend */
921fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		if (dvb->fe[0]->ops.i2c_gate_ctrl)
922fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
923fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
924fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			result = -EINVAL;
925fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			goto out_free;
926fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		}
927fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		if (dvb->fe[0]->ops.i2c_gate_ctrl)
928fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
929c4c3a3d32a2eac18dba04683bb5b7357402405c7Mauro Carvalho Chehab
930fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab		break;
93136588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari	case EM28174_BOARD_PCTV_460E:
93236588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari		/* attach demod */
93336588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari		dvb->fe[0] = dvb_attach(tda10071_attach,
93436588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari			&em28xx_tda10071_config, &dev->i2c_adap);
93536588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari
93636588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari		/* attach SEC */
93736588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari		if (dvb->fe[0])
93836588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
93936588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari				&em28xx_a8293_config);
94036588715fc0ed3ff0ffb025dc841652cb3b2b667Antti Palosaari		break;
9413aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	default:
942480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
943480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset				" isn't supported yet\n");
9443aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab		break;
9453aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
946f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	if (NULL == dvb->fe[0]) {
947480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset		em28xx_errdev("/2: frontend initialization failed\n");
9483421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		result = -EINVAL;
9493421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto out_free;
9503aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	}
951d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky	/* define general-purpose callback pointer */
952f71095be6645aee0828623701e35e7e7d52910d8Antti Palosaari	dvb->fe[0]->callback = em28xx_tuner_callback;
95382e7dbbd4a16274b0a7038978734fc11bbf9f4b6Eddi De Pieri	if (dvb->fe[1])
954de72405f6fc1aaedc0412f88cf681ed33519c49aMauro Carvalho Chehab		dvb->fe[1]->callback = em28xx_tuner_callback;
9553aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
9563aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	/* register everything */
957f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
9583421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
9596ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (result < 0)
9603421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		goto out_free;
9613421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
962e36454376a8f4637c0767daa78cf1d96d162d71aAntti Palosaari	/* MFE lock */
963e36454376a8f4637c0767daa78cf1d96d162d71aAntti Palosaari	dvb->adapter.mfe_shared = mfe_shared;
964e36454376a8f4637c0767daa78cf1d96d162d71aAntti Palosaari
965480be1851aebcb0b9c5b0fb9acefe5da97cc702aFilipe Rosset	em28xx_info("Successfully loaded em28xx-dvb\n");
9665013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehabret:
9675013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehab	em28xx_set_mode(dev, EM28XX_SUSPEND);
9685013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehab	mutex_unlock(&dev->lock);
9695013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehab	return result;
9703421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton
9713421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thorntonout_free:
9723421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	kfree(dvb);
9733421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	dev->dvb = NULL;
9745013318ca4fd22e30fd891f234b60daa3ca2f62dMauro Carvalho Chehab	goto ret;
9753aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
9763aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
9770b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankinstatic inline void prevent_sleep(struct dvb_frontend_ops *ops)
9780b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin{
9790b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin	ops->set_voltage = NULL;
9800b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin	ops->sleep = NULL;
9810b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin	ops->tuner_ops.sleep = NULL;
9820b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin}
9830b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin
984f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilsonstatic int em28xx_dvb_fini(struct em28xx *dev)
9853aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
986505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab	if (!dev->board.has_dvb) {
987df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller		/* This device does not support the extension */
988df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller		return 0;
989df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller	}
990df619181631217e3166bb6c7538f981e0272617fDevin Heitmueller
9913421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	if (dev->dvb) {
9920b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin		struct em28xx_dvb *dvb = dev->dvb;
9930b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin
9940b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin		if (dev->state & DEV_DISCONNECTED) {
9950b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin			/* We cannot tell the device to sleep
9960b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin			 * once it has been unplugged. */
9970b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin			if (dvb->fe[0])
9980b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin				prevent_sleep(&dvb->fe[0]->ops);
9990b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin			if (dvb->fe[1])
10000b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin				prevent_sleep(&dvb->fe[1]->ops);
10010b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin		}
10020b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin
10030b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin		em28xx_unregister_dvb(dvb);
10040b8bd83cf393832f1d00096b866d888b75b374c3Chris Rankin		kfree(dvb);
10053421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton		dev->dvb = NULL;
10063421b7787a2cf41ac5edce9b5766bddd1e1d9986Aidan Thornton	}
10073aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
10083aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return 0;
10093aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
10103aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
10113aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic struct em28xx_ops dvb_ops = {
10123aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.id   = EM28XX_DVB,
10133aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	.name = "Em28xx dvb Extension",
1014f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	.init = em28xx_dvb_init,
1015f2d0c1c625bc79aa524b52eea2de4262a9be1d90Jarod Wilson	.fini = em28xx_dvb_fini,
10163aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab};
10173aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
10183aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic int __init em28xx_dvb_register(void)
10193aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
10203aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	return em28xx_register_extension(&dvb_ops);
10213aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
10223aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
10233aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabstatic void __exit em28xx_dvb_unregister(void)
10243aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab{
10253aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab	em28xx_unregister_extension(&dvb_ops);
10263aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab}
10273aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehab
10283aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_init(em28xx_dvb_register);
10293aefb79af8d41c85e11da7109d62038849421bb6Mauro Carvalho Chehabmodule_exit(em28xx_dvb_unregister);
1030