18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// DVB device driver for em28xx 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// (c) 2008-2011 Mauro Carvalho Chehab <mchehab@kernel.org> 68c2ecf20Sopenharmony_ci// 78c2ecf20Sopenharmony_ci// (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> 88c2ecf20Sopenharmony_ci// - Fixes for the driver to properly work with HVR-950 98c2ecf20Sopenharmony_ci// - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick 108c2ecf20Sopenharmony_ci// - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 118c2ecf20Sopenharmony_ci// 128c2ecf20Sopenharmony_ci// (c) 2008 Aidan Thornton <makosoft@googlemail.com> 138c2ecf20Sopenharmony_ci// 148c2ecf20Sopenharmony_ci// (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com> 158c2ecf20Sopenharmony_ci// 168c2ecf20Sopenharmony_ci// Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: 178c2ecf20Sopenharmony_ci// (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> 188c2ecf20Sopenharmony_ci// (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 198c2ecf20Sopenharmony_ci// 208c2ecf20Sopenharmony_ci// This program is free software; you can redistribute it and/or modify 218c2ecf20Sopenharmony_ci// it under the terms of the GNU General Public License as published by 228c2ecf20Sopenharmony_ci// the Free Software Foundation version 2 of the License. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "em28xx.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/kernel.h> 278c2ecf20Sopenharmony_ci#include <linux/slab.h> 288c2ecf20Sopenharmony_ci#include <linux/usb.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <media/v4l2-common.h> 318c2ecf20Sopenharmony_ci#include <media/dvb_demux.h> 328c2ecf20Sopenharmony_ci#include <media/dvb_net.h> 338c2ecf20Sopenharmony_ci#include <media/dmxdev.h> 348c2ecf20Sopenharmony_ci#include <media/tuner.h> 358c2ecf20Sopenharmony_ci#include "tuner-simple.h" 368c2ecf20Sopenharmony_ci#include <linux/gpio.h> 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include "lgdt330x.h" 398c2ecf20Sopenharmony_ci#include "lgdt3305.h" 408c2ecf20Sopenharmony_ci#include "lgdt3306a.h" 418c2ecf20Sopenharmony_ci#include "zl10353.h" 428c2ecf20Sopenharmony_ci#include "s5h1409.h" 438c2ecf20Sopenharmony_ci#include "mt2060.h" 448c2ecf20Sopenharmony_ci#include "mt352.h" 458c2ecf20Sopenharmony_ci#include "mt352_priv.h" /* FIXME */ 468c2ecf20Sopenharmony_ci#include "tda1002x.h" 478c2ecf20Sopenharmony_ci#include "drx39xyj/drx39xxj.h" 488c2ecf20Sopenharmony_ci#include "tda18271.h" 498c2ecf20Sopenharmony_ci#include "s921.h" 508c2ecf20Sopenharmony_ci#include "drxd.h" 518c2ecf20Sopenharmony_ci#include "cxd2820r.h" 528c2ecf20Sopenharmony_ci#include "tda18271c2dd.h" 538c2ecf20Sopenharmony_ci#include "drxk.h" 548c2ecf20Sopenharmony_ci#include "tda10071.h" 558c2ecf20Sopenharmony_ci#include "tda18212.h" 568c2ecf20Sopenharmony_ci#include "a8293.h" 578c2ecf20Sopenharmony_ci#include "qt1010.h" 588c2ecf20Sopenharmony_ci#include "mb86a20s.h" 598c2ecf20Sopenharmony_ci#include "m88ds3103.h" 608c2ecf20Sopenharmony_ci#include "ts2020.h" 618c2ecf20Sopenharmony_ci#include "si2168.h" 628c2ecf20Sopenharmony_ci#include "si2157.h" 638c2ecf20Sopenharmony_ci#include "tc90522.h" 648c2ecf20Sopenharmony_ci#include "qm1d1c0042.h" 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>"); 678c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface"); 698c2ecf20Sopenharmony_ciMODULE_VERSION(EM28XX_VERSION); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic unsigned int debug; 728c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 738c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define dprintk(level, fmt, arg...) do { \ 788c2ecf20Sopenharmony_ci if (debug >= level) \ 798c2ecf20Sopenharmony_ci dev_printk(KERN_DEBUG, &dev->intf->dev, \ 808c2ecf20Sopenharmony_ci "dvb: " fmt, ## arg); \ 818c2ecf20Sopenharmony_ci} while (0) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistruct em28xx_dvb { 848c2ecf20Sopenharmony_ci struct dvb_frontend *fe[2]; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* feed count management */ 878c2ecf20Sopenharmony_ci struct mutex lock; 888c2ecf20Sopenharmony_ci int nfeeds; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* general boilerplate stuff */ 918c2ecf20Sopenharmony_ci struct dvb_adapter adapter; 928c2ecf20Sopenharmony_ci struct dvb_demux demux; 938c2ecf20Sopenharmony_ci struct dmxdev dmxdev; 948c2ecf20Sopenharmony_ci struct dmx_frontend fe_hw; 958c2ecf20Sopenharmony_ci struct dmx_frontend fe_mem; 968c2ecf20Sopenharmony_ci struct dvb_net net; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Due to DRX-K - probably need changes */ 998c2ecf20Sopenharmony_ci int (*gate_ctrl)(struct dvb_frontend *fe, int gate); 1008c2ecf20Sopenharmony_ci struct semaphore pll_mutex; 1018c2ecf20Sopenharmony_ci bool dont_attach_fe1; 1028c2ecf20Sopenharmony_ci int lna_gpio; 1038c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_demod; 1048c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_tuner; 1058c2ecf20Sopenharmony_ci struct i2c_client *i2c_client_sec; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic inline void print_err_status(struct em28xx *dev, 1098c2ecf20Sopenharmony_ci int packet, int status) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci char *errmsg = "Unknown"; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci switch (status) { 1148c2ecf20Sopenharmony_ci case -ENOENT: 1158c2ecf20Sopenharmony_ci errmsg = "unlinked synchronously"; 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci case -ECONNRESET: 1188c2ecf20Sopenharmony_ci errmsg = "unlinked asynchronously"; 1198c2ecf20Sopenharmony_ci break; 1208c2ecf20Sopenharmony_ci case -ENOSR: 1218c2ecf20Sopenharmony_ci errmsg = "Buffer error (overrun)"; 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci case -EPIPE: 1248c2ecf20Sopenharmony_ci errmsg = "Stalled (device not responding)"; 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci case -EOVERFLOW: 1278c2ecf20Sopenharmony_ci errmsg = "Babble (bad cable?)"; 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci case -EPROTO: 1308c2ecf20Sopenharmony_ci errmsg = "Bit-stuff error (bad cable?)"; 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci case -EILSEQ: 1338c2ecf20Sopenharmony_ci errmsg = "CRC/Timeout (could be anything)"; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case -ETIME: 1368c2ecf20Sopenharmony_ci errmsg = "Device does not respond"; 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci if (packet < 0) { 1408c2ecf20Sopenharmony_ci dprintk(1, "URB status %d [%s].\n", status, errmsg); 1418c2ecf20Sopenharmony_ci } else { 1428c2ecf20Sopenharmony_ci dprintk(1, "URB packet %d, status %d [%s].\n", 1438c2ecf20Sopenharmony_ci packet, status, errmsg); 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci int xfer_bulk, num_packets, i; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (!dev) 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (dev->disconnected) 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (urb->status < 0) 1588c2ecf20Sopenharmony_ci print_err_status(dev, -1, urb->status); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci xfer_bulk = usb_pipebulk(urb->pipe); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (xfer_bulk) /* bulk */ 1638c2ecf20Sopenharmony_ci num_packets = 1; 1648c2ecf20Sopenharmony_ci else /* isoc */ 1658c2ecf20Sopenharmony_ci num_packets = urb->number_of_packets; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci for (i = 0; i < num_packets; i++) { 1688c2ecf20Sopenharmony_ci if (xfer_bulk) { 1698c2ecf20Sopenharmony_ci if (urb->status < 0) { 1708c2ecf20Sopenharmony_ci print_err_status(dev, i, urb->status); 1718c2ecf20Sopenharmony_ci if (urb->status != -EPROTO) 1728c2ecf20Sopenharmony_ci continue; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci if (!urb->actual_length) 1758c2ecf20Sopenharmony_ci continue; 1768c2ecf20Sopenharmony_ci dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, 1778c2ecf20Sopenharmony_ci urb->actual_length); 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci if (urb->iso_frame_desc[i].status < 0) { 1808c2ecf20Sopenharmony_ci print_err_status(dev, i, 1818c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].status); 1828c2ecf20Sopenharmony_ci if (urb->iso_frame_desc[i].status != -EPROTO) 1838c2ecf20Sopenharmony_ci continue; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci if (!urb->iso_frame_desc[i].actual_length) 1868c2ecf20Sopenharmony_ci continue; 1878c2ecf20Sopenharmony_ci dvb_dmx_swfilter(&dev->dvb->demux, 1888c2ecf20Sopenharmony_ci urb->transfer_buffer + 1898c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].offset, 1908c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length); 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int em28xx_start_streaming(struct em28xx_dvb *dvb) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci int rc; 2008c2ecf20Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; 2018c2ecf20Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 2028c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(dev->intf); 2038c2ecf20Sopenharmony_ci int dvb_max_packet_size, packet_multiplier, dvb_alt; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if (dev->dvb_xfer_bulk) { 2068c2ecf20Sopenharmony_ci if (!dev->dvb_ep_bulk) 2078c2ecf20Sopenharmony_ci return -ENODEV; 2088c2ecf20Sopenharmony_ci dvb_max_packet_size = 512; /* USB 2.0 spec */ 2098c2ecf20Sopenharmony_ci packet_multiplier = EM28XX_DVB_BULK_PACKET_MULTIPLIER; 2108c2ecf20Sopenharmony_ci dvb_alt = 0; 2118c2ecf20Sopenharmony_ci } else { /* isoc */ 2128c2ecf20Sopenharmony_ci if (!dev->dvb_ep_isoc) 2138c2ecf20Sopenharmony_ci return -ENODEV; 2148c2ecf20Sopenharmony_ci dvb_max_packet_size = dev->dvb_max_pkt_size_isoc; 2158c2ecf20Sopenharmony_ci if (dvb_max_packet_size < 0) 2168c2ecf20Sopenharmony_ci return dvb_max_packet_size; 2178c2ecf20Sopenharmony_ci packet_multiplier = EM28XX_DVB_NUM_ISOC_PACKETS; 2188c2ecf20Sopenharmony_ci dvb_alt = dev->dvb_alt_isoc; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!dev->board.has_dual_ts) 2228c2ecf20Sopenharmony_ci usb_set_interface(udev, dev->ifnum, dvb_alt); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 2258c2ecf20Sopenharmony_ci if (rc < 0) 2268c2ecf20Sopenharmony_ci return rc; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci dprintk(1, "Using %d buffers each with %d x %d bytes, alternate %d\n", 2298c2ecf20Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 2308c2ecf20Sopenharmony_ci packet_multiplier, 2318c2ecf20Sopenharmony_ci dvb_max_packet_size, dvb_alt); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return em28xx_init_usb_xfer(dev, EM28XX_DIGITAL_MODE, 2348c2ecf20Sopenharmony_ci dev->dvb_xfer_bulk, 2358c2ecf20Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 2368c2ecf20Sopenharmony_ci dvb_max_packet_size, 2378c2ecf20Sopenharmony_ci packet_multiplier, 2388c2ecf20Sopenharmony_ci em28xx_dvb_urb_data_copy); 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic int em28xx_stop_streaming(struct em28xx_dvb *dvb) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; 2448c2ecf20Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci em28xx_stop_urbs(dev); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return 0; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int em28xx_start_feed(struct dvb_demux_feed *feed) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci struct dvb_demux *demux = feed->demux; 2548c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = demux->priv; 2558c2ecf20Sopenharmony_ci int rc, ret; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (!demux->dmx.frontend) 2588c2ecf20Sopenharmony_ci return -EINVAL; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci mutex_lock(&dvb->lock); 2618c2ecf20Sopenharmony_ci dvb->nfeeds++; 2628c2ecf20Sopenharmony_ci rc = dvb->nfeeds; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (dvb->nfeeds == 1) { 2658c2ecf20Sopenharmony_ci ret = em28xx_start_streaming(dvb); 2668c2ecf20Sopenharmony_ci if (ret < 0) 2678c2ecf20Sopenharmony_ci rc = ret; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci mutex_unlock(&dvb->lock); 2718c2ecf20Sopenharmony_ci return rc; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int em28xx_stop_feed(struct dvb_demux_feed *feed) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct dvb_demux *demux = feed->demux; 2778c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = demux->priv; 2788c2ecf20Sopenharmony_ci int err = 0; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci mutex_lock(&dvb->lock); 2818c2ecf20Sopenharmony_ci dvb->nfeeds--; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (!dvb->nfeeds) 2848c2ecf20Sopenharmony_ci err = em28xx_stop_streaming(dvb); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci mutex_unlock(&dvb->lock); 2878c2ecf20Sopenharmony_ci return err; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 2918c2ecf20Sopenharmony_cistatic int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 2948c2ecf20Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (acquire) 2978c2ecf20Sopenharmony_ci return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 2988c2ecf20Sopenharmony_ci else 2998c2ecf20Sopenharmony_ci return em28xx_set_mode(dev, EM28XX_SUSPEND); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic struct lgdt330x_config em2880_lgdt3303_dev = { 3058c2ecf20Sopenharmony_ci .demod_chip = LGDT3303, 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic struct lgdt3305_config em2870_lgdt3304_dev = { 3098c2ecf20Sopenharmony_ci .i2c_addr = 0x0e, 3108c2ecf20Sopenharmony_ci .demod_chip = LGDT3304, 3118c2ecf20Sopenharmony_ci .spectral_inversion = 1, 3128c2ecf20Sopenharmony_ci .deny_i2c_rptr = 1, 3138c2ecf20Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_PARALLEL, 3148c2ecf20Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 3158c2ecf20Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 3168c2ecf20Sopenharmony_ci .vsb_if_khz = 3250, 3178c2ecf20Sopenharmony_ci .qam_if_khz = 4000, 3188c2ecf20Sopenharmony_ci}; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic struct lgdt3305_config em2874_lgdt3305_dev = { 3218c2ecf20Sopenharmony_ci .i2c_addr = 0x0e, 3228c2ecf20Sopenharmony_ci .demod_chip = LGDT3305, 3238c2ecf20Sopenharmony_ci .spectral_inversion = 1, 3248c2ecf20Sopenharmony_ci .deny_i2c_rptr = 0, 3258c2ecf20Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_SERIAL, 3268c2ecf20Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 3278c2ecf20Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 3288c2ecf20Sopenharmony_ci .vsb_if_khz = 3250, 3298c2ecf20Sopenharmony_ci .qam_if_khz = 4000, 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic struct lgdt3305_config em2874_lgdt3305_nogate_dev = { 3338c2ecf20Sopenharmony_ci .i2c_addr = 0x0e, 3348c2ecf20Sopenharmony_ci .demod_chip = LGDT3305, 3358c2ecf20Sopenharmony_ci .spectral_inversion = 1, 3368c2ecf20Sopenharmony_ci .deny_i2c_rptr = 1, 3378c2ecf20Sopenharmony_ci .mpeg_mode = LGDT3305_MPEG_SERIAL, 3388c2ecf20Sopenharmony_ci .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, 3398c2ecf20Sopenharmony_ci .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, 3408c2ecf20Sopenharmony_ci .vsb_if_khz = 3600, 3418c2ecf20Sopenharmony_ci .qam_if_khz = 3600, 3428c2ecf20Sopenharmony_ci}; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic struct s921_config sharp_isdbt = { 3458c2ecf20Sopenharmony_ci .demod_address = 0x30 >> 1 3468c2ecf20Sopenharmony_ci}; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_with_xc3028 = { 3498c2ecf20Sopenharmony_ci .demod_address = (0x1e >> 1), 3508c2ecf20Sopenharmony_ci .no_tuner = 1, 3518c2ecf20Sopenharmony_ci .parallel_ts = 1, 3528c2ecf20Sopenharmony_ci .if2 = 45600, 3538c2ecf20Sopenharmony_ci}; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic struct s5h1409_config em28xx_s5h1409_with_xc3028 = { 3568c2ecf20Sopenharmony_ci .demod_address = 0x32 >> 1, 3578c2ecf20Sopenharmony_ci .output_mode = S5H1409_PARALLEL_OUTPUT, 3588c2ecf20Sopenharmony_ci .gpio = S5H1409_GPIO_OFF, 3598c2ecf20Sopenharmony_ci .inversion = S5H1409_INVERSION_OFF, 3608c2ecf20Sopenharmony_ci .status_mode = S5H1409_DEMODLOCKING, 3618c2ecf20Sopenharmony_ci .mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK 3628c2ecf20Sopenharmony_ci}; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic struct tda18271_std_map kworld_a340_std_map = { 3658c2ecf20Sopenharmony_ci .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, 3668c2ecf20Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 3678c2ecf20Sopenharmony_ci .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, 3688c2ecf20Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 3698c2ecf20Sopenharmony_ci}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic struct tda18271_config kworld_a340_config = { 3728c2ecf20Sopenharmony_ci .std_map = &kworld_a340_std_map, 3738c2ecf20Sopenharmony_ci}; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic struct tda18271_config kworld_ub435q_v2_config = { 3768c2ecf20Sopenharmony_ci .std_map = &kworld_a340_std_map, 3778c2ecf20Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 3788c2ecf20Sopenharmony_ci}; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic struct tda18212_config kworld_ub435q_v3_config = { 3818c2ecf20Sopenharmony_ci .if_atsc_vsb = 3600, 3828c2ecf20Sopenharmony_ci .if_atsc_qam = 3600, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { 3868c2ecf20Sopenharmony_ci .demod_address = (0x1e >> 1), 3878c2ecf20Sopenharmony_ci .no_tuner = 1, 3888c2ecf20Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 3898c2ecf20Sopenharmony_ci .parallel_ts = 1, 3908c2ecf20Sopenharmony_ci .if2 = 45600, 3918c2ecf20Sopenharmony_ci}; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic struct drxd_config em28xx_drxd = { 3948c2ecf20Sopenharmony_ci .demod_address = 0x70, 3958c2ecf20Sopenharmony_ci .demod_revision = 0xa2, 3968c2ecf20Sopenharmony_ci .pll_type = DRXD_PLL_NONE, 3978c2ecf20Sopenharmony_ci .clock = 12000, 3988c2ecf20Sopenharmony_ci .insert_rs_byte = 1, 3998c2ecf20Sopenharmony_ci .IF = 42800000, 4008c2ecf20Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 4018c2ecf20Sopenharmony_ci}; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic struct drxk_config terratec_h5_drxk = { 4048c2ecf20Sopenharmony_ci .adr = 0x29, 4058c2ecf20Sopenharmony_ci .single_master = 1, 4068c2ecf20Sopenharmony_ci .no_i2c_bridge = 1, 4078c2ecf20Sopenharmony_ci .microcode_name = "dvb-usb-terratec-h5-drxk.fw", 4088c2ecf20Sopenharmony_ci .qam_demod_parameter_count = 2, 4098c2ecf20Sopenharmony_ci}; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic struct drxk_config hauppauge_930c_drxk = { 4128c2ecf20Sopenharmony_ci .adr = 0x29, 4138c2ecf20Sopenharmony_ci .single_master = 1, 4148c2ecf20Sopenharmony_ci .no_i2c_bridge = 1, 4158c2ecf20Sopenharmony_ci .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", 4168c2ecf20Sopenharmony_ci .chunk_size = 56, 4178c2ecf20Sopenharmony_ci .qam_demod_parameter_count = 2, 4188c2ecf20Sopenharmony_ci}; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic struct drxk_config terratec_htc_stick_drxk = { 4218c2ecf20Sopenharmony_ci .adr = 0x29, 4228c2ecf20Sopenharmony_ci .single_master = 1, 4238c2ecf20Sopenharmony_ci .no_i2c_bridge = 1, 4248c2ecf20Sopenharmony_ci .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw", 4258c2ecf20Sopenharmony_ci .chunk_size = 54, 4268c2ecf20Sopenharmony_ci .qam_demod_parameter_count = 2, 4278c2ecf20Sopenharmony_ci /* Required for the antenna_gpio to disable LNA. */ 4288c2ecf20Sopenharmony_ci .antenna_dvbt = true, 4298c2ecf20Sopenharmony_ci /* The windows driver uses the same. This will disable LNA. */ 4308c2ecf20Sopenharmony_ci .antenna_gpio = 0x6, 4318c2ecf20Sopenharmony_ci}; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic struct drxk_config maxmedia_ub425_tc_drxk = { 4348c2ecf20Sopenharmony_ci .adr = 0x29, 4358c2ecf20Sopenharmony_ci .single_master = 1, 4368c2ecf20Sopenharmony_ci .no_i2c_bridge = 1, 4378c2ecf20Sopenharmony_ci .microcode_name = "dvb-demod-drxk-01.fw", 4388c2ecf20Sopenharmony_ci .chunk_size = 62, 4398c2ecf20Sopenharmony_ci .qam_demod_parameter_count = 2, 4408c2ecf20Sopenharmony_ci}; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic struct drxk_config pctv_520e_drxk = { 4438c2ecf20Sopenharmony_ci .adr = 0x29, 4448c2ecf20Sopenharmony_ci .single_master = 1, 4458c2ecf20Sopenharmony_ci .microcode_name = "dvb-demod-drxk-pctv.fw", 4468c2ecf20Sopenharmony_ci .qam_demod_parameter_count = 2, 4478c2ecf20Sopenharmony_ci .chunk_size = 58, 4488c2ecf20Sopenharmony_ci .antenna_dvbt = true, /* disable LNA */ 4498c2ecf20Sopenharmony_ci .antenna_gpio = (1 << 2), /* disable LNA */ 4508c2ecf20Sopenharmony_ci}; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = fe->sec_priv; 4558c2ecf20Sopenharmony_ci int status; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci if (!dvb) 4588c2ecf20Sopenharmony_ci return -EINVAL; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (enable) { 4618c2ecf20Sopenharmony_ci down(&dvb->pll_mutex); 4628c2ecf20Sopenharmony_ci status = dvb->gate_ctrl(fe, 1); 4638c2ecf20Sopenharmony_ci } else { 4648c2ecf20Sopenharmony_ci status = dvb->gate_ctrl(fe, 0); 4658c2ecf20Sopenharmony_ci up(&dvb->pll_mutex); 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci return status; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic void hauppauge_hvr930c_init(struct em28xx *dev) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci int i; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq hauppauge_hvr930c_init[] = { 4758c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0x65}, 4768c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xfb, 0xff, 0x32}, 4778c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0xb8}, 4788c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 4798c2ecf20Sopenharmony_ci }; 4808c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq hauppauge_hvr930c_end[] = { 4818c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, 4828c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xaf, 0xff, 0x65}, 4838c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x76}, 4848c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, 4858c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, 4868c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x40}, 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x65}, 4898c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, 4908c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, 4918c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 4948c2ecf20Sopenharmony_ci }; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci static const struct { 4978c2ecf20Sopenharmony_ci unsigned char r[4]; 4988c2ecf20Sopenharmony_ci int len; 4998c2ecf20Sopenharmony_ci } regs[] = { 5008c2ecf20Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 5018c2ecf20Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 5028c2ecf20Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 5038c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 5048c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 5058c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 5068c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 5078c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 5088c2ecf20Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 5098c2ecf20Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 5108c2ecf20Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 5118c2ecf20Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 5128c2ecf20Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 5138c2ecf20Sopenharmony_ci }; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, hauppauge_hvr930c_init); 5168c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 5178c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 5188c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 5198c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 5248c2ecf20Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 5258c2ecf20Sopenharmony_ci regs[i].r, regs[i].len); 5268c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, hauppauge_hvr930c_end); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci msleep(100); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 5318c2ecf20Sopenharmony_ci msleep(30); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); 5348c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_cistatic void terratec_h5_init(struct em28xx *dev) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci int i; 5408c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_h5_init[] = { 5418c2ecf20Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 5428c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 5438c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, 5448c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 5458c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 5468c2ecf20Sopenharmony_ci }; 5478c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_h5_end[] = { 5488c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 5498c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, 5508c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 5518c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 5528c2ecf20Sopenharmony_ci }; 5538c2ecf20Sopenharmony_ci static const struct { 5548c2ecf20Sopenharmony_ci unsigned char r[4]; 5558c2ecf20Sopenharmony_ci int len; 5568c2ecf20Sopenharmony_ci } regs[] = { 5578c2ecf20Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 5588c2ecf20Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 5598c2ecf20Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 5608c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 5618c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 5628c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 5638c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 5648c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 5658c2ecf20Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 5668c2ecf20Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 5678c2ecf20Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 5688c2ecf20Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 5698c2ecf20Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 5708c2ecf20Sopenharmony_ci }; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_h5_init); 5738c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 5748c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 5758c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); 5768c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 5818c2ecf20Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 5828c2ecf20Sopenharmony_ci regs[i].r, regs[i].len); 5838c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_h5_end); 5848c2ecf20Sopenharmony_ci}; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic void terratec_htc_stick_init(struct em28xx *dev) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci int i; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* 5918c2ecf20Sopenharmony_ci * GPIO configuration: 5928c2ecf20Sopenharmony_ci * 0xff: unknown (does not affect DVB-T). 5938c2ecf20Sopenharmony_ci * 0xf6: DRX-K (demodulator). 5948c2ecf20Sopenharmony_ci * 0xe6: unknown (does not affect DVB-T). 5958c2ecf20Sopenharmony_ci * 0xb6: unknown (does not affect DVB-T). 5968c2ecf20Sopenharmony_ci */ 5978c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_stick_init[] = { 5988c2ecf20Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 5998c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 6008c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, 6018c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, 6028c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 6038c2ecf20Sopenharmony_ci }; 6048c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_stick_end[] = { 6058c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, 6068c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, 6078c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 6088c2ecf20Sopenharmony_ci }; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /* 6118c2ecf20Sopenharmony_ci * Init the analog decoder (not yet supported), but 6128c2ecf20Sopenharmony_ci * it's probably still a good idea. 6138c2ecf20Sopenharmony_ci */ 6148c2ecf20Sopenharmony_ci static const struct { 6158c2ecf20Sopenharmony_ci unsigned char r[4]; 6168c2ecf20Sopenharmony_ci int len; 6178c2ecf20Sopenharmony_ci } regs[] = { 6188c2ecf20Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 6198c2ecf20Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 6208c2ecf20Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 6218c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 6228c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 6238c2ecf20Sopenharmony_ci }; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_stick_init); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 6288c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 6298c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 6308c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 6358c2ecf20Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 6368c2ecf20Sopenharmony_ci regs[i].r, regs[i].len); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_stick_end); 6398c2ecf20Sopenharmony_ci}; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic void terratec_htc_usb_xs_init(struct em28xx *dev) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci int i; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { 6468c2ecf20Sopenharmony_ci {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, 6478c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, 6488c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, 6498c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, 6508c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 6518c2ecf20Sopenharmony_ci }; 6528c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { 6538c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 100}, 6548c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, 6558c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, 6568c2ecf20Sopenharmony_ci { -1, -1, -1, -1}, 6578c2ecf20Sopenharmony_ci }; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* 6608c2ecf20Sopenharmony_ci * Init the analog decoder (not yet supported), but 6618c2ecf20Sopenharmony_ci * it's probably still a good idea. 6628c2ecf20Sopenharmony_ci */ 6638c2ecf20Sopenharmony_ci static const struct { 6648c2ecf20Sopenharmony_ci unsigned char r[4]; 6658c2ecf20Sopenharmony_ci int len; 6668c2ecf20Sopenharmony_ci } regs[] = { 6678c2ecf20Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 6688c2ecf20Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 6698c2ecf20Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 6708c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 6718c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 6728c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 6738c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 6748c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 6758c2ecf20Sopenharmony_ci {{ 0x04, 0x00 }, 2}, 6768c2ecf20Sopenharmony_ci {{ 0x00, 0x04 }, 2}, 6778c2ecf20Sopenharmony_ci {{ 0x00, 0x04, 0x00, 0x0a }, 4}, 6788c2ecf20Sopenharmony_ci {{ 0x04, 0x14 }, 2}, 6798c2ecf20Sopenharmony_ci {{ 0x04, 0x14, 0x00, 0x00 }, 4}, 6808c2ecf20Sopenharmony_ci }; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_usb_xs_init); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); 6878c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 6888c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); 6898c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 6948c2ecf20Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 6958c2ecf20Sopenharmony_ci regs[i].r, regs[i].len); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci em28xx_gpio_set(dev, terratec_htc_usb_xs_end); 6988c2ecf20Sopenharmony_ci}; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic void pctv_520e_init(struct em28xx *dev) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci /* 7038c2ecf20Sopenharmony_ci * Init AVF4910B analog decoder. Looks like I2C traffic to 7048c2ecf20Sopenharmony_ci * digital demodulator and tuner are routed via AVF4910B. 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci int i; 7078c2ecf20Sopenharmony_ci static const struct { 7088c2ecf20Sopenharmony_ci unsigned char r[4]; 7098c2ecf20Sopenharmony_ci int len; 7108c2ecf20Sopenharmony_ci } regs[] = { 7118c2ecf20Sopenharmony_ci {{ 0x06, 0x02, 0x00, 0x31 }, 4}, 7128c2ecf20Sopenharmony_ci {{ 0x01, 0x02 }, 2}, 7138c2ecf20Sopenharmony_ci {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, 7148c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 7158c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0xff, 0xaf }, 4}, 7168c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, 7178c2ecf20Sopenharmony_ci {{ 0x01, 0x00 }, 2}, 7188c2ecf20Sopenharmony_ci {{ 0x01, 0x00, 0x73, 0xaf }, 4}, 7198c2ecf20Sopenharmony_ci }; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; /* 0x41 */ 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) 7248c2ecf20Sopenharmony_ci i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], 7258c2ecf20Sopenharmony_ci regs[i].r, regs[i].len); 7268c2ecf20Sopenharmony_ci}; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_cistatic int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 7318c2ecf20Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 7328c2ecf20Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 7338c2ecf20Sopenharmony_ci#ifdef CONFIG_GPIOLIB 7348c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 7358c2ecf20Sopenharmony_ci int ret; 7368c2ecf20Sopenharmony_ci unsigned long flags; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci if (c->lna == 1) 7398c2ecf20Sopenharmony_ci flags = GPIOF_OUT_INIT_HIGH; /* enable LNA */ 7408c2ecf20Sopenharmony_ci else 7418c2ecf20Sopenharmony_ci flags = GPIOF_OUT_INIT_LOW; /* disable LNA */ 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci ret = gpio_request_one(dvb->lna_gpio, flags, NULL); 7448c2ecf20Sopenharmony_ci if (ret) 7458c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, "gpio request failed %d\n", ret); 7468c2ecf20Sopenharmony_ci else 7478c2ecf20Sopenharmony_ci gpio_free(dvb->lna_gpio); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci return ret; 7508c2ecf20Sopenharmony_ci#else 7518c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, "%s: LNA control is disabled (lna=%u)\n", 7528c2ecf20Sopenharmony_ci KBUILD_MODNAME, c->lna); 7538c2ecf20Sopenharmony_ci return 0; 7548c2ecf20Sopenharmony_ci#endif 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic int em28xx_pctv_292e_set_lna(struct dvb_frontend *fe) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 7608c2ecf20Sopenharmony_ci struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; 7618c2ecf20Sopenharmony_ci struct em28xx *dev = i2c_bus->dev; 7628c2ecf20Sopenharmony_ci u8 lna; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci if (c->lna == 1) 7658c2ecf20Sopenharmony_ci lna = 0x01; 7668c2ecf20Sopenharmony_ci else 7678c2ecf20Sopenharmony_ci lna = 0x00; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci return em28xx_write_reg_bits(dev, EM2874_R80_GPIO_P0_CTRL, lna, 0x01); 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cistatic int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci /* Values extracted from a USB trace of the Terratec Windows driver */ 7758c2ecf20Sopenharmony_ci static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; 7768c2ecf20Sopenharmony_ci static u8 reset[] = { RESET, 0x80 }; 7778c2ecf20Sopenharmony_ci static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 7788c2ecf20Sopenharmony_ci static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; 7798c2ecf20Sopenharmony_ci static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; 7808c2ecf20Sopenharmony_ci static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; 7818c2ecf20Sopenharmony_ci static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 7828c2ecf20Sopenharmony_ci static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; 7838c2ecf20Sopenharmony_ci static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; 7848c2ecf20Sopenharmony_ci static u8 tuner_go[] = { TUNER_GO, 0x01}; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 7878c2ecf20Sopenharmony_ci usleep_range(200, 250); 7888c2ecf20Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 7898c2ecf20Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 7908c2ecf20Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 7918c2ecf20Sopenharmony_ci mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); 7928c2ecf20Sopenharmony_ci mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); 7938c2ecf20Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 7948c2ecf20Sopenharmony_ci mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); 7958c2ecf20Sopenharmony_ci mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); 7968c2ecf20Sopenharmony_ci mt352_write(fe, tuner_go, sizeof(tuner_go)); 7978c2ecf20Sopenharmony_ci return 0; 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_cistatic void px_bcud_init(struct em28xx *dev) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci int i; 8038c2ecf20Sopenharmony_ci static const struct { 8048c2ecf20Sopenharmony_ci unsigned char r[4]; 8058c2ecf20Sopenharmony_ci int len; 8068c2ecf20Sopenharmony_ci } regs1[] = { 8078c2ecf20Sopenharmony_ci {{ 0x0e, 0x77 }, 2}, 8088c2ecf20Sopenharmony_ci {{ 0x0f, 0x77 }, 2}, 8098c2ecf20Sopenharmony_ci {{ 0x03, 0x90 }, 2}, 8108c2ecf20Sopenharmony_ci }, regs2[] = { 8118c2ecf20Sopenharmony_ci {{ 0x07, 0x01 }, 2}, 8128c2ecf20Sopenharmony_ci {{ 0x08, 0x10 }, 2}, 8138c2ecf20Sopenharmony_ci {{ 0x13, 0x00 }, 2}, 8148c2ecf20Sopenharmony_ci {{ 0x17, 0x00 }, 2}, 8158c2ecf20Sopenharmony_ci {{ 0x03, 0x01 }, 2}, 8168c2ecf20Sopenharmony_ci {{ 0x10, 0xb1 }, 2}, 8178c2ecf20Sopenharmony_ci {{ 0x11, 0x40 }, 2}, 8188c2ecf20Sopenharmony_ci {{ 0x85, 0x7a }, 2}, 8198c2ecf20Sopenharmony_ci {{ 0x87, 0x04 }, 2}, 8208c2ecf20Sopenharmony_ci }; 8218c2ecf20Sopenharmony_ci static const struct em28xx_reg_seq gpio[] = { 8228c2ecf20Sopenharmony_ci {EM28XX_R06_I2C_CLK, 0x40, 0xff, 300}, 8238c2ecf20Sopenharmony_ci {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 60}, 8248c2ecf20Sopenharmony_ci {EM28XX_R15_RGAIN, 0x20, 0xff, 0}, 8258c2ecf20Sopenharmony_ci {EM28XX_R16_GGAIN, 0x20, 0xff, 0}, 8268c2ecf20Sopenharmony_ci {EM28XX_R17_BGAIN, 0x20, 0xff, 0}, 8278c2ecf20Sopenharmony_ci {EM28XX_R18_ROFFSET, 0x00, 0xff, 0}, 8288c2ecf20Sopenharmony_ci {EM28XX_R19_GOFFSET, 0x00, 0xff, 0}, 8298c2ecf20Sopenharmony_ci {EM28XX_R1A_BOFFSET, 0x00, 0xff, 0}, 8308c2ecf20Sopenharmony_ci {EM28XX_R23_UOFFSET, 0x00, 0xff, 0}, 8318c2ecf20Sopenharmony_ci {EM28XX_R24_VOFFSET, 0x00, 0xff, 0}, 8328c2ecf20Sopenharmony_ci {EM28XX_R26_COMPR, 0x00, 0xff, 0}, 8338c2ecf20Sopenharmony_ci {0x13, 0x08, 0xff, 0}, 8348c2ecf20Sopenharmony_ci {EM28XX_R12_VINENABLE, 0x27, 0xff, 0}, 8358c2ecf20Sopenharmony_ci {EM28XX_R0C_USBSUSP, 0x10, 0xff, 0}, 8368c2ecf20Sopenharmony_ci {EM28XX_R27_OUTFMT, 0x00, 0xff, 0}, 8378c2ecf20Sopenharmony_ci {EM28XX_R10_VINMODE, 0x00, 0xff, 0}, 8388c2ecf20Sopenharmony_ci {EM28XX_R11_VINCTRL, 0x11, 0xff, 0}, 8398c2ecf20Sopenharmony_ci {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0}, 8408c2ecf20Sopenharmony_ci {EM2874_R5F_TS_ENABLE, 0x80, 0xff, 0}, 8418c2ecf20Sopenharmony_ci {EM28XX_R06_I2C_CLK, 0x46, 0xff, 0}, 8428c2ecf20Sopenharmony_ci }; 8438c2ecf20Sopenharmony_ci em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46); 8448c2ecf20Sopenharmony_ci /* sleeping ISDB-T */ 8458c2ecf20Sopenharmony_ci dev->dvb->i2c_client_demod->addr = 0x14; 8468c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs1); i++) 8478c2ecf20Sopenharmony_ci i2c_master_send(dev->dvb->i2c_client_demod, 8488c2ecf20Sopenharmony_ci regs1[i].r, regs1[i].len); 8498c2ecf20Sopenharmony_ci /* sleeping ISDB-S */ 8508c2ecf20Sopenharmony_ci dev->dvb->i2c_client_demod->addr = 0x15; 8518c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs2); i++) 8528c2ecf20Sopenharmony_ci i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r, 8538c2ecf20Sopenharmony_ci regs2[i].len); 8548c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(gpio); i++) { 8558c2ecf20Sopenharmony_ci em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val, 8568c2ecf20Sopenharmony_ci gpio[i].mask); 8578c2ecf20Sopenharmony_ci if (gpio[i].sleep > 0) 8588c2ecf20Sopenharmony_ci msleep(gpio[i].sleep); 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci}; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic struct mt352_config terratec_xs_mt352_cfg = { 8638c2ecf20Sopenharmony_ci .demod_address = (0x1e >> 1), 8648c2ecf20Sopenharmony_ci .no_tuner = 1, 8658c2ecf20Sopenharmony_ci .if2 = 45600, 8668c2ecf20Sopenharmony_ci .demod_init = em28xx_mt352_terratec_xs_init, 8678c2ecf20Sopenharmony_ci}; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic struct tda10023_config em28xx_tda10023_config = { 8708c2ecf20Sopenharmony_ci .demod_address = 0x0c, 8718c2ecf20Sopenharmony_ci .invert = 1, 8728c2ecf20Sopenharmony_ci}; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_cistatic struct cxd2820r_config em28xx_cxd2820r_config = { 8758c2ecf20Sopenharmony_ci .i2c_address = (0xd8 >> 1), 8768c2ecf20Sopenharmony_ci .ts_mode = CXD2820R_TS_SERIAL, 8778c2ecf20Sopenharmony_ci}; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic struct tda18271_config em28xx_cxd2820r_tda18271_config = { 8808c2ecf20Sopenharmony_ci .output_opt = TDA18271_OUTPUT_LT_OFF, 8818c2ecf20Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 8828c2ecf20Sopenharmony_ci}; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_cistatic struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { 8858c2ecf20Sopenharmony_ci .demod_address = (0x1e >> 1), 8868c2ecf20Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 8878c2ecf20Sopenharmony_ci .no_tuner = 1, 8888c2ecf20Sopenharmony_ci .parallel_ts = 1, 8898c2ecf20Sopenharmony_ci}; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic struct mt2060_config em28xx_mt2060_config = { 8928c2ecf20Sopenharmony_ci .i2c_address = 0x60, 8938c2ecf20Sopenharmony_ci}; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic struct qt1010_config em28xx_qt1010_config = { 8968c2ecf20Sopenharmony_ci .i2c_address = 0x62 8978c2ecf20Sopenharmony_ci}; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_cistatic const struct mb86a20s_config c3tech_duo_mb86a20s_config = { 9008c2ecf20Sopenharmony_ci .demod_address = 0x10, 9018c2ecf20Sopenharmony_ci .is_serial = true, 9028c2ecf20Sopenharmony_ci}; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_cistatic struct tda18271_std_map mb86a20s_tda18271_config = { 9058c2ecf20Sopenharmony_ci .dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4, 9068c2ecf20Sopenharmony_ci .if_lvl = 1, .rfagc_top = 0x37, }, 9078c2ecf20Sopenharmony_ci}; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_cistatic struct tda18271_config c3tech_duo_tda18271_config = { 9108c2ecf20Sopenharmony_ci .std_map = &mb86a20s_tda18271_config, 9118c2ecf20Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 9128c2ecf20Sopenharmony_ci .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, 9138c2ecf20Sopenharmony_ci}; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic struct tda18271_std_map drx_j_std_map = { 9168c2ecf20Sopenharmony_ci .atsc_6 = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1, 9178c2ecf20Sopenharmony_ci .rfagc_top = 0x37, }, 9188c2ecf20Sopenharmony_ci .qam_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, .if_lvl = 1, 9198c2ecf20Sopenharmony_ci .rfagc_top = 0x37, }, 9208c2ecf20Sopenharmony_ci}; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_cistatic struct tda18271_config pinnacle_80e_dvb_config = { 9238c2ecf20Sopenharmony_ci .std_map = &drx_j_std_map, 9248c2ecf20Sopenharmony_ci .gate = TDA18271_GATE_DIGITAL, 9258c2ecf20Sopenharmony_ci .role = TDA18271_MASTER, 9268c2ecf20Sopenharmony_ci}; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_cistatic struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = { 9298c2ecf20Sopenharmony_ci .qam_if_khz = 4000, 9308c2ecf20Sopenharmony_ci .vsb_if_khz = 3250, 9318c2ecf20Sopenharmony_ci .spectral_inversion = 0, 9328c2ecf20Sopenharmony_ci .deny_i2c_rptr = 0, 9338c2ecf20Sopenharmony_ci .mpeg_mode = LGDT3306A_MPEG_SERIAL, 9348c2ecf20Sopenharmony_ci .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, 9358c2ecf20Sopenharmony_ci .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, 9368c2ecf20Sopenharmony_ci .xtalMHz = 25, 9378c2ecf20Sopenharmony_ci}; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_cistatic noinline_for_stack int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct dvb_frontend *fe; 9448c2ecf20Sopenharmony_ci struct xc2028_config cfg; 9458c2ecf20Sopenharmony_ci struct xc2028_ctrl ctl; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 9488c2ecf20Sopenharmony_ci cfg.i2c_adap = &dev->i2c_adap[dev->def_i2c_bus]; 9498c2ecf20Sopenharmony_ci cfg.i2c_addr = addr; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci memset(&ctl, 0, sizeof(ctl)); 9528c2ecf20Sopenharmony_ci em28xx_setup_xc3028(dev, &ctl); 9538c2ecf20Sopenharmony_ci cfg.ctrl = &ctl; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (!dev->dvb->fe[0]) { 9568c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, 9578c2ecf20Sopenharmony_ci "dvb frontend not attached. Can't attach xc3028\n"); 9588c2ecf20Sopenharmony_ci return -EINVAL; 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); 9628c2ecf20Sopenharmony_ci if (!fe) { 9638c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, "xc3028 attach failed\n"); 9648c2ecf20Sopenharmony_ci dvb_frontend_detach(dev->dvb->fe[0]); 9658c2ecf20Sopenharmony_ci dev->dvb->fe[0] = NULL; 9668c2ecf20Sopenharmony_ci return -EINVAL; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "xc3028 attached\n"); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci return 0; 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, 9778c2ecf20Sopenharmony_ci struct em28xx *dev, struct device *device) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci int result; 9808c2ecf20Sopenharmony_ci bool create_rf_connector = false; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci mutex_init(&dvb->lock); 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci /* register adapter */ 9858c2ecf20Sopenharmony_ci result = dvb_register_adapter(&dvb->adapter, 9868c2ecf20Sopenharmony_ci dev_name(&dev->intf->dev), module, 9878c2ecf20Sopenharmony_ci device, adapter_nr); 9888c2ecf20Sopenharmony_ci if (result < 0) { 9898c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 9908c2ecf20Sopenharmony_ci "dvb_register_adapter failed (errno = %d)\n", 9918c2ecf20Sopenharmony_ci result); 9928c2ecf20Sopenharmony_ci goto fail_adapter; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 9958c2ecf20Sopenharmony_ci dvb->adapter.mdev = dev->media_dev; 9968c2ecf20Sopenharmony_ci#endif 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci /* Ensure all frontends negotiate bus access */ 9998c2ecf20Sopenharmony_ci dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 10008c2ecf20Sopenharmony_ci if (dvb->fe[1]) 10018c2ecf20Sopenharmony_ci dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci dvb->adapter.priv = &dev->i2c_bus[dev->def_i2c_bus]; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci /* register frontend */ 10068c2ecf20Sopenharmony_ci result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); 10078c2ecf20Sopenharmony_ci if (result < 0) { 10088c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10098c2ecf20Sopenharmony_ci "dvb_register_frontend failed (errno = %d)\n", 10108c2ecf20Sopenharmony_ci result); 10118c2ecf20Sopenharmony_ci goto fail_frontend0; 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci /* register 2nd frontend */ 10158c2ecf20Sopenharmony_ci if (dvb->fe[1]) { 10168c2ecf20Sopenharmony_ci result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); 10178c2ecf20Sopenharmony_ci if (result < 0) { 10188c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10198c2ecf20Sopenharmony_ci "2nd dvb_register_frontend failed (errno = %d)\n", 10208c2ecf20Sopenharmony_ci result); 10218c2ecf20Sopenharmony_ci goto fail_frontend1; 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* register demux stuff */ 10268c2ecf20Sopenharmony_ci dvb->demux.dmx.capabilities = 10278c2ecf20Sopenharmony_ci DMX_TS_FILTERING | DMX_SECTION_FILTERING | 10288c2ecf20Sopenharmony_ci DMX_MEMORY_BASED_FILTERING; 10298c2ecf20Sopenharmony_ci dvb->demux.priv = dvb; 10308c2ecf20Sopenharmony_ci dvb->demux.filternum = 256; 10318c2ecf20Sopenharmony_ci dvb->demux.feednum = 256; 10328c2ecf20Sopenharmony_ci dvb->demux.start_feed = em28xx_start_feed; 10338c2ecf20Sopenharmony_ci dvb->demux.stop_feed = em28xx_stop_feed; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci result = dvb_dmx_init(&dvb->demux); 10368c2ecf20Sopenharmony_ci if (result < 0) { 10378c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10388c2ecf20Sopenharmony_ci "dvb_dmx_init failed (errno = %d)\n", 10398c2ecf20Sopenharmony_ci result); 10408c2ecf20Sopenharmony_ci goto fail_dmx; 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci dvb->dmxdev.filternum = 256; 10448c2ecf20Sopenharmony_ci dvb->dmxdev.demux = &dvb->demux.dmx; 10458c2ecf20Sopenharmony_ci dvb->dmxdev.capabilities = 0; 10468c2ecf20Sopenharmony_ci result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); 10478c2ecf20Sopenharmony_ci if (result < 0) { 10488c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10498c2ecf20Sopenharmony_ci "dvb_dmxdev_init failed (errno = %d)\n", 10508c2ecf20Sopenharmony_ci result); 10518c2ecf20Sopenharmony_ci goto fail_dmxdev; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci dvb->fe_hw.source = DMX_FRONTEND_0; 10558c2ecf20Sopenharmony_ci result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); 10568c2ecf20Sopenharmony_ci if (result < 0) { 10578c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10588c2ecf20Sopenharmony_ci "add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", 10598c2ecf20Sopenharmony_ci result); 10608c2ecf20Sopenharmony_ci goto fail_fe_hw; 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci dvb->fe_mem.source = DMX_MEMORY_FE; 10648c2ecf20Sopenharmony_ci result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); 10658c2ecf20Sopenharmony_ci if (result < 0) { 10668c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10678c2ecf20Sopenharmony_ci "add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", 10688c2ecf20Sopenharmony_ci result); 10698c2ecf20Sopenharmony_ci goto fail_fe_mem; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); 10738c2ecf20Sopenharmony_ci if (result < 0) { 10748c2ecf20Sopenharmony_ci dev_warn(&dev->intf->dev, 10758c2ecf20Sopenharmony_ci "connect_frontend failed (errno = %d)\n", 10768c2ecf20Sopenharmony_ci result); 10778c2ecf20Sopenharmony_ci goto fail_fe_conn; 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci /* register network adapter */ 10818c2ecf20Sopenharmony_ci dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci /* If the analog part won't create RF connectors, DVB will do it */ 10848c2ecf20Sopenharmony_ci if (!dev->has_video || dev->tuner_type == TUNER_ABSENT) 10858c2ecf20Sopenharmony_ci create_rf_connector = true; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci result = dvb_create_media_graph(&dvb->adapter, create_rf_connector); 10888c2ecf20Sopenharmony_ci if (result < 0) 10898c2ecf20Sopenharmony_ci goto fail_create_graph; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci return 0; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cifail_create_graph: 10948c2ecf20Sopenharmony_ci dvb_net_release(&dvb->net); 10958c2ecf20Sopenharmony_cifail_fe_conn: 10968c2ecf20Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 10978c2ecf20Sopenharmony_cifail_fe_mem: 10988c2ecf20Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 10998c2ecf20Sopenharmony_cifail_fe_hw: 11008c2ecf20Sopenharmony_ci dvb_dmxdev_release(&dvb->dmxdev); 11018c2ecf20Sopenharmony_cifail_dmxdev: 11028c2ecf20Sopenharmony_ci dvb_dmx_release(&dvb->demux); 11038c2ecf20Sopenharmony_cifail_dmx: 11048c2ecf20Sopenharmony_ci if (dvb->fe[1]) 11058c2ecf20Sopenharmony_ci dvb_unregister_frontend(dvb->fe[1]); 11068c2ecf20Sopenharmony_ci dvb_unregister_frontend(dvb->fe[0]); 11078c2ecf20Sopenharmony_cifail_frontend1: 11088c2ecf20Sopenharmony_ci if (dvb->fe[1]) 11098c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[1]); 11108c2ecf20Sopenharmony_cifail_frontend0: 11118c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 11128c2ecf20Sopenharmony_ci dvb_unregister_adapter(&dvb->adapter); 11138c2ecf20Sopenharmony_cifail_adapter: 11148c2ecf20Sopenharmony_ci return result; 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_cistatic void em28xx_unregister_dvb(struct em28xx_dvb *dvb) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci dvb_net_release(&dvb->net); 11208c2ecf20Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); 11218c2ecf20Sopenharmony_ci dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 11228c2ecf20Sopenharmony_ci dvb_dmxdev_release(&dvb->dmxdev); 11238c2ecf20Sopenharmony_ci dvb_dmx_release(&dvb->demux); 11248c2ecf20Sopenharmony_ci if (dvb->fe[1]) 11258c2ecf20Sopenharmony_ci dvb_unregister_frontend(dvb->fe[1]); 11268c2ecf20Sopenharmony_ci dvb_unregister_frontend(dvb->fe[0]); 11278c2ecf20Sopenharmony_ci if (dvb->fe[1] && !dvb->dont_attach_fe1) 11288c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[1]); 11298c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 11308c2ecf20Sopenharmony_ci dvb_unregister_adapter(&dvb->adapter); 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_cistatic int em28174_dvb_init_pctv_460e(struct em28xx *dev) 11348c2ecf20Sopenharmony_ci{ 11358c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 11368c2ecf20Sopenharmony_ci struct tda10071_platform_data tda10071_pdata = {}; 11378c2ecf20Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci /* attach demod + tuner combo */ 11408c2ecf20Sopenharmony_ci tda10071_pdata.clk = 40444000; /* 40.444 MHz */ 11418c2ecf20Sopenharmony_ci tda10071_pdata.i2c_wr_max = 64; 11428c2ecf20Sopenharmony_ci tda10071_pdata.ts_mode = TDA10071_TS_SERIAL; 11438c2ecf20Sopenharmony_ci tda10071_pdata.pll_multiplier = 20; 11448c2ecf20Sopenharmony_ci tda10071_pdata.tuner_i2c_addr = 0x14; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("tda10071", "tda10071_cx24118", 11478c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 11488c2ecf20Sopenharmony_ci 0x55, &tda10071_pdata); 11498c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 11508c2ecf20Sopenharmony_ci return -ENODEV; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci dvb->fe[0] = tda10071_pdata.get_dvb_frontend(dvb->i2c_client_demod); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci /* attach SEC */ 11558c2ecf20Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 11588c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 11598c2ecf20Sopenharmony_ci 0x08, &a8293_pdata); 11608c2ecf20Sopenharmony_ci if (!dvb->i2c_client_sec) { 11618c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 11628c2ecf20Sopenharmony_ci return -ENODEV; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return 0; 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic int em28178_dvb_init_pctv_461e(struct em28xx *dev) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 11718c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 11728c2ecf20Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 11738c2ecf20Sopenharmony_ci struct ts2020_config ts2020_config = {}; 11748c2ecf20Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* attach demod */ 11778c2ecf20Sopenharmony_ci m88ds3103_pdata.clk = 27000000; 11788c2ecf20Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33; 11798c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; 11808c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk = 16000; 11818c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 1; 11828c2ecf20Sopenharmony_ci m88ds3103_pdata.agc = 0x99; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, 11858c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 11868c2ecf20Sopenharmony_ci 0x68, &m88ds3103_pdata); 11878c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 11888c2ecf20Sopenharmony_ci return -ENODEV; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); 11918c2ecf20Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci /* attach tuner */ 11948c2ecf20Sopenharmony_ci ts2020_config.fe = dvb->fe[0]; 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", 11978c2ecf20Sopenharmony_ci i2c_adapter, 11988c2ecf20Sopenharmony_ci 0x60, &ts2020_config); 11998c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 12008c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 12018c2ecf20Sopenharmony_ci return -ENODEV; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci /* delegate signal strength measurement to tuner */ 12058c2ecf20Sopenharmony_ci dvb->fe[0]->ops.read_signal_strength = 12068c2ecf20Sopenharmony_ci dvb->fe[0]->ops.tuner_ops.get_rf_strength; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci /* attach SEC */ 12098c2ecf20Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 12108c2ecf20Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 12118c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 12128c2ecf20Sopenharmony_ci 0x08, &a8293_pdata); 12138c2ecf20Sopenharmony_ci if (!dvb->i2c_client_sec) { 12148c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 12158c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 12168c2ecf20Sopenharmony_ci return -ENODEV; 12178c2ecf20Sopenharmony_ci } 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci return 0; 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_cistatic int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 12258c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adapter; 12268c2ecf20Sopenharmony_ci struct m88ds3103_platform_data m88ds3103_pdata = {}; 12278c2ecf20Sopenharmony_ci struct ts2020_config ts2020_config = {}; 12288c2ecf20Sopenharmony_ci struct a8293_platform_data a8293_pdata = {}; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci /* attach demod */ 12318c2ecf20Sopenharmony_ci m88ds3103_pdata.clk = 27000000; 12328c2ecf20Sopenharmony_ci m88ds3103_pdata.i2c_wr_max = 33; 12338c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; 12348c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk = 16000; 12358c2ecf20Sopenharmony_ci m88ds3103_pdata.ts_clk_pol = 0; 12368c2ecf20Sopenharmony_ci m88ds3103_pdata.agc = 0x99; 12378c2ecf20Sopenharmony_ci m88ds3103_pdata.agc_inv = 0; 12388c2ecf20Sopenharmony_ci m88ds3103_pdata.spec_inv = 0; 12398c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b", 12408c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 12418c2ecf20Sopenharmony_ci 0x6a, &m88ds3103_pdata); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 12448c2ecf20Sopenharmony_ci return -ENODEV; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); 12478c2ecf20Sopenharmony_ci i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci /* attach tuner */ 12508c2ecf20Sopenharmony_ci ts2020_config.fe = dvb->fe[0]; 12518c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", 12528c2ecf20Sopenharmony_ci i2c_adapter, 12538c2ecf20Sopenharmony_ci 0x60, &ts2020_config); 12548c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 12558c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 12568c2ecf20Sopenharmony_ci return -ENODEV; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci /* delegate signal strength measurement to tuner */ 12608c2ecf20Sopenharmony_ci dvb->fe[0]->ops.read_signal_strength = 12618c2ecf20Sopenharmony_ci dvb->fe[0]->ops.tuner_ops.get_rf_strength; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci /* attach SEC */ 12648c2ecf20Sopenharmony_ci a8293_pdata.dvb_frontend = dvb->fe[0]; 12658c2ecf20Sopenharmony_ci dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, 12668c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 12678c2ecf20Sopenharmony_ci 0x08, &a8293_pdata); 12688c2ecf20Sopenharmony_ci if (!dvb->i2c_client_sec) { 12698c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 12708c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 12718c2ecf20Sopenharmony_ci return -ENODEV; 12728c2ecf20Sopenharmony_ci } 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci return 0; 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_cistatic int em28178_dvb_init_pctv_292e(struct em28xx *dev) 12788c2ecf20Sopenharmony_ci{ 12798c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 12808c2ecf20Sopenharmony_ci struct i2c_adapter *adapter; 12818c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 12828c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci /* attach demod */ 12858c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 12868c2ecf20Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 12878c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 12888c2ecf20Sopenharmony_ci si2168_config.spectral_inversion = true; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 12918c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 12928c2ecf20Sopenharmony_ci 0x64, &si2168_config); 12938c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 12948c2ecf20Sopenharmony_ci return -ENODEV; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci /* attach tuner */ 12978c2ecf20Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 12988c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 12998c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 13008c2ecf20Sopenharmony_ci si2157_config.mdev = dev->media_dev; 13018c2ecf20Sopenharmony_ci#endif 13028c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 13038c2ecf20Sopenharmony_ci adapter, 13048c2ecf20Sopenharmony_ci 0x60, &si2157_config); 13058c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 13068c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 13078c2ecf20Sopenharmony_ci return -ENODEV; 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci return 0; 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_cistatic int em28178_dvb_init_terratec_t2_stick_hd(struct em28xx *dev) 13158c2ecf20Sopenharmony_ci{ 13168c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 13178c2ecf20Sopenharmony_ci struct i2c_adapter *adapter; 13188c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 13198c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci /* attach demod */ 13228c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 13238c2ecf20Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 13248c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_PARALLEL; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 13278c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 13288c2ecf20Sopenharmony_ci 0x64, &si2168_config); 13298c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 13308c2ecf20Sopenharmony_ci return -ENODEV; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci /* attach tuner */ 13338c2ecf20Sopenharmony_ci memset(&si2157_config, 0, sizeof(si2157_config)); 13348c2ecf20Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 13358c2ecf20Sopenharmony_ci si2157_config.if_port = 0; 13368c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 13378c2ecf20Sopenharmony_ci si2157_config.mdev = dev->media_dev; 13388c2ecf20Sopenharmony_ci#endif 13398c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", "si2146", 13408c2ecf20Sopenharmony_ci adapter, 13418c2ecf20Sopenharmony_ci 0x60, &si2157_config); 13428c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 13438c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 13448c2ecf20Sopenharmony_ci return -ENODEV; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci return 0; 13488c2ecf20Sopenharmony_ci} 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_cistatic int em28178_dvb_init_plex_px_bcud(struct em28xx *dev) 13518c2ecf20Sopenharmony_ci{ 13528c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 13538c2ecf20Sopenharmony_ci struct tc90522_config tc90522_config = {}; 13548c2ecf20Sopenharmony_ci struct qm1d1c0042_config qm1d1c0042_config = {}; 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci /* attach demod */ 13578c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("tc90522", "tc90522sat", 13588c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 13598c2ecf20Sopenharmony_ci 0x15, &tc90522_config); 13608c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 13618c2ecf20Sopenharmony_ci return -ENODEV; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci /* attach tuner */ 13648c2ecf20Sopenharmony_ci qm1d1c0042_config.fe = tc90522_config.fe; 13658c2ecf20Sopenharmony_ci qm1d1c0042_config.lpf = 1; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("qm1d1c0042", NULL, 13688c2ecf20Sopenharmony_ci tc90522_config.tuner_i2c, 13698c2ecf20Sopenharmony_ci 0x61, &qm1d1c0042_config); 13708c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 13718c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 13728c2ecf20Sopenharmony_ci return -ENODEV; 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci dvb->fe[0] = tc90522_config.fe; 13768c2ecf20Sopenharmony_ci px_bcud_init(dev); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci return 0; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistatic int em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx *dev) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 13848c2ecf20Sopenharmony_ci struct i2c_adapter *adapter; 13858c2ecf20Sopenharmony_ci struct si2168_config si2168_config = {}; 13868c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 13878c2ecf20Sopenharmony_ci unsigned char addr; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci /* attach demod */ 13908c2ecf20Sopenharmony_ci si2168_config.i2c_adapter = &adapter; 13918c2ecf20Sopenharmony_ci si2168_config.fe = &dvb->fe[0]; 13928c2ecf20Sopenharmony_ci si2168_config.ts_mode = SI2168_TS_SERIAL; 13938c2ecf20Sopenharmony_ci si2168_config.spectral_inversion = true; 13948c2ecf20Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x64 : 0x67; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("si2168", NULL, 13978c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 13988c2ecf20Sopenharmony_ci addr, &si2168_config); 13998c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 14008c2ecf20Sopenharmony_ci return -ENODEV; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci /* attach tuner */ 14038c2ecf20Sopenharmony_ci memset(&si2157_config, 0, sizeof(si2157_config)); 14048c2ecf20Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 14058c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 14068c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 14078c2ecf20Sopenharmony_ci si2157_config.mdev = dev->media_dev; 14088c2ecf20Sopenharmony_ci#endif 14098c2ecf20Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 14128c2ecf20Sopenharmony_ci adapter, 14138c2ecf20Sopenharmony_ci addr, &si2157_config); 14148c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 14158c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 14168c2ecf20Sopenharmony_ci return -ENODEV; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci return 0; 14208c2ecf20Sopenharmony_ci} 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_cistatic int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev) 14238c2ecf20Sopenharmony_ci{ 14248c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 14258c2ecf20Sopenharmony_ci struct i2c_adapter *adapter; 14268c2ecf20Sopenharmony_ci struct lgdt3306a_config lgdt3306a_config = {}; 14278c2ecf20Sopenharmony_ci struct si2157_config si2157_config = {}; 14288c2ecf20Sopenharmony_ci unsigned char addr; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* attach demod */ 14318c2ecf20Sopenharmony_ci lgdt3306a_config = hauppauge_01595_lgdt3306a_config; 14328c2ecf20Sopenharmony_ci lgdt3306a_config.fe = &dvb->fe[0]; 14338c2ecf20Sopenharmony_ci lgdt3306a_config.i2c_adapter = &adapter; 14348c2ecf20Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x59 : 0x0e; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci dvb->i2c_client_demod = dvb_module_probe("lgdt3306a", NULL, 14378c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 14388c2ecf20Sopenharmony_ci addr, &lgdt3306a_config); 14398c2ecf20Sopenharmony_ci if (!dvb->i2c_client_demod) 14408c2ecf20Sopenharmony_ci return -ENODEV; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci /* attach tuner */ 14438c2ecf20Sopenharmony_ci si2157_config.fe = dvb->fe[0]; 14448c2ecf20Sopenharmony_ci si2157_config.if_port = 1; 14458c2ecf20Sopenharmony_ci si2157_config.inversion = 1; 14468c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_DVB 14478c2ecf20Sopenharmony_ci si2157_config.mdev = dev->media_dev; 14488c2ecf20Sopenharmony_ci#endif 14498c2ecf20Sopenharmony_ci addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x62; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, 14528c2ecf20Sopenharmony_ci adapter, 14538c2ecf20Sopenharmony_ci addr, &si2157_config); 14548c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 14558c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 14568c2ecf20Sopenharmony_ci return -ENODEV; 14578c2ecf20Sopenharmony_ci } 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci return 0; 14608c2ecf20Sopenharmony_ci} 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_cistatic int em28xx_dvb_init(struct em28xx *dev) 14638c2ecf20Sopenharmony_ci{ 14648c2ecf20Sopenharmony_ci int result = 0, dvb_alt = 0; 14658c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb; 14668c2ecf20Sopenharmony_ci struct usb_device *udev; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci if (dev->is_audio_only) { 14698c2ecf20Sopenharmony_ci /* Shouldn't initialize IR for this interface */ 14708c2ecf20Sopenharmony_ci return 0; 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (!dev->board.has_dvb) { 14748c2ecf20Sopenharmony_ci /* This device does not support the extension */ 14758c2ecf20Sopenharmony_ci return 0; 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "Binding DVB extension\n"); 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci dvb = kzalloc(sizeof(*dvb), GFP_KERNEL); 14818c2ecf20Sopenharmony_ci if (!dvb) 14828c2ecf20Sopenharmony_ci return -ENOMEM; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci dev->dvb = dvb; 14858c2ecf20Sopenharmony_ci dvb->fe[0] = NULL; 14868c2ecf20Sopenharmony_ci dvb->fe[1] = NULL; 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci /* pre-allocate DVB usb transfer buffers */ 14898c2ecf20Sopenharmony_ci if (dev->dvb_xfer_bulk) { 14908c2ecf20Sopenharmony_ci result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, 14918c2ecf20Sopenharmony_ci dev->dvb_xfer_bulk, 14928c2ecf20Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 14938c2ecf20Sopenharmony_ci 512, 14948c2ecf20Sopenharmony_ci EM28XX_DVB_BULK_PACKET_MULTIPLIER); 14958c2ecf20Sopenharmony_ci } else { 14968c2ecf20Sopenharmony_ci result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, 14978c2ecf20Sopenharmony_ci dev->dvb_xfer_bulk, 14988c2ecf20Sopenharmony_ci EM28XX_DVB_NUM_BUFS, 14998c2ecf20Sopenharmony_ci dev->dvb_max_pkt_size_isoc, 15008c2ecf20Sopenharmony_ci EM28XX_DVB_NUM_ISOC_PACKETS); 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci if (result) { 15038c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, 15048c2ecf20Sopenharmony_ci "failed to pre-allocate USB transfer buffers for DVB.\n"); 15058c2ecf20Sopenharmony_ci kfree(dvb); 15068c2ecf20Sopenharmony_ci dev->dvb = NULL; 15078c2ecf20Sopenharmony_ci return result; 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci mutex_lock(&dev->lock); 15118c2ecf20Sopenharmony_ci em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 15128c2ecf20Sopenharmony_ci /* init frontend */ 15138c2ecf20Sopenharmony_ci switch (dev->model) { 15148c2ecf20Sopenharmony_ci case EM2874_BOARD_LEADERSHIP_ISDBT: 15158c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(s921_attach, 15168c2ecf20Sopenharmony_ci &sharp_isdbt, 15178c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 15208c2ecf20Sopenharmony_ci result = -EINVAL; 15218c2ecf20Sopenharmony_ci goto out_free; 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci break; 15258c2ecf20Sopenharmony_ci case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 15268c2ecf20Sopenharmony_ci case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 15278c2ecf20Sopenharmony_ci case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 15288c2ecf20Sopenharmony_ci case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 15298c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt330x_attach, 15308c2ecf20Sopenharmony_ci &em2880_lgdt3303_dev, 15318c2ecf20Sopenharmony_ci 0x0e, 15328c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15338c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 15348c2ecf20Sopenharmony_ci result = -EINVAL; 15358c2ecf20Sopenharmony_ci goto out_free; 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci break; 15388c2ecf20Sopenharmony_ci case EM2880_BOARD_KWORLD_DVB_310U: 15398c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 15408c2ecf20Sopenharmony_ci &em28xx_zl10353_with_xc3028, 15418c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15428c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 15438c2ecf20Sopenharmony_ci result = -EINVAL; 15448c2ecf20Sopenharmony_ci goto out_free; 15458c2ecf20Sopenharmony_ci } 15468c2ecf20Sopenharmony_ci break; 15478c2ecf20Sopenharmony_ci case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 15488c2ecf20Sopenharmony_ci case EM2882_BOARD_TERRATEC_HYBRID_XS: 15498c2ecf20Sopenharmony_ci case EM2880_BOARD_EMPIRE_DUAL_TV: 15508c2ecf20Sopenharmony_ci case EM2882_BOARD_ZOLID_HYBRID_TV_STICK: 15518c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 15528c2ecf20Sopenharmony_ci &em28xx_zl10353_xc3028_no_i2c_gate, 15538c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15548c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 15558c2ecf20Sopenharmony_ci result = -EINVAL; 15568c2ecf20Sopenharmony_ci goto out_free; 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci break; 15598c2ecf20Sopenharmony_ci case EM2880_BOARD_TERRATEC_HYBRID_XS: 15608c2ecf20Sopenharmony_ci case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: 15618c2ecf20Sopenharmony_ci case EM2881_BOARD_PINNACLE_HYBRID_PRO: 15628c2ecf20Sopenharmony_ci case EM2882_BOARD_DIKOM_DK300: 15638c2ecf20Sopenharmony_ci case EM2882_BOARD_KWORLD_VS_DVBT: 15648c2ecf20Sopenharmony_ci /* 15658c2ecf20Sopenharmony_ci * Those boards could have either a zl10353 or a mt352. 15668c2ecf20Sopenharmony_ci * If the chip id isn't for zl10353, try mt352. 15678c2ecf20Sopenharmony_ci */ 15688c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 15698c2ecf20Sopenharmony_ci &em28xx_zl10353_xc3028_no_i2c_gate, 15708c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15718c2ecf20Sopenharmony_ci if (!dvb->fe[0]) 15728c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(mt352_attach, 15738c2ecf20Sopenharmony_ci &terratec_xs_mt352_cfg, 15748c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 15778c2ecf20Sopenharmony_ci result = -EINVAL; 15788c2ecf20Sopenharmony_ci goto out_free; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci break; 15818c2ecf20Sopenharmony_ci case EM2870_BOARD_TERRATEC_XS_MT2060: 15828c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 15838c2ecf20Sopenharmony_ci &em28xx_zl10353_no_i2c_gate_dev, 15848c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15858c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 15868c2ecf20Sopenharmony_ci dvb_attach(mt2060_attach, dvb->fe[0], 15878c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 15888c2ecf20Sopenharmony_ci &em28xx_mt2060_config, 1220); 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci break; 15918c2ecf20Sopenharmony_ci case EM2870_BOARD_KWORLD_355U: 15928c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(zl10353_attach, 15938c2ecf20Sopenharmony_ci &em28xx_zl10353_no_i2c_gate_dev, 15948c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 15958c2ecf20Sopenharmony_ci if (dvb->fe[0]) 15968c2ecf20Sopenharmony_ci dvb_attach(qt1010_attach, dvb->fe[0], 15978c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 15988c2ecf20Sopenharmony_ci &em28xx_qt1010_config); 15998c2ecf20Sopenharmony_ci break; 16008c2ecf20Sopenharmony_ci case EM2883_BOARD_KWORLD_HYBRID_330U: 16018c2ecf20Sopenharmony_ci case EM2882_BOARD_EVGA_INDTUBE: 16028c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(s5h1409_attach, 16038c2ecf20Sopenharmony_ci &em28xx_s5h1409_with_xc3028, 16048c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 16058c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 16068c2ecf20Sopenharmony_ci result = -EINVAL; 16078c2ecf20Sopenharmony_ci goto out_free; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci break; 16108c2ecf20Sopenharmony_ci case EM2882_BOARD_KWORLD_ATSC_315U: 16118c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt330x_attach, 16128c2ecf20Sopenharmony_ci &em2880_lgdt3303_dev, 16138c2ecf20Sopenharmony_ci 0x0e, 16148c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 16158c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 16168c2ecf20Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, dvb->fe[0], 16178c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16188c2ecf20Sopenharmony_ci 0x61, TUNER_THOMSON_DTT761X)) { 16198c2ecf20Sopenharmony_ci result = -EINVAL; 16208c2ecf20Sopenharmony_ci goto out_free; 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci break; 16248c2ecf20Sopenharmony_ci case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 16258c2ecf20Sopenharmony_ci case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: 16268c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, 16278c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16288c2ecf20Sopenharmony_ci &dev->intf->dev); 16298c2ecf20Sopenharmony_ci if (em28xx_attach_xc3028(0x61, dev) < 0) { 16308c2ecf20Sopenharmony_ci result = -EINVAL; 16318c2ecf20Sopenharmony_ci goto out_free; 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci break; 16348c2ecf20Sopenharmony_ci case EM2870_BOARD_REDDO_DVB_C_USB_BOX: 16358c2ecf20Sopenharmony_ci /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ 16368c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(tda10023_attach, 16378c2ecf20Sopenharmony_ci &em28xx_tda10023_config, 16388c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16398c2ecf20Sopenharmony_ci 0x48); 16408c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 16418c2ecf20Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, dvb->fe[0], 16428c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16438c2ecf20Sopenharmony_ci 0x60, TUNER_PHILIPS_CU1216L)) { 16448c2ecf20Sopenharmony_ci result = -EINVAL; 16458c2ecf20Sopenharmony_ci goto out_free; 16468c2ecf20Sopenharmony_ci } 16478c2ecf20Sopenharmony_ci } 16488c2ecf20Sopenharmony_ci break; 16498c2ecf20Sopenharmony_ci case EM2870_BOARD_KWORLD_A340: 16508c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 16518c2ecf20Sopenharmony_ci &em2870_lgdt3304_dev, 16528c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 16538c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 16548c2ecf20Sopenharmony_ci result = -EINVAL; 16558c2ecf20Sopenharmony_ci goto out_free; 16568c2ecf20Sopenharmony_ci } 16578c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 16588c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16598c2ecf20Sopenharmony_ci &kworld_a340_config)) { 16608c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 16618c2ecf20Sopenharmony_ci result = -EINVAL; 16628c2ecf20Sopenharmony_ci goto out_free; 16638c2ecf20Sopenharmony_ci } 16648c2ecf20Sopenharmony_ci break; 16658c2ecf20Sopenharmony_ci case EM28174_BOARD_PCTV_290E: 16668c2ecf20Sopenharmony_ci /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ 16678c2ecf20Sopenharmony_ci dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O | 16688c2ecf20Sopenharmony_ci CXD2820R_GPIO_L; 16698c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(cxd2820r_attach, 16708c2ecf20Sopenharmony_ci &em28xx_cxd2820r_config, 16718c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16728c2ecf20Sopenharmony_ci &dvb->lna_gpio); 16738c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 16748c2ecf20Sopenharmony_ci /* FE 0 attach tuner */ 16758c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, 16768c2ecf20Sopenharmony_ci dvb->fe[0], 16778c2ecf20Sopenharmony_ci 0x60, 16788c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 16798c2ecf20Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 16808c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 16818c2ecf20Sopenharmony_ci result = -EINVAL; 16828c2ecf20Sopenharmony_ci goto out_free; 16838c2ecf20Sopenharmony_ci } 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci#ifdef CONFIG_GPIOLIB 16868c2ecf20Sopenharmony_ci /* enable LNA for DVB-T, DVB-T2 and DVB-C */ 16878c2ecf20Sopenharmony_ci result = gpio_request_one(dvb->lna_gpio, 16888c2ecf20Sopenharmony_ci GPIOF_OUT_INIT_LOW, NULL); 16898c2ecf20Sopenharmony_ci if (result) 16908c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, 16918c2ecf20Sopenharmony_ci "gpio request failed %d\n", 16928c2ecf20Sopenharmony_ci result); 16938c2ecf20Sopenharmony_ci else 16948c2ecf20Sopenharmony_ci gpio_free(dvb->lna_gpio); 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci result = 0; /* continue even set LNA fails */ 16978c2ecf20Sopenharmony_ci#endif 16988c2ecf20Sopenharmony_ci dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna; 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci break; 17028c2ecf20Sopenharmony_ci case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: 17038c2ecf20Sopenharmony_ci { 17048c2ecf20Sopenharmony_ci struct xc5000_config cfg = {}; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci hauppauge_hvr930c_init(dev); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, 17098c2ecf20Sopenharmony_ci &hauppauge_930c_drxk, 17108c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 17118c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 17128c2ecf20Sopenharmony_ci result = -EINVAL; 17138c2ecf20Sopenharmony_ci goto out_free; 17148c2ecf20Sopenharmony_ci } 17158c2ecf20Sopenharmony_ci /* FIXME: do we need a pll semaphore? */ 17168c2ecf20Sopenharmony_ci dvb->fe[0]->sec_priv = dvb; 17178c2ecf20Sopenharmony_ci sema_init(&dvb->pll_mutex, 1); 17188c2ecf20Sopenharmony_ci dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; 17198c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci /* Attach xc5000 */ 17228c2ecf20Sopenharmony_ci cfg.i2c_address = 0x61; 17238c2ecf20Sopenharmony_ci cfg.if_khz = 4000; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 17268c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); 17278c2ecf20Sopenharmony_ci if (!dvb_attach(xc5000_attach, dvb->fe[0], 17288c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], &cfg)) { 17298c2ecf20Sopenharmony_ci result = -EINVAL; 17308c2ecf20Sopenharmony_ci goto out_free; 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 17338c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci break; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci case EM2884_BOARD_TERRATEC_H5: 17388c2ecf20Sopenharmony_ci terratec_h5_init(dev); 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, 17418c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 17428c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 17438c2ecf20Sopenharmony_ci result = -EINVAL; 17448c2ecf20Sopenharmony_ci goto out_free; 17458c2ecf20Sopenharmony_ci } 17468c2ecf20Sopenharmony_ci /* FIXME: do we need a pll semaphore? */ 17478c2ecf20Sopenharmony_ci dvb->fe[0]->sec_priv = dvb; 17488c2ecf20Sopenharmony_ci sema_init(&dvb->pll_mutex, 1); 17498c2ecf20Sopenharmony_ci dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; 17508c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci /* Attach tda18271 to DVB-C frontend */ 17538c2ecf20Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 17548c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); 17558c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], 17568c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 0x60)) { 17578c2ecf20Sopenharmony_ci result = -EINVAL; 17588c2ecf20Sopenharmony_ci goto out_free; 17598c2ecf20Sopenharmony_ci } 17608c2ecf20Sopenharmony_ci if (dvb->fe[0]->ops.i2c_gate_ctrl) 17618c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci break; 17648c2ecf20Sopenharmony_ci case EM2884_BOARD_C3TECH_DIGITAL_DUO: 17658c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(mb86a20s_attach, 17668c2ecf20Sopenharmony_ci &c3tech_duo_mb86a20s_config, 17678c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 17688c2ecf20Sopenharmony_ci if (dvb->fe[0]) 17698c2ecf20Sopenharmony_ci dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 17708c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 17718c2ecf20Sopenharmony_ci &c3tech_duo_tda18271_config); 17728c2ecf20Sopenharmony_ci break; 17738c2ecf20Sopenharmony_ci case EM28174_BOARD_PCTV_460E: 17748c2ecf20Sopenharmony_ci result = em28174_dvb_init_pctv_460e(dev); 17758c2ecf20Sopenharmony_ci if (result) 17768c2ecf20Sopenharmony_ci goto out_free; 17778c2ecf20Sopenharmony_ci break; 17788c2ecf20Sopenharmony_ci case EM2874_BOARD_DELOCK_61959: 17798c2ecf20Sopenharmony_ci case EM2874_BOARD_MAXMEDIA_UB425_TC: 17808c2ecf20Sopenharmony_ci /* attach demodulator */ 17818c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, 17828c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 17858c2ecf20Sopenharmony_ci /* disable I2C-gate */ 17868c2ecf20Sopenharmony_ci dvb->fe[0]->ops.i2c_gate_ctrl = NULL; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci /* attach tuner */ 17898c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 17908c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 17918c2ecf20Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 17928c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 17938c2ecf20Sopenharmony_ci result = -EINVAL; 17948c2ecf20Sopenharmony_ci goto out_free; 17958c2ecf20Sopenharmony_ci } 17968c2ecf20Sopenharmony_ci } 17978c2ecf20Sopenharmony_ci break; 17988c2ecf20Sopenharmony_ci case EM2884_BOARD_PCTV_510E: 17998c2ecf20Sopenharmony_ci case EM2884_BOARD_PCTV_520E: 18008c2ecf20Sopenharmony_ci pctv_520e_init(dev); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci /* attach demodulator */ 18038c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, 18048c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 18078c2ecf20Sopenharmony_ci /* attach tuner */ 18088c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 18098c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 18108c2ecf20Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 18118c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 18128c2ecf20Sopenharmony_ci result = -EINVAL; 18138c2ecf20Sopenharmony_ci goto out_free; 18148c2ecf20Sopenharmony_ci } 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci break; 18178c2ecf20Sopenharmony_ci case EM2884_BOARD_ELGATO_EYETV_HYBRID_2008: 18188c2ecf20Sopenharmony_ci case EM2884_BOARD_CINERGY_HTC_STICK: 18198c2ecf20Sopenharmony_ci case EM2884_BOARD_TERRATEC_H6: 18208c2ecf20Sopenharmony_ci terratec_htc_stick_init(dev); 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci /* attach demodulator */ 18238c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, 18248c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 18258c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 18268c2ecf20Sopenharmony_ci result = -EINVAL; 18278c2ecf20Sopenharmony_ci goto out_free; 18288c2ecf20Sopenharmony_ci } 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci /* Attach the demodulator. */ 18318c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 18328c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 18338c2ecf20Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 18348c2ecf20Sopenharmony_ci result = -EINVAL; 18358c2ecf20Sopenharmony_ci goto out_free; 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci break; 18388c2ecf20Sopenharmony_ci case EM2884_BOARD_TERRATEC_HTC_USB_XS: 18398c2ecf20Sopenharmony_ci terratec_htc_usb_xs_init(dev); 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci /* attach demodulator */ 18428c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, 18438c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 18448c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 18458c2ecf20Sopenharmony_ci result = -EINVAL; 18468c2ecf20Sopenharmony_ci goto out_free; 18478c2ecf20Sopenharmony_ci } 18488c2ecf20Sopenharmony_ci 18498c2ecf20Sopenharmony_ci /* Attach the demodulator. */ 18508c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 18518c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 18528c2ecf20Sopenharmony_ci &em28xx_cxd2820r_tda18271_config)) { 18538c2ecf20Sopenharmony_ci result = -EINVAL; 18548c2ecf20Sopenharmony_ci goto out_free; 18558c2ecf20Sopenharmony_ci } 18568c2ecf20Sopenharmony_ci break; 18578c2ecf20Sopenharmony_ci case EM2874_BOARD_KWORLD_UB435Q_V2: 18588c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 18598c2ecf20Sopenharmony_ci &em2874_lgdt3305_dev, 18608c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 18618c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 18628c2ecf20Sopenharmony_ci result = -EINVAL; 18638c2ecf20Sopenharmony_ci goto out_free; 18648c2ecf20Sopenharmony_ci } 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci /* Attach the demodulator. */ 18678c2ecf20Sopenharmony_ci if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, 18688c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 18698c2ecf20Sopenharmony_ci &kworld_ub435q_v2_config)) { 18708c2ecf20Sopenharmony_ci result = -EINVAL; 18718c2ecf20Sopenharmony_ci goto out_free; 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci break; 18748c2ecf20Sopenharmony_ci case EM2874_BOARD_KWORLD_UB435Q_V3: 18758c2ecf20Sopenharmony_ci { 18768c2ecf20Sopenharmony_ci struct i2c_adapter *adapter = &dev->i2c_adap[dev->def_i2c_bus]; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(lgdt3305_attach, 18798c2ecf20Sopenharmony_ci &em2874_lgdt3305_nogate_dev, 18808c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 18818c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 18828c2ecf20Sopenharmony_ci result = -EINVAL; 18838c2ecf20Sopenharmony_ci goto out_free; 18848c2ecf20Sopenharmony_ci } 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci /* attach tuner */ 18878c2ecf20Sopenharmony_ci kworld_ub435q_v3_config.fe = dvb->fe[0]; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci dvb->i2c_client_tuner = dvb_module_probe("tda18212", NULL, 18908c2ecf20Sopenharmony_ci adapter, 0x60, 18918c2ecf20Sopenharmony_ci &kworld_ub435q_v3_config); 18928c2ecf20Sopenharmony_ci if (!dvb->i2c_client_tuner) { 18938c2ecf20Sopenharmony_ci dvb_frontend_detach(dvb->fe[0]); 18948c2ecf20Sopenharmony_ci result = -ENODEV; 18958c2ecf20Sopenharmony_ci goto out_free; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci break; 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci case EM2874_BOARD_PCTV_HD_MINI_80E: 19008c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(drx39xxj_attach, 19018c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus]); 19028c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 19038c2ecf20Sopenharmony_ci dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0], 19048c2ecf20Sopenharmony_ci 0x60, 19058c2ecf20Sopenharmony_ci &dev->i2c_adap[dev->def_i2c_bus], 19068c2ecf20Sopenharmony_ci &pinnacle_80e_dvb_config); 19078c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 19088c2ecf20Sopenharmony_ci result = -EINVAL; 19098c2ecf20Sopenharmony_ci goto out_free; 19108c2ecf20Sopenharmony_ci } 19118c2ecf20Sopenharmony_ci } 19128c2ecf20Sopenharmony_ci break; 19138c2ecf20Sopenharmony_ci case EM28178_BOARD_PCTV_461E: 19148c2ecf20Sopenharmony_ci result = em28178_dvb_init_pctv_461e(dev); 19158c2ecf20Sopenharmony_ci if (result) 19168c2ecf20Sopenharmony_ci goto out_free; 19178c2ecf20Sopenharmony_ci break; 19188c2ecf20Sopenharmony_ci case EM28178_BOARD_PCTV_461E_V2: 19198c2ecf20Sopenharmony_ci result = em28178_dvb_init_pctv_461e_v2(dev); 19208c2ecf20Sopenharmony_ci if (result) 19218c2ecf20Sopenharmony_ci goto out_free; 19228c2ecf20Sopenharmony_ci break; 19238c2ecf20Sopenharmony_ci case EM28178_BOARD_PCTV_292E: 19248c2ecf20Sopenharmony_ci result = em28178_dvb_init_pctv_292e(dev); 19258c2ecf20Sopenharmony_ci if (result) 19268c2ecf20Sopenharmony_ci goto out_free; 19278c2ecf20Sopenharmony_ci break; 19288c2ecf20Sopenharmony_ci case EM28178_BOARD_TERRATEC_T2_STICK_HD: 19298c2ecf20Sopenharmony_ci result = em28178_dvb_init_terratec_t2_stick_hd(dev); 19308c2ecf20Sopenharmony_ci if (result) 19318c2ecf20Sopenharmony_ci goto out_free; 19328c2ecf20Sopenharmony_ci break; 19338c2ecf20Sopenharmony_ci case EM28178_BOARD_PLEX_PX_BCUD: 19348c2ecf20Sopenharmony_ci result = em28178_dvb_init_plex_px_bcud(dev); 19358c2ecf20Sopenharmony_ci if (result) 19368c2ecf20Sopenharmony_ci goto out_free; 19378c2ecf20Sopenharmony_ci break; 19388c2ecf20Sopenharmony_ci case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: 19398c2ecf20Sopenharmony_ci result = em28174_dvb_init_hauppauge_wintv_dualhd_dvb(dev); 19408c2ecf20Sopenharmony_ci if (result) 19418c2ecf20Sopenharmony_ci goto out_free; 19428c2ecf20Sopenharmony_ci break; 19438c2ecf20Sopenharmony_ci case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595: 19448c2ecf20Sopenharmony_ci result = em28174_dvb_init_hauppauge_wintv_dualhd_01595(dev); 19458c2ecf20Sopenharmony_ci if (result) 19468c2ecf20Sopenharmony_ci goto out_free; 19478c2ecf20Sopenharmony_ci break; 19488c2ecf20Sopenharmony_ci default: 19498c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, 19508c2ecf20Sopenharmony_ci "The frontend of your DVB/ATSC card isn't supported yet\n"); 19518c2ecf20Sopenharmony_ci break; 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci if (!dvb->fe[0]) { 19548c2ecf20Sopenharmony_ci dev_err(&dev->intf->dev, "frontend initialization failed\n"); 19558c2ecf20Sopenharmony_ci result = -EINVAL; 19568c2ecf20Sopenharmony_ci goto out_free; 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci /* define general-purpose callback pointer */ 19598c2ecf20Sopenharmony_ci dvb->fe[0]->callback = em28xx_tuner_callback; 19608c2ecf20Sopenharmony_ci if (dvb->fe[1]) 19618c2ecf20Sopenharmony_ci dvb->fe[1]->callback = em28xx_tuner_callback; 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci /* register everything */ 19648c2ecf20Sopenharmony_ci result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->intf->dev); 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ci if (result < 0) 19678c2ecf20Sopenharmony_ci goto out_free; 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if (dev->dvb_xfer_bulk) { 19708c2ecf20Sopenharmony_ci dvb_alt = 0; 19718c2ecf20Sopenharmony_ci } else { /* isoc */ 19728c2ecf20Sopenharmony_ci dvb_alt = dev->dvb_alt_isoc; 19738c2ecf20Sopenharmony_ci } 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci udev = interface_to_usbdev(dev->intf); 19768c2ecf20Sopenharmony_ci usb_set_interface(udev, dev->ifnum, dvb_alt); 19778c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "DVB extension successfully initialized\n"); 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci kref_get(&dev->ref); 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ciret: 19828c2ecf20Sopenharmony_ci em28xx_set_mode(dev, EM28XX_SUSPEND); 19838c2ecf20Sopenharmony_ci mutex_unlock(&dev->lock); 19848c2ecf20Sopenharmony_ci return result; 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ciout_free: 19878c2ecf20Sopenharmony_ci em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); 19888c2ecf20Sopenharmony_ci kfree(dvb); 19898c2ecf20Sopenharmony_ci dev->dvb = NULL; 19908c2ecf20Sopenharmony_ci goto ret; 19918c2ecf20Sopenharmony_ci} 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_cistatic inline void prevent_sleep(struct dvb_frontend_ops *ops) 19948c2ecf20Sopenharmony_ci{ 19958c2ecf20Sopenharmony_ci ops->set_voltage = NULL; 19968c2ecf20Sopenharmony_ci ops->sleep = NULL; 19978c2ecf20Sopenharmony_ci ops->tuner_ops.sleep = NULL; 19988c2ecf20Sopenharmony_ci} 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_cistatic int em28xx_dvb_fini(struct em28xx *dev) 20018c2ecf20Sopenharmony_ci{ 20028c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci if (dev->is_audio_only) { 20058c2ecf20Sopenharmony_ci /* Shouldn't initialize IR for this interface */ 20068c2ecf20Sopenharmony_ci return 0; 20078c2ecf20Sopenharmony_ci } 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci if (!dev->board.has_dvb) { 20108c2ecf20Sopenharmony_ci /* This device does not support the extension */ 20118c2ecf20Sopenharmony_ci return 0; 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci if (!dev->dvb) 20158c2ecf20Sopenharmony_ci return 0; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "Closing DVB extension\n"); 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci dvb = dev->dvb; 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci if (dev->disconnected) { 20248c2ecf20Sopenharmony_ci /* 20258c2ecf20Sopenharmony_ci * We cannot tell the device to sleep 20268c2ecf20Sopenharmony_ci * once it has been unplugged. 20278c2ecf20Sopenharmony_ci */ 20288c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 20298c2ecf20Sopenharmony_ci prevent_sleep(&dvb->fe[0]->ops); 20308c2ecf20Sopenharmony_ci dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED; 20318c2ecf20Sopenharmony_ci } 20328c2ecf20Sopenharmony_ci if (dvb->fe[1]) { 20338c2ecf20Sopenharmony_ci prevent_sleep(&dvb->fe[1]->ops); 20348c2ecf20Sopenharmony_ci dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED; 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci } 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci em28xx_unregister_dvb(dvb); 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci /* release I2C module bindings */ 20418c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_sec); 20428c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_tuner); 20438c2ecf20Sopenharmony_ci dvb_module_release(dvb->i2c_client_demod); 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci kfree(dvb); 20468c2ecf20Sopenharmony_ci dev->dvb = NULL; 20478c2ecf20Sopenharmony_ci kref_put(&dev->ref, em28xx_free_device); 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci return 0; 20508c2ecf20Sopenharmony_ci} 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_cistatic int em28xx_dvb_suspend(struct em28xx *dev) 20538c2ecf20Sopenharmony_ci{ 20548c2ecf20Sopenharmony_ci int ret = 0; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci if (dev->is_audio_only) 20578c2ecf20Sopenharmony_ci return 0; 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci if (!dev->board.has_dvb) 20608c2ecf20Sopenharmony_ci return 0; 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "Suspending DVB extension\n"); 20638c2ecf20Sopenharmony_ci if (dev->dvb) { 20648c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 20678c2ecf20Sopenharmony_ci ret = dvb_frontend_suspend(dvb->fe[0]); 20688c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "fe0 suspend %d\n", ret); 20698c2ecf20Sopenharmony_ci } 20708c2ecf20Sopenharmony_ci if (dvb->fe[1]) { 20718c2ecf20Sopenharmony_ci dvb_frontend_suspend(dvb->fe[1]); 20728c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "fe1 suspend %d\n", ret); 20738c2ecf20Sopenharmony_ci } 20748c2ecf20Sopenharmony_ci } 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci return 0; 20778c2ecf20Sopenharmony_ci} 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_cistatic int em28xx_dvb_resume(struct em28xx *dev) 20808c2ecf20Sopenharmony_ci{ 20818c2ecf20Sopenharmony_ci int ret = 0; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci if (dev->is_audio_only) 20848c2ecf20Sopenharmony_ci return 0; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci if (!dev->board.has_dvb) 20878c2ecf20Sopenharmony_ci return 0; 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "Resuming DVB extension\n"); 20908c2ecf20Sopenharmony_ci if (dev->dvb) { 20918c2ecf20Sopenharmony_ci struct em28xx_dvb *dvb = dev->dvb; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci if (dvb->fe[0]) { 20948c2ecf20Sopenharmony_ci ret = dvb_frontend_resume(dvb->fe[0]); 20958c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "fe0 resume %d\n", ret); 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci if (dvb->fe[1]) { 20998c2ecf20Sopenharmony_ci ret = dvb_frontend_resume(dvb->fe[1]); 21008c2ecf20Sopenharmony_ci dev_info(&dev->intf->dev, "fe1 resume %d\n", ret); 21018c2ecf20Sopenharmony_ci } 21028c2ecf20Sopenharmony_ci } 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci return 0; 21058c2ecf20Sopenharmony_ci} 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_cistatic struct em28xx_ops dvb_ops = { 21088c2ecf20Sopenharmony_ci .id = EM28XX_DVB, 21098c2ecf20Sopenharmony_ci .name = "Em28xx dvb Extension", 21108c2ecf20Sopenharmony_ci .init = em28xx_dvb_init, 21118c2ecf20Sopenharmony_ci .fini = em28xx_dvb_fini, 21128c2ecf20Sopenharmony_ci .suspend = em28xx_dvb_suspend, 21138c2ecf20Sopenharmony_ci .resume = em28xx_dvb_resume, 21148c2ecf20Sopenharmony_ci}; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_cistatic int __init em28xx_dvb_register(void) 21178c2ecf20Sopenharmony_ci{ 21188c2ecf20Sopenharmony_ci return em28xx_register_extension(&dvb_ops); 21198c2ecf20Sopenharmony_ci} 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_cistatic void __exit em28xx_dvb_unregister(void) 21228c2ecf20Sopenharmony_ci{ 21238c2ecf20Sopenharmony_ci em28xx_unregister_extension(&dvb_ops); 21248c2ecf20Sopenharmony_ci} 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cimodule_init(em28xx_dvb_register); 21278c2ecf20Sopenharmony_cimodule_exit(em28xx_dvb_unregister); 2128