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