162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// DVB device driver for em28xx 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// (c) 2008-2011 Mauro Carvalho Chehab <mchehab@kernel.org> 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> 862306a36Sopenharmony_ci// - Fixes for the driver to properly work with HVR-950 962306a36Sopenharmony_ci// - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick 1062306a36Sopenharmony_ci// - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 1162306a36Sopenharmony_ci// 1262306a36Sopenharmony_ci// (c) 2008 Aidan Thornton <makosoft@googlemail.com> 1362306a36Sopenharmony_ci// 1462306a36Sopenharmony_ci// (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com> 1562306a36Sopenharmony_ci// 1662306a36Sopenharmony_ci// Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: 1762306a36Sopenharmony_ci// (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> 1862306a36Sopenharmony_ci// (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "em28xx.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/kernel.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci#include <linux/usb.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <media/v4l2-common.h> 2762306a36Sopenharmony_ci#include <media/dvb_demux.h> 2862306a36Sopenharmony_ci#include <media/dvb_net.h> 2962306a36Sopenharmony_ci#include <media/dmxdev.h> 3062306a36Sopenharmony_ci#include <media/tuner.h> 3162306a36Sopenharmony_ci#include "tuner-simple.h" 3262306a36Sopenharmony_ci#include <linux/gpio.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include "lgdt330x.h" 3562306a36Sopenharmony_ci#include "lgdt3305.h" 3662306a36Sopenharmony_ci#include "lgdt3306a.h" 3762306a36Sopenharmony_ci#include "zl10353.h" 3862306a36Sopenharmony_ci#include "s5h1409.h" 3962306a36Sopenharmony_ci#include "mt2060.h" 4062306a36Sopenharmony_ci#include "mt352.h" 4162306a36Sopenharmony_ci#include "mt352_priv.h" /* FIXME */ 4262306a36Sopenharmony_ci#include "tda1002x.h" 4362306a36Sopenharmony_ci#include "drx39xyj/drx39xxj.h" 4462306a36Sopenharmony_ci#include "tda18271.h" 4562306a36Sopenharmony_ci#include "s921.h" 4662306a36Sopenharmony_ci#include "drxd.h" 4762306a36Sopenharmony_ci#include "cxd2820r.h" 4862306a36Sopenharmony_ci#include "tda18271c2dd.h" 4962306a36Sopenharmony_ci#include "drxk.h" 5062306a36Sopenharmony_ci#include "tda10071.h" 5162306a36Sopenharmony_ci#include "tda18212.h" 5262306a36Sopenharmony_ci#include "a8293.h" 5362306a36Sopenharmony_ci#include "qt1010.h" 5462306a36Sopenharmony_ci#include "mb86a20s.h" 5562306a36Sopenharmony_ci#include "m88ds3103.h" 5662306a36Sopenharmony_ci#include "ts2020.h" 5762306a36Sopenharmony_ci#include "si2168.h" 5862306a36Sopenharmony_ci#include "si2157.h" 5962306a36Sopenharmony_ci#include "tc90522.h" 6062306a36Sopenharmony_ci#include "qm1d1c0042.h" 6162306a36Sopenharmony_ci#include "mxl692.h" 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>"); 6462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6562306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface"); 6662306a36Sopenharmony_ciMODULE_VERSION(EM28XX_VERSION); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic unsigned int debug; 6962306a36Sopenharmony_cimodule_param(debug, int, 0644); 7062306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define dprintk(level, fmt, arg...) do { \ 7562306a36Sopenharmony_ci if (debug >= level) \ 7662306a36Sopenharmony_ci dev_printk(KERN_DEBUG, &dev->intf->dev, \ 7762306a36Sopenharmony_ci "dvb: " fmt, ## arg); \ 7862306a36Sopenharmony_ci} while (0) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistruct em28xx_dvb { 8162306a36Sopenharmony_ci struct dvb_frontend *fe[2]; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* feed count management */ 8462306a36Sopenharmony_ci struct mutex lock; 8562306a36Sopenharmony_ci int nfeeds; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* general boilerplate stuff */ 8862306a36Sopenharmony_ci struct dvb_adapter adapter; 8962306a36Sopenharmony_ci struct dvb_demux demux; 9062306a36Sopenharmony_ci struct dmxdev dmxdev; 9162306a36Sopenharmony_ci struct dmx_frontend fe_hw; 9262306a36Sopenharmony_ci struct dmx_frontend fe_mem; 9362306a36Sopenharmony_ci struct dvb_net net; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* Due to DRX-K - probably need changes */ 9662306a36Sopenharmony_ci int (*gate_ctrl)(struct dvb_frontend *fe, int gate); 9762306a36Sopenharmony_ci struct semaphore pll_mutex; 9862306a36Sopenharmony_ci bool dont_attach_fe1; 9962306a36Sopenharmony_ci int lna_gpio; 10062306a36Sopenharmony_ci struct i2c_client *i2c_client_demod; 10162306a36Sopenharmony_ci struct i2c_client *i2c_client_tuner; 10262306a36Sopenharmony_ci struct i2c_client *i2c_client_sec; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void print_err_status(struct em28xx *dev, 10662306a36Sopenharmony_ci int packet, int status) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci char *errmsg = "Unknown"; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci switch (status) { 11162306a36Sopenharmony_ci case -ENOENT: 11262306a36Sopenharmony_ci errmsg = "unlinked synchronously"; 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci case -ECONNRESET: 11562306a36Sopenharmony_ci errmsg = "unlinked asynchronously"; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci case -ENOSR: 11862306a36Sopenharmony_ci errmsg = "Buffer error (overrun)"; 11962306a36Sopenharmony_ci break; 12062306a36Sopenharmony_ci case -EPIPE: 12162306a36Sopenharmony_ci errmsg = "Stalled (device not responding)"; 12262306a36Sopenharmony_ci break; 12362306a36Sopenharmony_ci case -EOVERFLOW: 12462306a36Sopenharmony_ci errmsg = "Babble (bad cable?)"; 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case -EPROTO: 12762306a36Sopenharmony_ci errmsg = "Bit-stuff error (bad cable?)"; 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci case -EILSEQ: 13062306a36Sopenharmony_ci errmsg = "CRC/Timeout (could be anything)"; 13162306a36Sopenharmony_ci break; 13262306a36Sopenharmony_ci case -ETIME: 13362306a36Sopenharmony_ci errmsg = "Device does not respond"; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci if (packet < 0) { 13762306a36Sopenharmony_ci dprintk(1, "URB status %d [%s].\n", status, errmsg); 13862306a36Sopenharmony_ci } else { 13962306a36Sopenharmony_ci dprintk(1, "URB packet %d, status %d [%s].\n", 14062306a36Sopenharmony_ci packet, status, errmsg); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci int xfer_bulk, num_packets, i; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (!dev) 14962306a36Sopenharmony_ci return 0; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (dev->disconnected) 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (urb->status < 0) 15562306a36Sopenharmony_ci print_err_status(dev, -1, urb->status); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci xfer_bulk = usb_pipebulk(urb->pipe); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (xfer_bulk) /* bulk */ 16062306a36Sopenharmony_ci num_packets = 1; 16162306a36Sopenharmony_ci else /* isoc */ 16262306a36Sopenharmony_ci num_packets = urb->number_of_packets; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci for (i = 0; i < num_packets; i++) { 16562306a36Sopenharmony_ci if (xfer_bulk) { 16662306a36Sopenharmony_ci if (urb->status < 0) { 16762306a36Sopenharmony_ci print_err_status(dev, i, urb->status); 16862306a36Sopenharmony_ci if (urb->status != -EPROTO) 16962306a36Sopenharmony_ci continue; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci if (!urb->actual_length) 17262306a36Sopenharmony_ci continue; 17362306a36Sopenharmony_ci dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, 17462306a36Sopenharmony_ci urb->actual_length); 17562306a36Sopenharmony_ci } else { 17662306a36Sopenharmony_ci if (urb->iso_frame_desc[i].status < 0) { 17762306a36Sopenharmony_ci print_err_status(dev, i, 17862306a36Sopenharmony_ci urb->iso_frame_desc[i].status); 17962306a36Sopenharmony_ci if (urb->iso_frame_desc[i].status != -EPROTO) 18062306a36Sopenharmony_ci continue; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci if (!urb->iso_frame_desc[i].actual_length) 18362306a36Sopenharmony_ci continue; 18462306a36Sopenharmony_ci dvb_dmx_swfilter(&dev->dvb->demux, 18562306a36Sopenharmony_ci urb->transfer_buffer + 18662306a36Sopenharmony_ci urb->iso_frame_desc[i].offset, 18762306a36Sopenharmony_ci urb->iso_frame_desc[i].actual_length); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int em28xx_start_streaming(struct em28xx_dvb *dvb) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci int rc; 19762306a36Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; 19862306a36Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 19962306a36Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(dev->intf); 20062306a36Sopenharmony_ci int dvb_max_packet_size, packet_multiplier, dvb_alt; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (dev->dvb_xfer_bulk) { 20362306a36Sopenharmony_ci if (!dev->dvb_ep_bulk) 20462306a36Sopenharmony_ci return -ENODEV; 20562306a36Sopenharmony_ci dvb_max_packet_size = 512; /* USB 2.0 spec */ 20662306a36Sopenharmony_ci packet_multiplier = EM28XX_DVB_BULK_PACKET_MULTIPLIER; 20762306a36Sopenharmony_ci dvb_alt = 0; 20862306a36Sopenharmony_ci } else { /* isoc */ 20962306a36Sopenharmony_ci if (!dev->dvb_ep_isoc) 21062306a36Sopenharmony_ci return -ENODEV; 21162306a36Sopenharmony_ci dvb_max_packet_size = dev->dvb_max_pkt_size_isoc; 21262306a36Sopenharmony_ci if (dvb_max_packet_size < 0) 21362306a36Sopenharmony_ci return dvb_max_packet_size; 21462306a36Sopenharmony_ci packet_multiplier = EM28XX_DVB_NUM_ISOC_PACKETS; 21562306a36Sopenharmony_ci dvb_alt = dev->dvb_alt_isoc; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if (!dev->board.has_dual_ts) 21962306a36Sopenharmony_ci usb_set_interface(udev, dev->ifnum, dvb_alt); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 22262306a36Sopenharmony_ci if (rc < 0) 22362306a36Sopenharmony_ci return rc; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci dprintk(1, "Using %d buffers each with %d x %d bytes, alternate %d\n", 22662306a36Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 22762306a36Sopenharmony_ci packet_multiplier, 22862306a36Sopenharmony_ci dvb_max_packet_size, dvb_alt); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return em28xx_init_usb_xfer(dev, EM28XX_DIGITAL_MODE, 23162306a36Sopenharmony_ci dev->dvb_xfer_bulk, 23262306a36Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 23362306a36Sopenharmony_ci dvb_max_packet_size, 23462306a36Sopenharmony_ci packet_multiplier, 23562306a36Sopenharmony_ci em28xx_dvb_urb_data_copy); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int em28xx_stop_streaming(struct em28xx_dvb *dvb) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; 24162306a36Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci em28xx_stop_urbs(dev); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic int em28xx_start_feed(struct dvb_demux_feed *feed) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct dvb_demux *demux = feed->demux; 25162306a36Sopenharmony_ci struct em28xx_dvb *dvb = demux->priv; 25262306a36Sopenharmony_ci int rc, ret; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (!demux->dmx.frontend) 25562306a36Sopenharmony_ci return -EINVAL; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci mutex_lock(&dvb->lock); 25862306a36Sopenharmony_ci dvb->nfeeds++; 25962306a36Sopenharmony_ci rc = dvb->nfeeds; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (dvb->nfeeds == 1) { 26262306a36Sopenharmony_ci ret = em28xx_start_streaming(dvb); 26362306a36Sopenharmony_ci if (ret < 0) 26462306a36Sopenharmony_ci rc = ret; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci mutex_unlock(&dvb->lock); 26862306a36Sopenharmony_ci return rc; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic int em28xx_stop_feed(struct dvb_demux_feed *feed) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct dvb_demux *demux = feed->demux; 27462306a36Sopenharmony_ci struct em28xx_dvb *dvb = demux->priv; 27562306a36Sopenharmony_ci int err = 0; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci mutex_lock(&dvb->lock); 27862306a36Sopenharmony_ci dvb->nfeeds--; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (!dvb->nfeeds) 28162306a36Sopenharmony_ci err = em28xx_stop_streaming(dvb); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci mutex_unlock(&dvb->lock); 28462306a36Sopenharmony_ci return err; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 28862306a36Sopenharmony_cistatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 29162306a36Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (acquire) 29462306a36Sopenharmony_ci return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 29562306a36Sopenharmony_ci else 29662306a36Sopenharmony_ci return em28xx_set_mode(dev, EM28XX_SUSPEND); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic struct lgdt330x_config em2880_lgdt3303_dev = { 30262306a36Sopenharmony_ci .demod_chip = LGDT3303, 30362306a36Sopenharmony_ci}; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic struct lgdt3305_config em2870_lgdt3304_dev = { 30662306a36Sopenharmony_ci .i2c_addr = 0x0e, 30762306a36Sopenharmony_ci .demod_chip = LGDT3304, 30862306a36Sopenharmony_ci .spectral_inversion = 1, 30962306a36Sopenharmony_ci .deny_i2c_rptr = 1, 31062306a36Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_PARALLEL, 31162306a36Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 31262306a36Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 31362306a36Sopenharmony_ci .vsb_if_khz = 3250, 31462306a36Sopenharmony_ci .qam_if_khz = 4000, 31562306a36Sopenharmony_ci}; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic struct lgdt3305_config em2874_lgdt3305_dev = { 31862306a36Sopenharmony_ci .i2c_addr = 0x0e, 31962306a36Sopenharmony_ci .demod_chip = LGDT3305, 32062306a36Sopenharmony_ci .spectral_inversion = 1, 32162306a36Sopenharmony_ci .deny_i2c_rptr = 0, 32262306a36Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_SERIAL, 32362306a36Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 32462306a36Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 32562306a36Sopenharmony_ci .vsb_if_khz = 3250, 32662306a36Sopenharmony_ci .qam_if_khz = 4000, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic struct lgdt3305_config em2874_lgdt3305_nogate_dev = { 33062306a36Sopenharmony_ci .i2c_addr = 0x0e, 33162306a36Sopenharmony_ci .demod_chip = LGDT3305, 33262306a36Sopenharmony_ci .spectral_inversion = 1, 33362306a36Sopenharmony_ci .deny_i2c_rptr = 1, 33462306a36Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_SERIAL, 33562306a36Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 33662306a36Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 33762306a36Sopenharmony_ci .vsb_if_khz = 3600, 33862306a36Sopenharmony_ci .qam_if_khz = 3600, 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic struct s921_config sharp_isdbt = { 34262306a36Sopenharmony_ci .demod_address = 0x30 >> 1 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 34662306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 34762306a36Sopenharmony_ci .no_tuner = 1, 34862306a36Sopenharmony_ci .parallel_ts = 1, 34962306a36Sopenharmony_ci .if2 = 45600, 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic struct s5h1409_config em28xx_s5h1409_with_xc3028 = { 35362306a36Sopenharmony_ci .demod_address = 0x32 >> 1, 35462306a36Sopenharmony_ci .output_mode = S5H1409_PARALLEL_OUTPUT, 35562306a36Sopenharmony_ci .gpio = S5H1409_GPIO_OFF, 35662306a36Sopenharmony_ci .inversion = S5H1409_INVERSION_OFF, 35762306a36Sopenharmony_ci .status_mode = S5H1409_DEMODLOCKING, 35862306a36Sopenharmony_ci .mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic struct tda18271_std_map kworld_a340_std_map = { 36262306a36Sopenharmony_ci .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, 36362306a36Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 36462306a36Sopenharmony_ci .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, 36562306a36Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 36662306a36Sopenharmony_ci}; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic struct tda18271_config kworld_a340_config = { 36962306a36Sopenharmony_ci .std_map = &kworld_a340_std_map, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic struct tda18271_config kworld_ub435q_v2_config = { 37362306a36Sopenharmony_ci .std_map = &kworld_a340_std_map, 37462306a36Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic struct tda18212_config kworld_ub435q_v3_config = { 37862306a36Sopenharmony_ci .if_atsc_vsb = 3600, 37962306a36Sopenharmony_ci .if_atsc_qam = 3600, 38062306a36Sopenharmony_ci}; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { 38362306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 38462306a36Sopenharmony_ci .no_tuner = 1, 38562306a36Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 38662306a36Sopenharmony_ci .parallel_ts = 1, 38762306a36Sopenharmony_ci .if2 = 45600, 38862306a36Sopenharmony_ci}; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic struct drxd_config em28xx_drxd = { 39162306a36Sopenharmony_ci .demod_address = 0x70, 39262306a36Sopenharmony_ci .demod_revision = 0xa2, 39362306a36Sopenharmony_ci .pll_type = DRXD_PLL_NONE, 39462306a36Sopenharmony_ci .clock = 12000, 39562306a36Sopenharmony_ci .insert_rs_byte = 1, 39662306a36Sopenharmony_ci .IF = 42800000, 39762306a36Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic struct drxk_config terratec_h5_drxk = { 40162306a36Sopenharmony_ci .adr = 0x29, 40262306a36Sopenharmony_ci .single_master = 1, 40362306a36Sopenharmony_ci .no_i2c_bridge = 1, 40462306a36Sopenharmony_ci .microcode_name = "dvb-usb-terratec-h5-drxk.fw", 40562306a36Sopenharmony_ci .qam_demod_parameter_count = 2, 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic struct drxk_config hauppauge_930c_drxk = { 40962306a36Sopenharmony_ci .adr = 0x29, 41062306a36Sopenharmony_ci .single_master = 1, 41162306a36Sopenharmony_ci .no_i2c_bridge = 1, 41262306a36Sopenharmony_ci .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", 41362306a36Sopenharmony_ci .chunk_size = 56, 41462306a36Sopenharmony_ci .qam_demod_parameter_count = 2, 41562306a36Sopenharmony_ci}; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct drxk_config terratec_htc_stick_drxk = { 41862306a36Sopenharmony_ci .adr = 0x29, 41962306a36Sopenharmony_ci .single_master = 1, 42062306a36Sopenharmony_ci .no_i2c_bridge = 1, 42162306a36Sopenharmony_ci .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw", 42262306a36Sopenharmony_ci .chunk_size = 54, 42362306a36Sopenharmony_ci .qam_demod_parameter_count = 2, 42462306a36Sopenharmony_ci /* Required for the antenna_gpio to disable LNA. */ 42562306a36Sopenharmony_ci .antenna_dvbt = true, 42662306a36Sopenharmony_ci /* The windows driver uses the same. This will disable LNA. */ 42762306a36Sopenharmony_ci .antenna_gpio = 0x6, 42862306a36Sopenharmony_ci}; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic struct drxk_config maxmedia_ub425_tc_drxk = { 43162306a36Sopenharmony_ci .adr = 0x29, 43262306a36Sopenharmony_ci .single_master = 1, 43362306a36Sopenharmony_ci .no_i2c_bridge = 1, 43462306a36Sopenharmony_ci .microcode_name = "dvb-demod-drxk-01.fw", 43562306a36Sopenharmony_ci .chunk_size = 62, 43662306a36Sopenharmony_ci .qam_demod_parameter_count = 2, 43762306a36Sopenharmony_ci}; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic struct drxk_config pctv_520e_drxk = { 44062306a36Sopenharmony_ci .adr = 0x29, 44162306a36Sopenharmony_ci .single_master = 1, 44262306a36Sopenharmony_ci .microcode_name = "dvb-demod-drxk-pctv.fw", 44362306a36Sopenharmony_ci .qam_demod_parameter_count = 2, 44462306a36Sopenharmony_ci .chunk_size = 58, 44562306a36Sopenharmony_ci .antenna_dvbt = true, /* disable LNA */ 44662306a36Sopenharmony_ci .antenna_gpio = (1 << 2), /* disable LNA */ 44762306a36Sopenharmony_ci}; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct em28xx_dvb *dvb = fe->sec_priv; 45262306a36Sopenharmony_ci int status; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (!dvb) 45562306a36Sopenharmony_ci return -EINVAL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci if (enable) { 45862306a36Sopenharmony_ci down(&dvb->pll_mutex); 45962306a36Sopenharmony_ci status = dvb->gate_ctrl(fe, 1); 46062306a36Sopenharmony_ci } else { 46162306a36Sopenharmony_ci status = dvb->gate_ctrl(fe, 0); 46262306a36Sopenharmony_ci up(&dvb->pll_mutex); 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci return status; 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic void hauppauge_hvr930c_init(struct em28xx *dev) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci int i; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci static const struct em28xx_reg_seq hauppauge_hvr930c_init[] = { 47262306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0x65}, 47362306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xfb, 0xff, 0x32}, 47462306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0xb8}, 47562306a36Sopenharmony_ci { -1, -1, -1, -1}, 47662306a36Sopenharmony_ci }; 47762306a36Sopenharmony_ci static const struct em28xx_reg_seq hauppauge_hvr930c_end[] = { 47862306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, 47962306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xaf, 0xff, 0x65}, 48062306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x76}, 48162306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, 48262306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, 48362306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x40}, 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x65}, 48662306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, 48762306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, 48862306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci { -1, -1, -1, -1}, 49162306a36Sopenharmony_ci }; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci static const struct { 49462306a36Sopenharmony_ci unsigned char r[4]; 49562306a36Sopenharmony_ci int len; 49662306a36Sopenharmony_ci } regs[] = { 49762306a36Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 49862306a36Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 49962306a36Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 50062306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 50162306a36Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 50262306a36Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 50362306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 50462306a36Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 50562306a36Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 50662306a36Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 50762306a36Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 50862306a36Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 50962306a36Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 51062306a36Sopenharmony_ci }; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci em28xx_gpio_set(dev, hauppauge_hvr930c_init); 51362306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 51462306a36Sopenharmony_ci usleep_range(10000, 11000); 51562306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 51662306a36Sopenharmony_ci usleep_range(10000, 11000); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 52162306a36Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 52262306a36Sopenharmony_ci regs[i].r, regs[i].len); 52362306a36Sopenharmony_ci em28xx_gpio_set(dev, hauppauge_hvr930c_end); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci msleep(100); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 52862306a36Sopenharmony_ci msleep(30); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); 53162306a36Sopenharmony_ci usleep_range(10000, 11000); 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic void terratec_h5_init(struct em28xx *dev) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci int i; 53762306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_h5_init[] = { 53862306a36Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 53962306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 54062306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, 54162306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 54262306a36Sopenharmony_ci { -1, -1, -1, -1}, 54362306a36Sopenharmony_ci }; 54462306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_h5_end[] = { 54562306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 54662306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, 54762306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 54862306a36Sopenharmony_ci { -1, -1, -1, -1}, 54962306a36Sopenharmony_ci }; 55062306a36Sopenharmony_ci static const struct { 55162306a36Sopenharmony_ci unsigned char r[4]; 55262306a36Sopenharmony_ci int len; 55362306a36Sopenharmony_ci } regs[] = { 55462306a36Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 55562306a36Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 55662306a36Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 55762306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 55862306a36Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 55962306a36Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 56062306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 56162306a36Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 56262306a36Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 56362306a36Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 56462306a36Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 56562306a36Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 56662306a36Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 56762306a36Sopenharmony_ci }; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_h5_init); 57062306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 57162306a36Sopenharmony_ci usleep_range(10000, 11000); 57262306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); 57362306a36Sopenharmony_ci usleep_range(10000, 11000); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 57862306a36Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 57962306a36Sopenharmony_ci regs[i].r, regs[i].len); 58062306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_h5_end); 58162306a36Sopenharmony_ci}; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic void terratec_htc_stick_init(struct em28xx *dev) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci int i; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* 58862306a36Sopenharmony_ci * GPIO configuration: 58962306a36Sopenharmony_ci * 0xff: unknown (does not affect DVB-T). 59062306a36Sopenharmony_ci * 0xf6: DRX-K (demodulator). 59162306a36Sopenharmony_ci * 0xe6: unknown (does not affect DVB-T). 59262306a36Sopenharmony_ci * 0xb6: unknown (does not affect DVB-T). 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_stick_init[] = { 59562306a36Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 59662306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 59762306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, 59862306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 59962306a36Sopenharmony_ci { -1, -1, -1, -1}, 60062306a36Sopenharmony_ci }; 60162306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_stick_end[] = { 60262306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, 60362306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, 60462306a36Sopenharmony_ci { -1, -1, -1, -1}, 60562306a36Sopenharmony_ci }; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* 60862306a36Sopenharmony_ci * Init the analog decoder (not yet supported), but 60962306a36Sopenharmony_ci * it's probably still a good idea. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci static const struct { 61262306a36Sopenharmony_ci unsigned char r[4]; 61362306a36Sopenharmony_ci int len; 61462306a36Sopenharmony_ci } regs[] = { 61562306a36Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 61662306a36Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 61762306a36Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 61862306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 61962306a36Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 62062306a36Sopenharmony_ci }; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_stick_init); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 62562306a36Sopenharmony_ci usleep_range(10000, 11000); 62662306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 62762306a36Sopenharmony_ci usleep_range(10000, 11000); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 63262306a36Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 63362306a36Sopenharmony_ci regs[i].r, regs[i].len); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_stick_end); 63662306a36Sopenharmony_ci}; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic void terratec_htc_usb_xs_init(struct em28xx *dev) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci int i; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { 64362306a36Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 64462306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, 64562306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, 64662306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, 64762306a36Sopenharmony_ci { -1, -1, -1, -1}, 64862306a36Sopenharmony_ci }; 64962306a36Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { 65062306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 100}, 65162306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, 65262306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 65362306a36Sopenharmony_ci { -1, -1, -1, -1}, 65462306a36Sopenharmony_ci }; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* 65762306a36Sopenharmony_ci * Init the analog decoder (not yet supported), but 65862306a36Sopenharmony_ci * it's probably still a good idea. 65962306a36Sopenharmony_ci */ 66062306a36Sopenharmony_ci static const struct { 66162306a36Sopenharmony_ci unsigned char r[4]; 66262306a36Sopenharmony_ci int len; 66362306a36Sopenharmony_ci } regs[] = { 66462306a36Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 66562306a36Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 66662306a36Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 66762306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 66862306a36Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 66962306a36Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 67062306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 67162306a36Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 67262306a36Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 67362306a36Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 67462306a36Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 67562306a36Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 67662306a36Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 67762306a36Sopenharmony_ci }; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_usb_xs_init); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 68462306a36Sopenharmony_ci usleep_range(10000, 11000); 68562306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 68662306a36Sopenharmony_ci usleep_range(10000, 11000); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 69162306a36Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 69262306a36Sopenharmony_ci regs[i].r, regs[i].len); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_usb_xs_end); 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic void pctv_520e_init(struct em28xx *dev) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci /* 70062306a36Sopenharmony_ci * Init AVF4910B analog decoder. Looks like I2C traffic to 70162306a36Sopenharmony_ci * digital demodulator and tuner are routed via AVF4910B. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci int i; 70462306a36Sopenharmony_ci static const struct { 70562306a36Sopenharmony_ci unsigned char r[4]; 70662306a36Sopenharmony_ci int len; 70762306a36Sopenharmony_ci } regs[] = { 70862306a36Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 70962306a36Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 71062306a36Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 71162306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 71262306a36Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 71362306a36Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 71462306a36Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 71562306a36Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 71662306a36Sopenharmony_ci }; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; /* 0x41 */ 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 72162306a36Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 72262306a36Sopenharmony_ci regs[i].r, regs[i].len); 72362306a36Sopenharmony_ci}; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_cistatic int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) 72662306a36Sopenharmony_ci{ 72762306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 72862306a36Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 72962306a36Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 73062306a36Sopenharmony_ci#ifdef CONFIG_GPIOLIB 73162306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 73262306a36Sopenharmony_ci int ret; 73362306a36Sopenharmony_ci unsigned long flags; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (c->lna == 1) 73662306a36Sopenharmony_ci flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */ 73762306a36Sopenharmony_ci else 73862306a36Sopenharmony_ci flags = GPIOF_OUT_INIT_LOW; /* disable LNA */ 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci ret = gpio_request_one(dvb->lna_gpio, flags, NULL); 74162306a36Sopenharmony_ci if (ret) 74262306a36Sopenharmony_ci dev_err(&dev->intf->dev, "gpio request failed %d\n", ret); 74362306a36Sopenharmony_ci else 74462306a36Sopenharmony_ci gpio_free(dvb->lna_gpio); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci return ret; 74762306a36Sopenharmony_ci#else 74862306a36Sopenharmony_ci dev_warn(&dev->intf->dev, "%s: LNA control is disabled (lna=%u)\n", 74962306a36Sopenharmony_ci KBUILD_MODNAME, c->lna); 75062306a36Sopenharmony_ci return 0; 75162306a36Sopenharmony_ci#endif 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_cistatic int em28xx_pctv_292e_set_lna(struct dvb_frontend *fe) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 75762306a36Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 75862306a36Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 75962306a36Sopenharmony_ci u8 lna; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci if (c->lna == 1) 76262306a36Sopenharmony_ci lna = 0x01; 76362306a36Sopenharmony_ci else 76462306a36Sopenharmony_ci lna = 0x00; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci return em28xx_write_reg_bits(dev, EM2874_R80_GPIO_P0_CTRL, lna, 0x01); 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci /* Values extracted from a USB trace of the Terratec Windows driver */ 77262306a36Sopenharmony_ci static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; 77362306a36Sopenharmony_ci static u8 reset[] = { RESET, 0x80 }; 77462306a36Sopenharmony_ci static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 77562306a36Sopenharmony_ci static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; 77662306a36Sopenharmony_ci static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; 77762306a36Sopenharmony_ci static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; 77862306a36Sopenharmony_ci static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 77962306a36Sopenharmony_ci static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; 78062306a36Sopenharmony_ci static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; 78162306a36Sopenharmony_ci static u8 tuner_go[] = { TUNER_GO, 0x01}; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 78462306a36Sopenharmony_ci usleep_range(200, 250); 78562306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 78662306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 78762306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 78862306a36Sopenharmony_ci mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); 78962306a36Sopenharmony_ci mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); 79062306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 79162306a36Sopenharmony_ci mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); 79262306a36Sopenharmony_ci mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); 79362306a36Sopenharmony_ci mt352_write(fe, tuner_go, sizeof(tuner_go)); 79462306a36Sopenharmony_ci return 0; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic void px_bcud_init(struct em28xx *dev) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci int i; 80062306a36Sopenharmony_ci static const struct { 80162306a36Sopenharmony_ci unsigned char r[4]; 80262306a36Sopenharmony_ci int len; 80362306a36Sopenharmony_ci } regs1[] = { 80462306a36Sopenharmony_ci {{ 0x0e, 0x77 }, 2}, 80562306a36Sopenharmony_ci {{ 0x0f, 0x77 }, 2}, 80662306a36Sopenharmony_ci {{ 0x03, 0x90 }, 2}, 80762306a36Sopenharmony_ci }, regs2[] = { 80862306a36Sopenharmony_ci {{ 0x07, 0x01 }, 2}, 80962306a36Sopenharmony_ci {{ 0x08, 0x10 }, 2}, 81062306a36Sopenharmony_ci {{ 0x13, 0x00 }, 2}, 81162306a36Sopenharmony_ci {{ 0x17, 0x00 }, 2}, 81262306a36Sopenharmony_ci {{ 0x03, 0x01 }, 2}, 81362306a36Sopenharmony_ci {{ 0x10, 0xb1 }, 2}, 81462306a36Sopenharmony_ci {{ 0x11, 0x40 }, 2}, 81562306a36Sopenharmony_ci {{ 0x85, 0x7a }, 2}, 81662306a36Sopenharmony_ci {{ 0x87, 0x04 }, 2}, 81762306a36Sopenharmony_ci }; 81862306a36Sopenharmony_ci static const struct em28xx_reg_seq gpio[] = { 81962306a36Sopenharmony_ci {EM28XX_R06_I2C_CLK, 0x40, 0xff, 300}, 82062306a36Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 60}, 82162306a36Sopenharmony_ci {EM28XX_R15_RGAIN, 0x20, 0xff, 0}, 82262306a36Sopenharmony_ci {EM28XX_R16_GGAIN, 0x20, 0xff, 0}, 82362306a36Sopenharmony_ci {EM28XX_R17_BGAIN, 0x20, 0xff, 0}, 82462306a36Sopenharmony_ci {EM28XX_R18_ROFFSET, 0x00, 0xff, 0}, 82562306a36Sopenharmony_ci {EM28XX_R19_GOFFSET, 0x00, 0xff, 0}, 82662306a36Sopenharmony_ci {EM28XX_R1A_BOFFSET, 0x00, 0xff, 0}, 82762306a36Sopenharmony_ci {EM28XX_R23_UOFFSET, 0x00, 0xff, 0}, 82862306a36Sopenharmony_ci {EM28XX_R24_VOFFSET, 0x00, 0xff, 0}, 82962306a36Sopenharmony_ci {EM28XX_R26_COMPR, 0x00, 0xff, 0}, 83062306a36Sopenharmony_ci {0x13, 0x08, 0xff, 0}, 83162306a36Sopenharmony_ci {EM28XX_R12_VINENABLE, 0x27, 0xff, 0}, 83262306a36Sopenharmony_ci {EM28XX_R0C_USBSUSP, 0x10, 0xff, 0}, 83362306a36Sopenharmony_ci {EM28XX_R27_OUTFMT, 0x00, 0xff, 0}, 83462306a36Sopenharmony_ci {EM28XX_R10_VINMODE, 0x00, 0xff, 0}, 83562306a36Sopenharmony_ci {EM28XX_R11_VINCTRL, 0x11, 0xff, 0}, 83662306a36Sopenharmony_ci {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0}, 83762306a36Sopenharmony_ci {EM2874_R5F_TS_ENABLE, 0x80, 0xff, 0}, 83862306a36Sopenharmony_ci {EM28XX_R06_I2C_CLK, 0x46, 0xff, 0}, 83962306a36Sopenharmony_ci }; 84062306a36Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46); 84162306a36Sopenharmony_ci /* sleeping ISDB-T */ 84262306a36Sopenharmony_ci dev->dvb->i2c_client_demod->addr = 0x14; 84362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs1); i++) 84462306a36Sopenharmony_ci i2c_master_send(dev->dvb->i2c_client_demod, 84562306a36Sopenharmony_ci regs1[i].r, regs1[i].len); 84662306a36Sopenharmony_ci /* sleeping ISDB-S */ 84762306a36Sopenharmony_ci dev->dvb->i2c_client_demod->addr = 0x15; 84862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs2); i++) 84962306a36Sopenharmony_ci i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r, 85062306a36Sopenharmony_ci regs2[i].len); 85162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(gpio); i++) { 85262306a36Sopenharmony_ci em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val, 85362306a36Sopenharmony_ci gpio[i].mask); 85462306a36Sopenharmony_ci if (gpio[i].sleep > 0) 85562306a36Sopenharmony_ci msleep(gpio[i].sleep); 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci}; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic struct mt352_config terratec_xs_mt352_cfg = { 86062306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 86162306a36Sopenharmony_ci .no_tuner = 1, 86262306a36Sopenharmony_ci .if2 = 45600, 86362306a36Sopenharmony_ci .demod_init = em28xx_mt352_terratec_xs_init, 86462306a36Sopenharmony_ci}; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_cistatic struct tda10023_config em28xx_tda10023_config = { 86762306a36Sopenharmony_ci .demod_address = 0x0c, 86862306a36Sopenharmony_ci .invert = 1, 86962306a36Sopenharmony_ci}; 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic struct cxd2820r_config em28xx_cxd2820r_config = { 87262306a36Sopenharmony_ci .i2c_address = (0xd8 >> 1), 87362306a36Sopenharmony_ci .ts_mode = CXD2820R_TS_SERIAL, 87462306a36Sopenharmony_ci}; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_cistatic struct tda18271_config em28xx_cxd2820r_tda18271_config = { 87762306a36Sopenharmony_ci .output_opt = TDA18271_OUTPUT_LT_OFF, 87862306a36Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 87962306a36Sopenharmony_ci}; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { 88262306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 88362306a36Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 88462306a36Sopenharmony_ci .no_tuner = 1, 88562306a36Sopenharmony_ci .parallel_ts = 1, 88662306a36Sopenharmony_ci}; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic struct mt2060_config em28xx_mt2060_config = { 88962306a36Sopenharmony_ci .i2c_address = 0x60, 89062306a36Sopenharmony_ci}; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic struct qt1010_config em28xx_qt1010_config = { 89362306a36Sopenharmony_ci .i2c_address = 0x62 89462306a36Sopenharmony_ci}; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_cistatic const struct mb86a20s_config c3tech_duo_mb86a20s_config = { 89762306a36Sopenharmony_ci .demod_address = 0x10, 89862306a36Sopenharmony_ci .is_serial = true, 89962306a36Sopenharmony_ci}; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_cistatic struct tda18271_std_map mb86a20s_tda18271_config = { 90262306a36Sopenharmony_ci .dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4, 90362306a36Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 90462306a36Sopenharmony_ci}; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_cistatic struct tda18271_config c3tech_duo_tda18271_config = { 90762306a36Sopenharmony_ci .std_map = &mb86a20s_tda18271_config, 90862306a36Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 90962306a36Sopenharmony_ci .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, 91062306a36Sopenharmony_ci}; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic struct tda18271_std_map drx_j_std_map = { 91362306a36Sopenharmony_ci .atsc_6 = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1, 91462306a36Sopenharmony_ci .rfagc_top = 0x37, }, 91562306a36Sopenharmony_ci .qam_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, .if_lvl = 1, 91662306a36Sopenharmony_ci .rfagc_top = 0x37, }, 91762306a36Sopenharmony_ci}; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_cistatic struct tda18271_config pinnacle_80e_dvb_config = { 92062306a36Sopenharmony_ci .std_map = &drx_j_std_map, 92162306a36Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 92262306a36Sopenharmony_ci .role = TDA18271_MASTER, 92362306a36Sopenharmony_ci}; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = { 92662306a36Sopenharmony_ci .qam_if_khz = 4000, 92762306a36Sopenharmony_ci .vsb_if_khz = 3250, 92862306a36Sopenharmony_ci .spectral_inversion = 0, 92962306a36Sopenharmony_ci .deny_i2c_rptr = 0, 93062306a36Sopenharmony_ci .mpeg_mode = LGDT3306A_MPEG_SERIAL, 93162306a36Sopenharmony_ci .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, 93262306a36Sopenharmony_ci .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, 93362306a36Sopenharmony_ci .xtalMHz = 25, 93462306a36Sopenharmony_ci}; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic noinline_for_stack int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci struct dvb_frontend *fe; 94162306a36Sopenharmony_ci struct xc2028_config cfg; 94262306a36Sopenharmony_ci struct xc2028_ctrl ctl; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 94562306a36Sopenharmony_ci cfg.i2c_adap = &dev->i2c_adap[dev->def_i2c_bus]; 94662306a36Sopenharmony_ci cfg.i2c_addr = addr; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci memset(&ctl, 0, sizeof(ctl)); 94962306a36Sopenharmony_ci em28xx_setup_xc3028(dev, &ctl); 95062306a36Sopenharmony_ci cfg.ctrl = &ctl; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci if (!dev->dvb->fe[0]) { 95362306a36Sopenharmony_ci dev_err(&dev->intf->dev, 95462306a36Sopenharmony_ci "dvb frontend not attached. Can't attach xc3028\n"); 95562306a36Sopenharmony_ci return -EINVAL; 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); 95962306a36Sopenharmony_ci if (!fe) { 96062306a36Sopenharmony_ci dev_err(&dev->intf->dev, "xc3028 attach failed\n"); 96162306a36Sopenharmony_ci dvb_frontend_detach(dev->dvb->fe[0]); 96262306a36Sopenharmony_ci dev->dvb->fe[0] = NULL; 96362306a36Sopenharmony_ci return -EINVAL; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci dev_info(&dev->intf->dev, "xc3028 attached\n"); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci return 0; 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_cistatic int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, 97462306a36Sopenharmony_ci struct em28xx *dev, struct device *device) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci int result; 97762306a36Sopenharmony_ci bool create_rf_connector = false; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci mutex_init(&dvb->lock); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci /* register adapter */ 98262306a36Sopenharmony_ci result = dvb_register_adapter(&dvb->adapter, 98362306a36Sopenharmony_ci dev_name(&dev->intf->dev), module, 98462306a36Sopenharmony_ci device, adapter_nr); 98562306a36Sopenharmony_ci if (result < 0) { 98662306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 98762306a36Sopenharmony_ci "dvb_register_adapter failed (errno = %d)\n", 98862306a36Sopenharmony_ci result); 98962306a36Sopenharmony_ci goto fail_adapter; 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 99262306a36Sopenharmony_ci dvb->adapter.mdev = dev->media_dev; 99362306a36Sopenharmony_ci#endif 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci /* Ensure all frontends negotiate bus access */ 99662306a36Sopenharmony_ci dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 99762306a36Sopenharmony_ci if (dvb->fe[1]) 99862306a36Sopenharmony_ci dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci dvb->adapter.priv = &dev->i2c_bus[dev->def_i2c_bus]; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci /* register frontend */ 100362306a36Sopenharmony_ci result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); 100462306a36Sopenharmony_ci if (result < 0) { 100562306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 100662306a36Sopenharmony_ci "dvb_register_frontend failed (errno = %d)\n", 100762306a36Sopenharmony_ci result); 100862306a36Sopenharmony_ci goto fail_frontend0; 100962306a36Sopenharmony_ci } 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* register 2nd frontend */ 101262306a36Sopenharmony_ci if (dvb->fe[1]) { 101362306a36Sopenharmony_ci result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); 101462306a36Sopenharmony_ci if (result < 0) { 101562306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 101662306a36Sopenharmony_ci "2nd dvb_register_frontend failed (errno = %d)\n", 101762306a36Sopenharmony_ci result); 101862306a36Sopenharmony_ci goto fail_frontend1; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci /* register demux stuff */ 102362306a36Sopenharmony_ci dvb->demux.dmx.capabilities = 102462306a36Sopenharmony_ci DMX_TS_FILTERING | DMX_SECTION_FILTERING | 102562306a36Sopenharmony_ci DMX_MEMORY_BASED_FILTERING; 102662306a36Sopenharmony_ci dvb->demux.priv = dvb; 102762306a36Sopenharmony_ci dvb->demux.filternum = 256; 102862306a36Sopenharmony_ci dvb->demux.feednum = 256; 102962306a36Sopenharmony_ci dvb->demux.start_feed = em28xx_start_feed; 103062306a36Sopenharmony_ci dvb->demux.stop_feed = em28xx_stop_feed; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci result = dvb_dmx_init(&dvb->demux); 103362306a36Sopenharmony_ci if (result < 0) { 103462306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 103562306a36Sopenharmony_ci "dvb_dmx_init failed (errno = %d)\n", 103662306a36Sopenharmony_ci result); 103762306a36Sopenharmony_ci goto fail_dmx; 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci dvb->dmxdev.filternum = 256; 104162306a36Sopenharmony_ci dvb->dmxdev.demux = &dvb->demux.dmx; 104262306a36Sopenharmony_ci dvb->dmxdev.capabilities = 0; 104362306a36Sopenharmony_ci result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 104462306a36Sopenharmony_ci if (result < 0) { 104562306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 104662306a36Sopenharmony_ci "dvb_dmxdev_init failed (errno = %d)\n", 104762306a36Sopenharmony_ci result); 104862306a36Sopenharmony_ci goto fail_dmxdev; 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci dvb->fe_hw.source = DMX_FRONTEND_0; 105262306a36Sopenharmony_ci result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 105362306a36Sopenharmony_ci if (result < 0) { 105462306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 105562306a36Sopenharmony_ci "add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 105662306a36Sopenharmony_ci result); 105762306a36Sopenharmony_ci goto fail_fe_hw; 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci dvb->fe_mem.source = DMX_MEMORY_FE; 106162306a36Sopenharmony_ci result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 106262306a36Sopenharmony_ci if (result < 0) { 106362306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 106462306a36Sopenharmony_ci "add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 106562306a36Sopenharmony_ci result); 106662306a36Sopenharmony_ci goto fail_fe_mem; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 107062306a36Sopenharmony_ci if (result < 0) { 107162306a36Sopenharmony_ci dev_warn(&dev->intf->dev, 107262306a36Sopenharmony_ci "connect_frontend failed (errno = %d)\n", 107362306a36Sopenharmony_ci result); 107462306a36Sopenharmony_ci goto fail_fe_conn; 107562306a36Sopenharmony_ci } 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci /* register network adapter */ 107862306a36Sopenharmony_ci dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci /* If the analog part won't create RF connectors, DVB will do it */ 108162306a36Sopenharmony_ci if (!dev->has_video || dev->tuner_type == TUNER_ABSENT) 108262306a36Sopenharmony_ci create_rf_connector = true; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci result = dvb_create_media_graph(&dvb->adapter, create_rf_connector); 108562306a36Sopenharmony_ci if (result < 0) 108662306a36Sopenharmony_ci goto fail_create_graph; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci return 0; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cifail_create_graph: 109162306a36Sopenharmony_ci dvb_net_release(&dvb->net); 109262306a36Sopenharmony_cifail_fe_conn: 109362306a36Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 109462306a36Sopenharmony_cifail_fe_mem: 109562306a36Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 109662306a36Sopenharmony_cifail_fe_hw: 109762306a36Sopenharmony_ci dvb_dmxdev_release(&dvb->dmxdev); 109862306a36Sopenharmony_cifail_dmxdev: 109962306a36Sopenharmony_ci dvb_dmx_release(&dvb->demux); 110062306a36Sopenharmony_cifail_dmx: 110162306a36Sopenharmony_ci if (dvb->fe[1]) 110262306a36Sopenharmony_ci dvb_unregister_frontend(dvb->fe[1]); 110362306a36Sopenharmony_ci dvb_unregister_frontend(dvb->fe[0]); 110462306a36Sopenharmony_cifail_frontend1: 110562306a36Sopenharmony_ci if (dvb->fe[1]) 110662306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[1]); 110762306a36Sopenharmony_cifail_frontend0: 110862306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 110962306a36Sopenharmony_ci dvb_unregister_adapter(&dvb->adapter); 111062306a36Sopenharmony_cifail_adapter: 111162306a36Sopenharmony_ci return result; 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_cistatic void em28xx_unregister_dvb(struct em28xx_dvb *dvb) 111562306a36Sopenharmony_ci{ 111662306a36Sopenharmony_ci dvb_net_release(&dvb->net); 111762306a36Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 111862306a36Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 111962306a36Sopenharmony_ci dvb_dmxdev_release(&dvb->dmxdev); 112062306a36Sopenharmony_ci dvb_dmx_release(&dvb->demux); 112162306a36Sopenharmony_ci if (dvb->fe[1]) 112262306a36Sopenharmony_ci dvb_unregister_frontend(dvb->fe[1]); 112362306a36Sopenharmony_ci dvb_unregister_frontend(dvb->fe[0]); 112462306a36Sopenharmony_ci if (dvb->fe[1] && !dvb->dont_attach_fe1) 112562306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[1]); 112662306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 112762306a36Sopenharmony_ci dvb_unregister_adapter(&dvb->adapter); 112862306a36Sopenharmony_ci} 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_cistatic int em28174_dvb_init_pctv_460e(struct em28xx *dev) 113162306a36Sopenharmony_ci{ 113262306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 113362306a36Sopenharmony_ci struct tda10071_platform_data tda10071_pdata = {}; 113462306a36Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci /* attach demod + tuner combo */ 113762306a36Sopenharmony_ci tda10071_pdata.clk = 40444000; /* 40.444 MHz */ 113862306a36Sopenharmony_ci tda10071_pdata.i2c_wr_max = 64; 113962306a36Sopenharmony_ci tda10071_pdata.ts_mode = TDA10071_TS_SERIAL; 114062306a36Sopenharmony_ci tda10071_pdata.pll_multiplier = 20; 114162306a36Sopenharmony_ci tda10071_pdata.tuner_i2c_addr = 0x14; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("tda10071", "tda10071_cx24118", 114462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 114562306a36Sopenharmony_ci 0x55, &tda10071_pdata); 114662306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 114762306a36Sopenharmony_ci return -ENODEV; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci dvb->fe[0] = tda10071_pdata.get_dvb_frontend(dvb->i2c_client_demod); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci /* attach SEC */ 115262306a36Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 115562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 115662306a36Sopenharmony_ci 0x08, &a8293_pdata); 115762306a36Sopenharmony_ci if (!dvb->i2c_client_sec) { 115862306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 115962306a36Sopenharmony_ci return -ENODEV; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci return 0; 116362306a36Sopenharmony_ci} 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_cistatic int em28178_dvb_init_pctv_461e(struct em28xx *dev) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 116862306a36Sopenharmony_ci struct i2c_adapter *i2c_adapter; 116962306a36Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 117062306a36Sopenharmony_ci struct ts2020_config ts2020_config = {}; 117162306a36Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* attach demod */ 117462306a36Sopenharmony_ci m88ds3103_pdata.clk = 27000000; 117562306a36Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33; 117662306a36Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; 117762306a36Sopenharmony_ci m88ds3103_pdata.ts_clk = 16000; 117862306a36Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 1; 117962306a36Sopenharmony_ci m88ds3103_pdata.agc = 0x99; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 118262306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 118362306a36Sopenharmony_ci 0x68, &m88ds3103_pdata); 118462306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 118562306a36Sopenharmony_ci return -ENODEV; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); 118862306a36Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci /* attach tuner */ 119162306a36Sopenharmony_ci ts2020_config.fe = dvb->fe[0]; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", 119462306a36Sopenharmony_ci i2c_adapter, 119562306a36Sopenharmony_ci 0x60, &ts2020_config); 119662306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 119762306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 119862306a36Sopenharmony_ci return -ENODEV; 119962306a36Sopenharmony_ci } 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci /* delegate signal strength measurement to tuner */ 120262306a36Sopenharmony_ci dvb->fe[0]->ops.read_signal_strength = 120362306a36Sopenharmony_ci dvb->fe[0]->ops.tuner_ops.get_rf_strength; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci /* attach SEC */ 120662306a36Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 120762306a36Sopenharmony_ci /* 120862306a36Sopenharmony_ci * 461e has a tendency to have vIN undervoltage troubles. 120962306a36Sopenharmony_ci * Slew mitigates this. 121062306a36Sopenharmony_ci */ 121162306a36Sopenharmony_ci a8293_pdata.volt_slew_nanos_per_mv = 20; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 121462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 121562306a36Sopenharmony_ci 0x08, &a8293_pdata); 121662306a36Sopenharmony_ci if (!dvb->i2c_client_sec) { 121762306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 121862306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 121962306a36Sopenharmony_ci return -ENODEV; 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return 0; 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_cistatic int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev) 122662306a36Sopenharmony_ci{ 122762306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 122862306a36Sopenharmony_ci struct i2c_adapter *i2c_adapter; 122962306a36Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 123062306a36Sopenharmony_ci struct ts2020_config ts2020_config = {}; 123162306a36Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci /* attach demod */ 123462306a36Sopenharmony_ci m88ds3103_pdata.clk = 27000000; 123562306a36Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33; 123662306a36Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; 123762306a36Sopenharmony_ci m88ds3103_pdata.ts_clk = 16000; 123862306a36Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 0; 123962306a36Sopenharmony_ci m88ds3103_pdata.agc = 0x99; 124062306a36Sopenharmony_ci m88ds3103_pdata.agc_inv = 0; 124162306a36Sopenharmony_ci m88ds3103_pdata.spec_inv = 0; 124262306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b", 124362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 124462306a36Sopenharmony_ci 0x6a, &m88ds3103_pdata); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 124762306a36Sopenharmony_ci return -ENODEV; 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); 125062306a36Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci /* attach tuner */ 125362306a36Sopenharmony_ci ts2020_config.fe = dvb->fe[0]; 125462306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", 125562306a36Sopenharmony_ci i2c_adapter, 125662306a36Sopenharmony_ci 0x60, &ts2020_config); 125762306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 125862306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 125962306a36Sopenharmony_ci return -ENODEV; 126062306a36Sopenharmony_ci } 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci /* delegate signal strength measurement to tuner */ 126362306a36Sopenharmony_ci dvb->fe[0]->ops.read_signal_strength = 126462306a36Sopenharmony_ci dvb->fe[0]->ops.tuner_ops.get_rf_strength; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci /* attach SEC */ 126762306a36Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 126862306a36Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 126962306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 127062306a36Sopenharmony_ci 0x08, &a8293_pdata); 127162306a36Sopenharmony_ci if (!dvb->i2c_client_sec) { 127262306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 127362306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 127462306a36Sopenharmony_ci return -ENODEV; 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci return 0; 127862306a36Sopenharmony_ci} 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_cistatic int em28178_dvb_init_pctv_292e(struct em28xx *dev) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 128362306a36Sopenharmony_ci struct i2c_adapter *adapter; 128462306a36Sopenharmony_ci struct si2168_config si2168_config = {}; 128562306a36Sopenharmony_ci struct si2157_config si2157_config = {}; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci /* attach demod */ 128862306a36Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 128962306a36Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 129062306a36Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 129162306a36Sopenharmony_ci si2168_config.spectral_inversion = true; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 129462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 129562306a36Sopenharmony_ci 0x64, &si2168_config); 129662306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 129762306a36Sopenharmony_ci return -ENODEV; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci /* attach tuner */ 130062306a36Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 130162306a36Sopenharmony_ci si2157_config.if_port = 1; 130262306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 130362306a36Sopenharmony_ci si2157_config.mdev = dev->media_dev; 130462306a36Sopenharmony_ci#endif 130562306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 130662306a36Sopenharmony_ci adapter, 130762306a36Sopenharmony_ci 0x60, &si2157_config); 130862306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 130962306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 131062306a36Sopenharmony_ci return -ENODEV; 131162306a36Sopenharmony_ci } 131262306a36Sopenharmony_ci dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci return 0; 131562306a36Sopenharmony_ci} 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_cistatic int em28178_dvb_init_terratec_t2_stick_hd(struct em28xx *dev) 131862306a36Sopenharmony_ci{ 131962306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 132062306a36Sopenharmony_ci struct i2c_adapter *adapter; 132162306a36Sopenharmony_ci struct si2168_config si2168_config = {}; 132262306a36Sopenharmony_ci struct si2157_config si2157_config = {}; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci /* attach demod */ 132562306a36Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 132662306a36Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 132762306a36Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 133062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 133162306a36Sopenharmony_ci 0x64, &si2168_config); 133262306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 133362306a36Sopenharmony_ci return -ENODEV; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci /* attach tuner */ 133662306a36Sopenharmony_ci memset(&si2157_config, 0, sizeof(si2157_config)); 133762306a36Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 133862306a36Sopenharmony_ci si2157_config.if_port = 0; 133962306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 134062306a36Sopenharmony_ci si2157_config.mdev = dev->media_dev; 134162306a36Sopenharmony_ci#endif 134262306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", "si2146", 134362306a36Sopenharmony_ci adapter, 134462306a36Sopenharmony_ci 0x60, &si2157_config); 134562306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 134662306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 134762306a36Sopenharmony_ci return -ENODEV; 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci return 0; 135162306a36Sopenharmony_ci} 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_cistatic int em28178_dvb_init_plex_px_bcud(struct em28xx *dev) 135462306a36Sopenharmony_ci{ 135562306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 135662306a36Sopenharmony_ci struct tc90522_config tc90522_config = {}; 135762306a36Sopenharmony_ci struct qm1d1c0042_config qm1d1c0042_config = {}; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci /* attach demod */ 136062306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("tc90522", "tc90522sat", 136162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 136262306a36Sopenharmony_ci 0x15, &tc90522_config); 136362306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 136462306a36Sopenharmony_ci return -ENODEV; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* attach tuner */ 136762306a36Sopenharmony_ci qm1d1c0042_config.fe = tc90522_config.fe; 136862306a36Sopenharmony_ci qm1d1c0042_config.lpf = 1; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("qm1d1c0042", NULL, 137162306a36Sopenharmony_ci tc90522_config.tuner_i2c, 137262306a36Sopenharmony_ci 0x61, &qm1d1c0042_config); 137362306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 137462306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 137562306a36Sopenharmony_ci return -ENODEV; 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci dvb->fe[0] = tc90522_config.fe; 137962306a36Sopenharmony_ci px_bcud_init(dev); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci return 0; 138262306a36Sopenharmony_ci} 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_cistatic int em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx *dev) 138562306a36Sopenharmony_ci{ 138662306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 138762306a36Sopenharmony_ci struct i2c_adapter *adapter; 138862306a36Sopenharmony_ci struct si2168_config si2168_config = {}; 138962306a36Sopenharmony_ci struct si2157_config si2157_config = {}; 139062306a36Sopenharmony_ci unsigned char addr; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci /* attach demod */ 139362306a36Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 139462306a36Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 139562306a36Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_SERIAL; 139662306a36Sopenharmony_ci si2168_config.spectral_inversion = true; 139762306a36Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x64 : 0x67; 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 140062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 140162306a36Sopenharmony_ci addr, &si2168_config); 140262306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 140362306a36Sopenharmony_ci return -ENODEV; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci /* attach tuner */ 140662306a36Sopenharmony_ci memset(&si2157_config, 0, sizeof(si2157_config)); 140762306a36Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 140862306a36Sopenharmony_ci si2157_config.if_port = 1; 140962306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 141062306a36Sopenharmony_ci si2157_config.mdev = dev->media_dev; 141162306a36Sopenharmony_ci#endif 141262306a36Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 141562306a36Sopenharmony_ci adapter, 141662306a36Sopenharmony_ci addr, &si2157_config); 141762306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 141862306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 141962306a36Sopenharmony_ci return -ENODEV; 142062306a36Sopenharmony_ci } 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci return 0; 142362306a36Sopenharmony_ci} 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev) 142662306a36Sopenharmony_ci{ 142762306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 142862306a36Sopenharmony_ci struct i2c_adapter *adapter; 142962306a36Sopenharmony_ci struct lgdt3306a_config lgdt3306a_config = {}; 143062306a36Sopenharmony_ci struct si2157_config si2157_config = {}; 143162306a36Sopenharmony_ci unsigned char addr; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci /* attach demod */ 143462306a36Sopenharmony_ci lgdt3306a_config = hauppauge_01595_lgdt3306a_config; 143562306a36Sopenharmony_ci lgdt3306a_config.fe = &dvb->fe[0]; 143662306a36Sopenharmony_ci lgdt3306a_config.i2c_adapter = &adapter; 143762306a36Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x59 : 0x0e; 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("lgdt3306a", NULL, 144062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 144162306a36Sopenharmony_ci addr, &lgdt3306a_config); 144262306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 144362306a36Sopenharmony_ci return -ENODEV; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci /* attach tuner */ 144662306a36Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 144762306a36Sopenharmony_ci si2157_config.if_port = 1; 144862306a36Sopenharmony_ci si2157_config.inversion = 1; 144962306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 145062306a36Sopenharmony_ci si2157_config.mdev = dev->media_dev; 145162306a36Sopenharmony_ci#endif 145262306a36Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x62; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 145562306a36Sopenharmony_ci adapter, 145662306a36Sopenharmony_ci addr, &si2157_config); 145762306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 145862306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 145962306a36Sopenharmony_ci return -ENODEV; 146062306a36Sopenharmony_ci } 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci return 0; 146362306a36Sopenharmony_ci} 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_cistatic int em2874_dvb_init_hauppauge_usb_quadhd(struct em28xx *dev) 146662306a36Sopenharmony_ci{ 146762306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 146862306a36Sopenharmony_ci struct mxl692_config mxl692_config = {}; 146962306a36Sopenharmony_ci unsigned char addr; 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci /* attach demod/tuner combo */ 147262306a36Sopenharmony_ci mxl692_config.id = (dev->ts == PRIMARY_TS) ? 0 : 1; 147362306a36Sopenharmony_ci mxl692_config.fe = &dvb->fe[0]; 147462306a36Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("mxl692", NULL, 147762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 147862306a36Sopenharmony_ci addr, &mxl692_config); 147962306a36Sopenharmony_ci if (!dvb->i2c_client_demod) 148062306a36Sopenharmony_ci return -ENODEV; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci return 0; 148362306a36Sopenharmony_ci} 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_cistatic int em28xx_dvb_init(struct em28xx *dev) 148662306a36Sopenharmony_ci{ 148762306a36Sopenharmony_ci int result = 0, dvb_alt = 0; 148862306a36Sopenharmony_ci struct em28xx_dvb *dvb; 148962306a36Sopenharmony_ci struct usb_device *udev; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci if (dev->is_audio_only) { 149262306a36Sopenharmony_ci /* Shouldn't initialize IR for this interface */ 149362306a36Sopenharmony_ci return 0; 149462306a36Sopenharmony_ci } 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci if (!dev->board.has_dvb) { 149762306a36Sopenharmony_ci /* This device does not support the extension */ 149862306a36Sopenharmony_ci return 0; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci dev_info(&dev->intf->dev, "Binding DVB extension\n"); 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci dvb = kzalloc(sizeof(*dvb), GFP_KERNEL); 150462306a36Sopenharmony_ci if (!dvb) 150562306a36Sopenharmony_ci return -ENOMEM; 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci dev->dvb = dvb; 150862306a36Sopenharmony_ci dvb->fe[0] = NULL; 150962306a36Sopenharmony_ci dvb->fe[1] = NULL; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci /* pre-allocate DVB usb transfer buffers */ 151262306a36Sopenharmony_ci if (dev->dvb_xfer_bulk) { 151362306a36Sopenharmony_ci result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, 151462306a36Sopenharmony_ci dev->dvb_xfer_bulk, 151562306a36Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 151662306a36Sopenharmony_ci 512, 151762306a36Sopenharmony_ci EM28XX_DVB_BULK_PACKET_MULTIPLIER); 151862306a36Sopenharmony_ci } else { 151962306a36Sopenharmony_ci result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, 152062306a36Sopenharmony_ci dev->dvb_xfer_bulk, 152162306a36Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 152262306a36Sopenharmony_ci dev->dvb_max_pkt_size_isoc, 152362306a36Sopenharmony_ci EM28XX_DVB_NUM_ISOC_PACKETS); 152462306a36Sopenharmony_ci } 152562306a36Sopenharmony_ci if (result) { 152662306a36Sopenharmony_ci dev_err(&dev->intf->dev, 152762306a36Sopenharmony_ci "failed to pre-allocate USB transfer buffers for DVB.\n"); 152862306a36Sopenharmony_ci kfree(dvb); 152962306a36Sopenharmony_ci dev->dvb = NULL; 153062306a36Sopenharmony_ci return result; 153162306a36Sopenharmony_ci } 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci mutex_lock(&dev->lock); 153462306a36Sopenharmony_ci em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 153562306a36Sopenharmony_ci /* init frontend */ 153662306a36Sopenharmony_ci switch (dev->model) { 153762306a36Sopenharmony_ci case EM2874_BOARD_LEADERSHIP_ISDBT: 153862306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(s921_attach, 153962306a36Sopenharmony_ci &sharp_isdbt, 154062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci if (!dvb->fe[0]) { 154362306a36Sopenharmony_ci result = -EINVAL; 154462306a36Sopenharmony_ci goto out_free; 154562306a36Sopenharmony_ci } 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci break; 154862306a36Sopenharmony_ci case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 154962306a36Sopenharmony_ci case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 155062306a36Sopenharmony_ci case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 155162306a36Sopenharmony_ci case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 155262306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt330x_attach, 155362306a36Sopenharmony_ci &em2880_lgdt3303_dev, 155462306a36Sopenharmony_ci 0x0e, 155562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 155662306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 155762306a36Sopenharmony_ci result = -EINVAL; 155862306a36Sopenharmony_ci goto out_free; 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci break; 156162306a36Sopenharmony_ci case EM2880_BOARD_KWORLD_DVB_310U: 156262306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 156362306a36Sopenharmony_ci &em28xx_zl10353_with_xc3028, 156462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 156562306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 156662306a36Sopenharmony_ci result = -EINVAL; 156762306a36Sopenharmony_ci goto out_free; 156862306a36Sopenharmony_ci } 156962306a36Sopenharmony_ci break; 157062306a36Sopenharmony_ci case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 157162306a36Sopenharmony_ci case EM2882_BOARD_TERRATEC_HYBRID_XS: 157262306a36Sopenharmony_ci case EM2880_BOARD_EMPIRE_DUAL_TV: 157362306a36Sopenharmony_ci case EM2882_BOARD_ZOLID_HYBRID_TV_STICK: 157462306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 157562306a36Sopenharmony_ci &em28xx_zl10353_xc3028_no_i2c_gate, 157662306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 157762306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 157862306a36Sopenharmony_ci result = -EINVAL; 157962306a36Sopenharmony_ci goto out_free; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci break; 158262306a36Sopenharmony_ci case EM2880_BOARD_TERRATEC_HYBRID_XS: 158362306a36Sopenharmony_ci case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: 158462306a36Sopenharmony_ci case EM2881_BOARD_PINNACLE_HYBRID_PRO: 158562306a36Sopenharmony_ci case EM2882_BOARD_DIKOM_DK300: 158662306a36Sopenharmony_ci case EM2882_BOARD_KWORLD_VS_DVBT: 158762306a36Sopenharmony_ci /* 158862306a36Sopenharmony_ci * Those boards could have either a zl10353 or a mt352. 158962306a36Sopenharmony_ci * If the chip id isn't for zl10353, try mt352. 159062306a36Sopenharmony_ci */ 159162306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 159262306a36Sopenharmony_ci &em28xx_zl10353_xc3028_no_i2c_gate, 159362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 159462306a36Sopenharmony_ci if (!dvb->fe[0]) 159562306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(mt352_attach, 159662306a36Sopenharmony_ci &terratec_xs_mt352_cfg, 159762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 160062306a36Sopenharmony_ci result = -EINVAL; 160162306a36Sopenharmony_ci goto out_free; 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci break; 160462306a36Sopenharmony_ci case EM2870_BOARD_TERRATEC_XS_MT2060: 160562306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 160662306a36Sopenharmony_ci &em28xx_zl10353_no_i2c_gate_dev, 160762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 160862306a36Sopenharmony_ci if (dvb->fe[0]) { 160962306a36Sopenharmony_ci dvb_attach(mt2060_attach, dvb->fe[0], 161062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 161162306a36Sopenharmony_ci &em28xx_mt2060_config, 1220); 161262306a36Sopenharmony_ci } 161362306a36Sopenharmony_ci break; 161462306a36Sopenharmony_ci case EM2870_BOARD_KWORLD_355U: 161562306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 161662306a36Sopenharmony_ci &em28xx_zl10353_no_i2c_gate_dev, 161762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 161862306a36Sopenharmony_ci if (dvb->fe[0]) 161962306a36Sopenharmony_ci dvb_attach(qt1010_attach, dvb->fe[0], 162062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 162162306a36Sopenharmony_ci &em28xx_qt1010_config); 162262306a36Sopenharmony_ci break; 162362306a36Sopenharmony_ci case EM2883_BOARD_KWORLD_HYBRID_330U: 162462306a36Sopenharmony_ci case EM2882_BOARD_EVGA_INDTUBE: 162562306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(s5h1409_attach, 162662306a36Sopenharmony_ci &em28xx_s5h1409_with_xc3028, 162762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 162862306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 162962306a36Sopenharmony_ci result = -EINVAL; 163062306a36Sopenharmony_ci goto out_free; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci break; 163362306a36Sopenharmony_ci case EM2882_BOARD_KWORLD_ATSC_315U: 163462306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt330x_attach, 163562306a36Sopenharmony_ci &em2880_lgdt3303_dev, 163662306a36Sopenharmony_ci 0x0e, 163762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 163862306a36Sopenharmony_ci if (dvb->fe[0]) { 163962306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, dvb->fe[0], 164062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 164162306a36Sopenharmony_ci 0x61, TUNER_THOMSON_DTT761X)) { 164262306a36Sopenharmony_ci result = -EINVAL; 164362306a36Sopenharmony_ci goto out_free; 164462306a36Sopenharmony_ci } 164562306a36Sopenharmony_ci } 164662306a36Sopenharmony_ci break; 164762306a36Sopenharmony_ci case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 164862306a36Sopenharmony_ci case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: 164962306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, 165062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 165162306a36Sopenharmony_ci &dev->intf->dev); 165262306a36Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 165362306a36Sopenharmony_ci result = -EINVAL; 165462306a36Sopenharmony_ci goto out_free; 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci break; 165762306a36Sopenharmony_ci case EM2870_BOARD_REDDO_DVB_C_USB_BOX: 165862306a36Sopenharmony_ci /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ 165962306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(tda10023_attach, 166062306a36Sopenharmony_ci &em28xx_tda10023_config, 166162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 166262306a36Sopenharmony_ci 0x48); 166362306a36Sopenharmony_ci if (dvb->fe[0]) { 166462306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, dvb->fe[0], 166562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 166662306a36Sopenharmony_ci 0x60, TUNER_PHILIPS_CU1216L)) { 166762306a36Sopenharmony_ci result = -EINVAL; 166862306a36Sopenharmony_ci goto out_free; 166962306a36Sopenharmony_ci } 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci break; 167262306a36Sopenharmony_ci case EM2870_BOARD_KWORLD_A340: 167362306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 167462306a36Sopenharmony_ci &em2870_lgdt3304_dev, 167562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 167662306a36Sopenharmony_ci if (!dvb->fe[0]) { 167762306a36Sopenharmony_ci result = -EINVAL; 167862306a36Sopenharmony_ci goto out_free; 167962306a36Sopenharmony_ci } 168062306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 168162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 168262306a36Sopenharmony_ci &kworld_a340_config)) { 168362306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 168462306a36Sopenharmony_ci result = -EINVAL; 168562306a36Sopenharmony_ci goto out_free; 168662306a36Sopenharmony_ci } 168762306a36Sopenharmony_ci break; 168862306a36Sopenharmony_ci case EM28174_BOARD_PCTV_290E: 168962306a36Sopenharmony_ci /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ 169062306a36Sopenharmony_ci dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O | 169162306a36Sopenharmony_ci CXD2820R_GPIO_L; 169262306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(cxd2820r_attach, 169362306a36Sopenharmony_ci &em28xx_cxd2820r_config, 169462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 169562306a36Sopenharmony_ci &dvb->lna_gpio); 169662306a36Sopenharmony_ci if (dvb->fe[0]) { 169762306a36Sopenharmony_ci /* FE 0 attach tuner */ 169862306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, 169962306a36Sopenharmony_ci dvb->fe[0], 170062306a36Sopenharmony_ci 0x60, 170162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 170262306a36Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 170362306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 170462306a36Sopenharmony_ci result = -EINVAL; 170562306a36Sopenharmony_ci goto out_free; 170662306a36Sopenharmony_ci } 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci#ifdef CONFIG_GPIOLIB 170962306a36Sopenharmony_ci /* enable LNA for DVB-T, DVB-T2 and DVB-C */ 171062306a36Sopenharmony_ci result = gpio_request_one(dvb->lna_gpio, 171162306a36Sopenharmony_ci GPIOF_OUT_INIT_LOW, NULL); 171262306a36Sopenharmony_ci if (result) 171362306a36Sopenharmony_ci dev_err(&dev->intf->dev, 171462306a36Sopenharmony_ci "gpio request failed %d\n", 171562306a36Sopenharmony_ci result); 171662306a36Sopenharmony_ci else 171762306a36Sopenharmony_ci gpio_free(dvb->lna_gpio); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci result = 0; /* continue even set LNA fails */ 172062306a36Sopenharmony_ci#endif 172162306a36Sopenharmony_ci dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna; 172262306a36Sopenharmony_ci } 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci break; 172562306a36Sopenharmony_ci case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: 172662306a36Sopenharmony_ci { 172762306a36Sopenharmony_ci struct xc5000_config cfg = {}; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci hauppauge_hvr930c_init(dev); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, 173262306a36Sopenharmony_ci &hauppauge_930c_drxk, 173362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 173462306a36Sopenharmony_ci if (!dvb->fe[0]) { 173562306a36Sopenharmony_ci result = -EINVAL; 173662306a36Sopenharmony_ci goto out_free; 173762306a36Sopenharmony_ci } 173862306a36Sopenharmony_ci /* FIXME: do we need a pll semaphore? */ 173962306a36Sopenharmony_ci dvb->fe[0]->sec_priv = dvb; 174062306a36Sopenharmony_ci sema_init(&dvb->pll_mutex, 1); 174162306a36Sopenharmony_ci dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; 174262306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci /* Attach xc5000 */ 174562306a36Sopenharmony_ci cfg.i2c_address = 0x61; 174662306a36Sopenharmony_ci cfg.if_khz = 4000; 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 174962306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); 175062306a36Sopenharmony_ci if (!dvb_attach(xc5000_attach, dvb->fe[0], 175162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], &cfg)) { 175262306a36Sopenharmony_ci result = -EINVAL; 175362306a36Sopenharmony_ci goto out_free; 175462306a36Sopenharmony_ci } 175562306a36Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 175662306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci break; 175962306a36Sopenharmony_ci } 176062306a36Sopenharmony_ci case EM2884_BOARD_TERRATEC_H5: 176162306a36Sopenharmony_ci terratec_h5_init(dev); 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, 176462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 176562306a36Sopenharmony_ci if (!dvb->fe[0]) { 176662306a36Sopenharmony_ci result = -EINVAL; 176762306a36Sopenharmony_ci goto out_free; 176862306a36Sopenharmony_ci } 176962306a36Sopenharmony_ci /* FIXME: do we need a pll semaphore? */ 177062306a36Sopenharmony_ci dvb->fe[0]->sec_priv = dvb; 177162306a36Sopenharmony_ci sema_init(&dvb->pll_mutex, 1); 177262306a36Sopenharmony_ci dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; 177362306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci /* Attach tda18271 to DVB-C frontend */ 177662306a36Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 177762306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); 177862306a36Sopenharmony_ci if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], 177962306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 0x60)) { 178062306a36Sopenharmony_ci result = -EINVAL; 178162306a36Sopenharmony_ci goto out_free; 178262306a36Sopenharmony_ci } 178362306a36Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 178462306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci break; 178762306a36Sopenharmony_ci case EM2884_BOARD_C3TECH_DIGITAL_DUO: 178862306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(mb86a20s_attach, 178962306a36Sopenharmony_ci &c3tech_duo_mb86a20s_config, 179062306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 179162306a36Sopenharmony_ci if (dvb->fe[0]) 179262306a36Sopenharmony_ci dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 179362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 179462306a36Sopenharmony_ci &c3tech_duo_tda18271_config); 179562306a36Sopenharmony_ci break; 179662306a36Sopenharmony_ci case EM28174_BOARD_PCTV_460E: 179762306a36Sopenharmony_ci result = em28174_dvb_init_pctv_460e(dev); 179862306a36Sopenharmony_ci if (result) 179962306a36Sopenharmony_ci goto out_free; 180062306a36Sopenharmony_ci break; 180162306a36Sopenharmony_ci case EM2874_BOARD_DELOCK_61959: 180262306a36Sopenharmony_ci case EM2874_BOARD_MAXMEDIA_UB425_TC: 180362306a36Sopenharmony_ci /* attach demodulator */ 180462306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, 180562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (dvb->fe[0]) { 180862306a36Sopenharmony_ci /* disable I2C-gate */ 180962306a36Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = NULL; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci /* attach tuner */ 181262306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 181362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 181462306a36Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 181562306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 181662306a36Sopenharmony_ci result = -EINVAL; 181762306a36Sopenharmony_ci goto out_free; 181862306a36Sopenharmony_ci } 181962306a36Sopenharmony_ci } 182062306a36Sopenharmony_ci break; 182162306a36Sopenharmony_ci case EM2884_BOARD_PCTV_510E: 182262306a36Sopenharmony_ci case EM2884_BOARD_PCTV_520E: 182362306a36Sopenharmony_ci pctv_520e_init(dev); 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci /* attach demodulator */ 182662306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, 182762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci if (dvb->fe[0]) { 183062306a36Sopenharmony_ci /* attach tuner */ 183162306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 183262306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 183362306a36Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 183462306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 183562306a36Sopenharmony_ci result = -EINVAL; 183662306a36Sopenharmony_ci goto out_free; 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci break; 184062306a36Sopenharmony_ci case EM2884_BOARD_ELGATO_EYETV_HYBRID_2008: 184162306a36Sopenharmony_ci case EM2884_BOARD_CINERGY_HTC_STICK: 184262306a36Sopenharmony_ci case EM2884_BOARD_TERRATEC_H6: 184362306a36Sopenharmony_ci terratec_htc_stick_init(dev); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci /* attach demodulator */ 184662306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, 184762306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 184862306a36Sopenharmony_ci if (!dvb->fe[0]) { 184962306a36Sopenharmony_ci result = -EINVAL; 185062306a36Sopenharmony_ci goto out_free; 185162306a36Sopenharmony_ci } 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci /* Attach the demodulator. */ 185462306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 185562306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 185662306a36Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 185762306a36Sopenharmony_ci result = -EINVAL; 185862306a36Sopenharmony_ci goto out_free; 185962306a36Sopenharmony_ci } 186062306a36Sopenharmony_ci break; 186162306a36Sopenharmony_ci case EM2884_BOARD_TERRATEC_HTC_USB_XS: 186262306a36Sopenharmony_ci terratec_htc_usb_xs_init(dev); 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci /* attach demodulator */ 186562306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, 186662306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 186762306a36Sopenharmony_ci if (!dvb->fe[0]) { 186862306a36Sopenharmony_ci result = -EINVAL; 186962306a36Sopenharmony_ci goto out_free; 187062306a36Sopenharmony_ci } 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci /* Attach the demodulator. */ 187362306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 187462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 187562306a36Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 187662306a36Sopenharmony_ci result = -EINVAL; 187762306a36Sopenharmony_ci goto out_free; 187862306a36Sopenharmony_ci } 187962306a36Sopenharmony_ci break; 188062306a36Sopenharmony_ci case EM2874_BOARD_KWORLD_UB435Q_V2: 188162306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 188262306a36Sopenharmony_ci &em2874_lgdt3305_dev, 188362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 188462306a36Sopenharmony_ci if (!dvb->fe[0]) { 188562306a36Sopenharmony_ci result = -EINVAL; 188662306a36Sopenharmony_ci goto out_free; 188762306a36Sopenharmony_ci } 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci /* Attach the demodulator. */ 189062306a36Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 189162306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 189262306a36Sopenharmony_ci &kworld_ub435q_v2_config)) { 189362306a36Sopenharmony_ci result = -EINVAL; 189462306a36Sopenharmony_ci goto out_free; 189562306a36Sopenharmony_ci } 189662306a36Sopenharmony_ci break; 189762306a36Sopenharmony_ci case EM2874_BOARD_KWORLD_UB435Q_V3: 189862306a36Sopenharmony_ci { 189962306a36Sopenharmony_ci struct i2c_adapter *adapter = &dev->i2c_adap[dev->def_i2c_bus]; 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 190262306a36Sopenharmony_ci &em2874_lgdt3305_nogate_dev, 190362306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 190462306a36Sopenharmony_ci if (!dvb->fe[0]) { 190562306a36Sopenharmony_ci result = -EINVAL; 190662306a36Sopenharmony_ci goto out_free; 190762306a36Sopenharmony_ci } 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci /* attach tuner */ 191062306a36Sopenharmony_ci kworld_ub435q_v3_config.fe = dvb->fe[0]; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("tda18212", NULL, 191362306a36Sopenharmony_ci adapter, 0x60, 191462306a36Sopenharmony_ci &kworld_ub435q_v3_config); 191562306a36Sopenharmony_ci if (!dvb->i2c_client_tuner) { 191662306a36Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 191762306a36Sopenharmony_ci result = -ENODEV; 191862306a36Sopenharmony_ci goto out_free; 191962306a36Sopenharmony_ci } 192062306a36Sopenharmony_ci break; 192162306a36Sopenharmony_ci } 192262306a36Sopenharmony_ci case EM2874_BOARD_PCTV_HD_MINI_80E: 192362306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(drx39xxj_attach, 192462306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 192562306a36Sopenharmony_ci if (dvb->fe[0]) { 192662306a36Sopenharmony_ci dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0], 192762306a36Sopenharmony_ci 0x60, 192862306a36Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 192962306a36Sopenharmony_ci &pinnacle_80e_dvb_config); 193062306a36Sopenharmony_ci if (!dvb->fe[0]) { 193162306a36Sopenharmony_ci result = -EINVAL; 193262306a36Sopenharmony_ci goto out_free; 193362306a36Sopenharmony_ci } 193462306a36Sopenharmony_ci } 193562306a36Sopenharmony_ci break; 193662306a36Sopenharmony_ci case EM28178_BOARD_PCTV_461E: 193762306a36Sopenharmony_ci result = em28178_dvb_init_pctv_461e(dev); 193862306a36Sopenharmony_ci if (result) 193962306a36Sopenharmony_ci goto out_free; 194062306a36Sopenharmony_ci break; 194162306a36Sopenharmony_ci case EM28178_BOARD_PCTV_461E_V2: 194262306a36Sopenharmony_ci result = em28178_dvb_init_pctv_461e_v2(dev); 194362306a36Sopenharmony_ci if (result) 194462306a36Sopenharmony_ci goto out_free; 194562306a36Sopenharmony_ci break; 194662306a36Sopenharmony_ci case EM28178_BOARD_PCTV_292E: 194762306a36Sopenharmony_ci result = em28178_dvb_init_pctv_292e(dev); 194862306a36Sopenharmony_ci if (result) 194962306a36Sopenharmony_ci goto out_free; 195062306a36Sopenharmony_ci break; 195162306a36Sopenharmony_ci case EM28178_BOARD_TERRATEC_T2_STICK_HD: 195262306a36Sopenharmony_ci result = em28178_dvb_init_terratec_t2_stick_hd(dev); 195362306a36Sopenharmony_ci if (result) 195462306a36Sopenharmony_ci goto out_free; 195562306a36Sopenharmony_ci break; 195662306a36Sopenharmony_ci case EM28178_BOARD_PLEX_PX_BCUD: 195762306a36Sopenharmony_ci result = em28178_dvb_init_plex_px_bcud(dev); 195862306a36Sopenharmony_ci if (result) 195962306a36Sopenharmony_ci goto out_free; 196062306a36Sopenharmony_ci break; 196162306a36Sopenharmony_ci case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: 196262306a36Sopenharmony_ci result = em28174_dvb_init_hauppauge_wintv_dualhd_dvb(dev); 196362306a36Sopenharmony_ci if (result) 196462306a36Sopenharmony_ci goto out_free; 196562306a36Sopenharmony_ci break; 196662306a36Sopenharmony_ci case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595: 196762306a36Sopenharmony_ci result = em28174_dvb_init_hauppauge_wintv_dualhd_01595(dev); 196862306a36Sopenharmony_ci if (result) 196962306a36Sopenharmony_ci goto out_free; 197062306a36Sopenharmony_ci break; 197162306a36Sopenharmony_ci case EM2874_BOARD_HAUPPAUGE_USB_QUADHD: 197262306a36Sopenharmony_ci result = em2874_dvb_init_hauppauge_usb_quadhd(dev); 197362306a36Sopenharmony_ci if (result) 197462306a36Sopenharmony_ci goto out_free; 197562306a36Sopenharmony_ci break; 197662306a36Sopenharmony_ci default: 197762306a36Sopenharmony_ci dev_err(&dev->intf->dev, 197862306a36Sopenharmony_ci "The frontend of your DVB/ATSC card isn't supported yet\n"); 197962306a36Sopenharmony_ci break; 198062306a36Sopenharmony_ci } 198162306a36Sopenharmony_ci if (!dvb->fe[0]) { 198262306a36Sopenharmony_ci dev_err(&dev->intf->dev, "frontend initialization failed\n"); 198362306a36Sopenharmony_ci result = -EINVAL; 198462306a36Sopenharmony_ci goto out_free; 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci /* define general-purpose callback pointer */ 198762306a36Sopenharmony_ci dvb->fe[0]->callback = em28xx_tuner_callback; 198862306a36Sopenharmony_ci if (dvb->fe[1]) 198962306a36Sopenharmony_ci dvb->fe[1]->callback = em28xx_tuner_callback; 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci /* register everything */ 199262306a36Sopenharmony_ci result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->intf->dev); 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci if (result < 0) 199562306a36Sopenharmony_ci goto out_free; 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci if (dev->dvb_xfer_bulk) { 199862306a36Sopenharmony_ci dvb_alt = 0; 199962306a36Sopenharmony_ci } else { /* isoc */ 200062306a36Sopenharmony_ci dvb_alt = dev->dvb_alt_isoc; 200162306a36Sopenharmony_ci } 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci udev = interface_to_usbdev(dev->intf); 200462306a36Sopenharmony_ci usb_set_interface(udev, dev->ifnum, dvb_alt); 200562306a36Sopenharmony_ci dev_info(&dev->intf->dev, "DVB extension successfully initialized\n"); 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci kref_get(&dev->ref); 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ciret: 201062306a36Sopenharmony_ci em28xx_set_mode(dev, EM28XX_SUSPEND); 201162306a36Sopenharmony_ci mutex_unlock(&dev->lock); 201262306a36Sopenharmony_ci return result; 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ciout_free: 201562306a36Sopenharmony_ci em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); 201662306a36Sopenharmony_ci kfree(dvb); 201762306a36Sopenharmony_ci dev->dvb = NULL; 201862306a36Sopenharmony_ci goto ret; 201962306a36Sopenharmony_ci} 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_cistatic inline void prevent_sleep(struct dvb_frontend_ops *ops) 202262306a36Sopenharmony_ci{ 202362306a36Sopenharmony_ci ops->set_voltage = NULL; 202462306a36Sopenharmony_ci ops->sleep = NULL; 202562306a36Sopenharmony_ci ops->tuner_ops.sleep = NULL; 202662306a36Sopenharmony_ci} 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_cistatic int em28xx_dvb_fini(struct em28xx *dev) 202962306a36Sopenharmony_ci{ 203062306a36Sopenharmony_ci struct em28xx_dvb *dvb; 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci if (dev->is_audio_only) { 203362306a36Sopenharmony_ci /* Shouldn't initialize IR for this interface */ 203462306a36Sopenharmony_ci return 0; 203562306a36Sopenharmony_ci } 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci if (!dev->board.has_dvb) { 203862306a36Sopenharmony_ci /* This device does not support the extension */ 203962306a36Sopenharmony_ci return 0; 204062306a36Sopenharmony_ci } 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci if (!dev->dvb) 204362306a36Sopenharmony_ci return 0; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci dev_info(&dev->intf->dev, "Closing DVB extension\n"); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci dvb = dev->dvb; 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci if (dev->disconnected) { 205262306a36Sopenharmony_ci /* 205362306a36Sopenharmony_ci * We cannot tell the device to sleep 205462306a36Sopenharmony_ci * once it has been unplugged. 205562306a36Sopenharmony_ci */ 205662306a36Sopenharmony_ci if (dvb->fe[0]) { 205762306a36Sopenharmony_ci prevent_sleep(&dvb->fe[0]->ops); 205862306a36Sopenharmony_ci dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED; 205962306a36Sopenharmony_ci } 206062306a36Sopenharmony_ci if (dvb->fe[1]) { 206162306a36Sopenharmony_ci prevent_sleep(&dvb->fe[1]->ops); 206262306a36Sopenharmony_ci dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci em28xx_unregister_dvb(dvb); 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci /* release I2C module bindings */ 206962306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_sec); 207062306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 207162306a36Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci kfree(dvb); 207462306a36Sopenharmony_ci dev->dvb = NULL; 207562306a36Sopenharmony_ci kref_put(&dev->ref, em28xx_free_device); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci return 0; 207862306a36Sopenharmony_ci} 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_cistatic int em28xx_dvb_suspend(struct em28xx *dev) 208162306a36Sopenharmony_ci{ 208262306a36Sopenharmony_ci int ret = 0; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci if (dev->is_audio_only) 208562306a36Sopenharmony_ci return 0; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci if (!dev->board.has_dvb) 208862306a36Sopenharmony_ci return 0; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci dev_info(&dev->intf->dev, "Suspending DVB extension\n"); 209162306a36Sopenharmony_ci if (dev->dvb) { 209262306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci if (dvb->fe[0]) { 209562306a36Sopenharmony_ci ret = dvb_frontend_suspend(dvb->fe[0]); 209662306a36Sopenharmony_ci dev_info(&dev->intf->dev, "fe0 suspend %d\n", ret); 209762306a36Sopenharmony_ci } 209862306a36Sopenharmony_ci if (dvb->fe[1]) { 209962306a36Sopenharmony_ci dvb_frontend_suspend(dvb->fe[1]); 210062306a36Sopenharmony_ci dev_info(&dev->intf->dev, "fe1 suspend %d\n", ret); 210162306a36Sopenharmony_ci } 210262306a36Sopenharmony_ci } 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci return 0; 210562306a36Sopenharmony_ci} 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_cistatic int em28xx_dvb_resume(struct em28xx *dev) 210862306a36Sopenharmony_ci{ 210962306a36Sopenharmony_ci int ret = 0; 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci if (dev->is_audio_only) 211262306a36Sopenharmony_ci return 0; 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci if (!dev->board.has_dvb) 211562306a36Sopenharmony_ci return 0; 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci dev_info(&dev->intf->dev, "Resuming DVB extension\n"); 211862306a36Sopenharmony_ci if (dev->dvb) { 211962306a36Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci if (dvb->fe[0]) { 212262306a36Sopenharmony_ci ret = dvb_frontend_resume(dvb->fe[0]); 212362306a36Sopenharmony_ci dev_info(&dev->intf->dev, "fe0 resume %d\n", ret); 212462306a36Sopenharmony_ci } 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci if (dvb->fe[1]) { 212762306a36Sopenharmony_ci ret = dvb_frontend_resume(dvb->fe[1]); 212862306a36Sopenharmony_ci dev_info(&dev->intf->dev, "fe1 resume %d\n", ret); 212962306a36Sopenharmony_ci } 213062306a36Sopenharmony_ci } 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci return 0; 213362306a36Sopenharmony_ci} 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_cistatic struct em28xx_ops dvb_ops = { 213662306a36Sopenharmony_ci .id = EM28XX_DVB, 213762306a36Sopenharmony_ci .name = "Em28xx dvb Extension", 213862306a36Sopenharmony_ci .init = em28xx_dvb_init, 213962306a36Sopenharmony_ci .fini = em28xx_dvb_fini, 214062306a36Sopenharmony_ci .suspend = em28xx_dvb_suspend, 214162306a36Sopenharmony_ci .resume = em28xx_dvb_resume, 214262306a36Sopenharmony_ci}; 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_cistatic int __init em28xx_dvb_register(void) 214562306a36Sopenharmony_ci{ 214662306a36Sopenharmony_ci return em28xx_register_extension(&dvb_ops); 214762306a36Sopenharmony_ci} 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_cistatic void __exit em28xx_dvb_unregister(void) 215062306a36Sopenharmony_ci{ 215162306a36Sopenharmony_ci em28xx_unregister_extension(&dvb_ops); 215262306a36Sopenharmony_ci} 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_cimodule_init(em28xx_dvb_register); 215562306a36Sopenharmony_cimodule_exit(em28xx_dvb_unregister); 2156