1 /* 2 * Abilis Systems Single DVB-T Receiver 3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> 4 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 #include <linux/kernel.h> 21 #include <linux/errno.h> 22 #include <linux/slab.h> 23 #include <linux/module.h> 24 #include <linux/mm.h> 25 #include <linux/kref.h> 26 #include <linux/uaccess.h> 27 #include <linux/usb.h> 28 29 /* header file for usb device driver*/ 30 #include "as102_drv.h" 31 #include "as102_fw.h" 32 #include "dvbdev.h" 33 34 int dual_tuner; 35 module_param_named(dual_tuner, dual_tuner, int, 0644); 36 MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)"); 37 38 static int fw_upload = 1; 39 module_param_named(fw_upload, fw_upload, int, 0644); 40 MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)"); 41 42 static int pid_filtering; 43 module_param_named(pid_filtering, pid_filtering, int, 0644); 44 MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)"); 45 46 static int ts_auto_disable; 47 module_param_named(ts_auto_disable, ts_auto_disable, int, 0644); 48 MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)"); 49 50 int elna_enable = 1; 51 module_param_named(elna_enable, elna_enable, int, 0644); 52 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)"); 53 54 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 55 56 static void as102_stop_stream(struct as102_dev_t *dev) 57 { 58 struct as10x_bus_adapter_t *bus_adap; 59 60 if (dev != NULL) 61 bus_adap = &dev->bus_adap; 62 else 63 return; 64 65 if (bus_adap->ops->stop_stream != NULL) 66 bus_adap->ops->stop_stream(dev); 67 68 if (ts_auto_disable) { 69 if (mutex_lock_interruptible(&dev->bus_adap.lock)) 70 return; 71 72 if (as10x_cmd_stop_streaming(bus_adap) < 0) 73 dev_dbg(&dev->bus_adap.usb_dev->dev, 74 "as10x_cmd_stop_streaming failed\n"); 75 76 mutex_unlock(&dev->bus_adap.lock); 77 } 78 } 79 80 static int as102_start_stream(struct as102_dev_t *dev) 81 { 82 struct as10x_bus_adapter_t *bus_adap; 83 int ret = -EFAULT; 84 85 if (dev != NULL) 86 bus_adap = &dev->bus_adap; 87 else 88 return ret; 89 90 if (bus_adap->ops->start_stream != NULL) 91 ret = bus_adap->ops->start_stream(dev); 92 93 if (ts_auto_disable) { 94 if (mutex_lock_interruptible(&dev->bus_adap.lock)) 95 return -EFAULT; 96 97 ret = as10x_cmd_start_streaming(bus_adap); 98 99 mutex_unlock(&dev->bus_adap.lock); 100 } 101 102 return ret; 103 } 104 105 static int as10x_pid_filter(struct as102_dev_t *dev, 106 int index, u16 pid, int onoff) { 107 108 struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap; 109 int ret = -EFAULT; 110 111 if (mutex_lock_interruptible(&dev->bus_adap.lock)) { 112 dev_dbg(&dev->bus_adap.usb_dev->dev, 113 "amutex_lock_interruptible(lock) failed !\n"); 114 return -EBUSY; 115 } 116 117 switch (onoff) { 118 case 0: 119 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid); 120 dev_dbg(&dev->bus_adap.usb_dev->dev, 121 "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n", 122 index, pid, ret); 123 break; 124 case 1: 125 { 126 struct as10x_ts_filter filter; 127 128 filter.type = TS_PID_TYPE_TS; 129 filter.idx = 0xFF; 130 filter.pid = pid; 131 132 ret = as10x_cmd_add_PID_filter(bus_adap, &filter); 133 dev_dbg(&dev->bus_adap.usb_dev->dev, 134 "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n", 135 index, filter.idx, filter.pid, ret); 136 break; 137 } 138 } 139 140 mutex_unlock(&dev->bus_adap.lock); 141 return ret; 142 } 143 144 static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) 145 { 146 int ret = 0; 147 struct dvb_demux *demux = dvbdmxfeed->demux; 148 struct as102_dev_t *as102_dev = demux->priv; 149 150 if (mutex_lock_interruptible(&as102_dev->sem)) 151 return -ERESTARTSYS; 152 153 if (pid_filtering) 154 as10x_pid_filter(as102_dev, dvbdmxfeed->index, 155 dvbdmxfeed->pid, 1); 156 157 if (as102_dev->streaming++ == 0) 158 ret = as102_start_stream(as102_dev); 159 160 mutex_unlock(&as102_dev->sem); 161 return ret; 162 } 163 164 static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 165 { 166 struct dvb_demux *demux = dvbdmxfeed->demux; 167 struct as102_dev_t *as102_dev = demux->priv; 168 169 if (mutex_lock_interruptible(&as102_dev->sem)) 170 return -ERESTARTSYS; 171 172 if (--as102_dev->streaming == 0) 173 as102_stop_stream(as102_dev); 174 175 if (pid_filtering) 176 as10x_pid_filter(as102_dev, dvbdmxfeed->index, 177 dvbdmxfeed->pid, 0); 178 179 mutex_unlock(&as102_dev->sem); 180 return 0; 181 } 182 183 int as102_dvb_register(struct as102_dev_t *as102_dev) 184 { 185 struct device *dev = &as102_dev->bus_adap.usb_dev->dev; 186 int ret; 187 188 ret = dvb_register_adapter(&as102_dev->dvb_adap, 189 as102_dev->name, THIS_MODULE, 190 dev, adapter_nr); 191 if (ret < 0) { 192 dev_err(dev, "%s: dvb_register_adapter() failed: %d\n", 193 __func__, ret); 194 return ret; 195 } 196 197 as102_dev->dvb_dmx.priv = as102_dev; 198 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256; 199 as102_dev->dvb_dmx.feednum = 256; 200 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed; 201 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed; 202 203 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING | 204 DMX_SECTION_FILTERING; 205 206 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum; 207 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx; 208 as102_dev->dvb_dmxdev.capabilities = 0; 209 210 ret = dvb_dmx_init(&as102_dev->dvb_dmx); 211 if (ret < 0) { 212 dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret); 213 goto edmxinit; 214 } 215 216 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap); 217 if (ret < 0) { 218 dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n", 219 __func__, ret); 220 goto edmxdinit; 221 } 222 223 ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe); 224 if (ret < 0) { 225 dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d", 226 __func__, ret); 227 goto efereg; 228 } 229 230 /* init bus mutex for token locking */ 231 mutex_init(&as102_dev->bus_adap.lock); 232 233 /* init start / stop stream mutex */ 234 mutex_init(&as102_dev->sem); 235 236 /* 237 * try to load as102 firmware. If firmware upload failed, we'll be 238 * able to upload it later. 239 */ 240 if (fw_upload) 241 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap), 242 "firmware_class"); 243 244 pr_info("Registered device %s", as102_dev->name); 245 return 0; 246 247 efereg: 248 dvb_dmxdev_release(&as102_dev->dvb_dmxdev); 249 edmxdinit: 250 dvb_dmx_release(&as102_dev->dvb_dmx); 251 edmxinit: 252 dvb_unregister_adapter(&as102_dev->dvb_adap); 253 return ret; 254 } 255 256 void as102_dvb_unregister(struct as102_dev_t *as102_dev) 257 { 258 /* unregister as102 frontend */ 259 as102_dvb_unregister_fe(&as102_dev->dvb_fe); 260 261 /* unregister demux device */ 262 dvb_dmxdev_release(&as102_dev->dvb_dmxdev); 263 dvb_dmx_release(&as102_dev->dvb_dmx); 264 265 /* unregister dvb adapter */ 266 dvb_unregister_adapter(&as102_dev->dvb_adap); 267 268 pr_info("Unregistered device %s", as102_dev->name); 269 } 270 271 module_usb_driver(as102_usb_driver); 272 273 /* modinfo details */ 274 MODULE_DESCRIPTION(DRIVER_FULL_NAME); 275 MODULE_LICENSE("GPL"); 276 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>"); 277