1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Abilis Systems Single DVB-T Receiver 4 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> 5 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> 6 */ 7 #include <linux/kernel.h> 8 #include <linux/errno.h> 9 #include <linux/slab.h> 10 #include <linux/module.h> 11 #include <linux/mm.h> 12 #include <linux/kref.h> 13 #include <linux/uaccess.h> 14 #include <linux/usb.h> 15 16 /* header file for usb device driver*/ 17 #include "as102_drv.h" 18 #include "as10x_cmd.h" 19 #include "as102_fe.h" 20 #include "as102_fw.h" 21 #include <media/dvbdev.h> 22 23 int dual_tuner; 24 module_param_named(dual_tuner, dual_tuner, int, 0644); 25 MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)"); 26 27 static int fw_upload = 1; 28 module_param_named(fw_upload, fw_upload, int, 0644); 29 MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)"); 30 31 static int pid_filtering; 32 module_param_named(pid_filtering, pid_filtering, int, 0644); 33 MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)"); 34 35 static int ts_auto_disable; 36 module_param_named(ts_auto_disable, ts_auto_disable, int, 0644); 37 MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)"); 38 39 int elna_enable = 1; 40 module_param_named(elna_enable, elna_enable, int, 0644); 41 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)"); 42 43 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 44 45 static void as102_stop_stream(struct as102_dev_t *dev) 46 { 47 struct as10x_bus_adapter_t *bus_adap; 48 49 if (dev != NULL) 50 bus_adap = &dev->bus_adap; 51 else 52 return; 53 54 if (bus_adap->ops->stop_stream != NULL) 55 bus_adap->ops->stop_stream(dev); 56 57 if (ts_auto_disable) { 58 if (mutex_lock_interruptible(&dev->bus_adap.lock)) 59 return; 60 61 if (as10x_cmd_stop_streaming(bus_adap) < 0) 62 dev_dbg(&dev->bus_adap.usb_dev->dev, 63 "as10x_cmd_stop_streaming failed\n"); 64 65 mutex_unlock(&dev->bus_adap.lock); 66 } 67 } 68 69 static int as102_start_stream(struct as102_dev_t *dev) 70 { 71 struct as10x_bus_adapter_t *bus_adap; 72 int ret = -EFAULT; 73 74 if (dev != NULL) 75 bus_adap = &dev->bus_adap; 76 else 77 return ret; 78 79 if (bus_adap->ops->start_stream != NULL) 80 ret = bus_adap->ops->start_stream(dev); 81 82 if (ts_auto_disable) { 83 if (mutex_lock_interruptible(&dev->bus_adap.lock)) 84 return -EFAULT; 85 86 ret = as10x_cmd_start_streaming(bus_adap); 87 88 mutex_unlock(&dev->bus_adap.lock); 89 } 90 91 return ret; 92 } 93 94 static int as10x_pid_filter(struct as102_dev_t *dev, 95 int index, u16 pid, int onoff) { 96 97 struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap; 98 int ret = -EFAULT; 99 100 if (mutex_lock_interruptible(&dev->bus_adap.lock)) { 101 dev_dbg(&dev->bus_adap.usb_dev->dev, 102 "amutex_lock_interruptible(lock) failed !\n"); 103 return -EBUSY; 104 } 105 106 switch (onoff) { 107 case 0: 108 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid); 109 dev_dbg(&dev->bus_adap.usb_dev->dev, 110 "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n", 111 index, pid, ret); 112 break; 113 case 1: 114 { 115 struct as10x_ts_filter filter; 116 117 filter.type = TS_PID_TYPE_TS; 118 filter.idx = 0xFF; 119 filter.pid = pid; 120 121 ret = as10x_cmd_add_PID_filter(bus_adap, &filter); 122 dev_dbg(&dev->bus_adap.usb_dev->dev, 123 "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n", 124 index, filter.idx, filter.pid, ret); 125 break; 126 } 127 } 128 129 mutex_unlock(&dev->bus_adap.lock); 130 return ret; 131 } 132 133 static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) 134 { 135 int ret = 0; 136 struct dvb_demux *demux = dvbdmxfeed->demux; 137 struct as102_dev_t *as102_dev = demux->priv; 138 139 if (mutex_lock_interruptible(&as102_dev->sem)) 140 return -ERESTARTSYS; 141 142 if (pid_filtering) 143 as10x_pid_filter(as102_dev, dvbdmxfeed->index, 144 dvbdmxfeed->pid, 1); 145 146 if (as102_dev->streaming++ == 0) 147 ret = as102_start_stream(as102_dev); 148 149 mutex_unlock(&as102_dev->sem); 150 return ret; 151 } 152 153 static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 154 { 155 struct dvb_demux *demux = dvbdmxfeed->demux; 156 struct as102_dev_t *as102_dev = demux->priv; 157 158 if (mutex_lock_interruptible(&as102_dev->sem)) 159 return -ERESTARTSYS; 160 161 if (--as102_dev->streaming == 0) 162 as102_stop_stream(as102_dev); 163 164 if (pid_filtering) 165 as10x_pid_filter(as102_dev, dvbdmxfeed->index, 166 dvbdmxfeed->pid, 0); 167 168 mutex_unlock(&as102_dev->sem); 169 return 0; 170 } 171 172 static int as102_set_tune(void *priv, struct as10x_tune_args *tune_args) 173 { 174 struct as10x_bus_adapter_t *bus_adap = priv; 175 int ret; 176 177 /* Set frontend arguments */ 178 if (mutex_lock_interruptible(&bus_adap->lock)) 179 return -EBUSY; 180 181 ret = as10x_cmd_set_tune(bus_adap, tune_args); 182 if (ret != 0) 183 dev_dbg(&bus_adap->usb_dev->dev, 184 "as10x_cmd_set_tune failed. (err = %d)\n", ret); 185 186 mutex_unlock(&bus_adap->lock); 187 188 return ret; 189 } 190 191 static int as102_get_tps(void *priv, struct as10x_tps *tps) 192 { 193 struct as10x_bus_adapter_t *bus_adap = priv; 194 int ret; 195 196 if (mutex_lock_interruptible(&bus_adap->lock)) 197 return -EBUSY; 198 199 /* send abilis command: GET_TPS */ 200 ret = as10x_cmd_get_tps(bus_adap, tps); 201 202 mutex_unlock(&bus_adap->lock); 203 204 return ret; 205 } 206 207 static int as102_get_status(void *priv, struct as10x_tune_status *tstate) 208 { 209 struct as10x_bus_adapter_t *bus_adap = priv; 210 int ret; 211 212 if (mutex_lock_interruptible(&bus_adap->lock)) 213 return -EBUSY; 214 215 /* send abilis command: GET_TUNE_STATUS */ 216 ret = as10x_cmd_get_tune_status(bus_adap, tstate); 217 if (ret < 0) { 218 dev_dbg(&bus_adap->usb_dev->dev, 219 "as10x_cmd_get_tune_status failed (err = %d)\n", 220 ret); 221 } 222 223 mutex_unlock(&bus_adap->lock); 224 225 return ret; 226 } 227 228 static int as102_get_stats(void *priv, struct as10x_demod_stats *demod_stats) 229 { 230 struct as10x_bus_adapter_t *bus_adap = priv; 231 int ret; 232 233 if (mutex_lock_interruptible(&bus_adap->lock)) 234 return -EBUSY; 235 236 /* send abilis command: GET_TUNE_STATUS */ 237 ret = as10x_cmd_get_demod_stats(bus_adap, demod_stats); 238 if (ret < 0) { 239 dev_dbg(&bus_adap->usb_dev->dev, 240 "as10x_cmd_get_demod_stats failed (probably not tuned)\n"); 241 } else { 242 dev_dbg(&bus_adap->usb_dev->dev, 243 "demod status: fc: 0x%08x, bad fc: 0x%08x, bytes corrected: 0x%08x , MER: 0x%04x\n", 244 demod_stats->frame_count, 245 demod_stats->bad_frame_count, 246 demod_stats->bytes_fixed_by_rs, 247 demod_stats->mer); 248 } 249 mutex_unlock(&bus_adap->lock); 250 251 return ret; 252 } 253 254 static int as102_stream_ctrl(void *priv, int acquire, uint32_t elna_cfg) 255 { 256 struct as10x_bus_adapter_t *bus_adap = priv; 257 int ret; 258 259 if (mutex_lock_interruptible(&bus_adap->lock)) 260 return -EBUSY; 261 262 if (acquire) { 263 if (elna_enable) 264 as10x_cmd_set_context(bus_adap, 265 CONTEXT_LNA, elna_cfg); 266 267 ret = as10x_cmd_turn_on(bus_adap); 268 } else { 269 ret = as10x_cmd_turn_off(bus_adap); 270 } 271 272 mutex_unlock(&bus_adap->lock); 273 274 return ret; 275 } 276 277 static const struct as102_fe_ops as102_fe_ops = { 278 .set_tune = as102_set_tune, 279 .get_tps = as102_get_tps, 280 .get_status = as102_get_status, 281 .get_stats = as102_get_stats, 282 .stream_ctrl = as102_stream_ctrl, 283 }; 284 285 int as102_dvb_register(struct as102_dev_t *as102_dev) 286 { 287 struct device *dev = &as102_dev->bus_adap.usb_dev->dev; 288 int ret; 289 290 ret = dvb_register_adapter(&as102_dev->dvb_adap, 291 as102_dev->name, THIS_MODULE, 292 dev, adapter_nr); 293 if (ret < 0) { 294 dev_err(dev, "%s: dvb_register_adapter() failed: %d\n", 295 __func__, ret); 296 return ret; 297 } 298 299 as102_dev->dvb_dmx.priv = as102_dev; 300 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256; 301 as102_dev->dvb_dmx.feednum = 256; 302 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed; 303 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed; 304 305 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING | 306 DMX_SECTION_FILTERING; 307 308 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum; 309 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx; 310 as102_dev->dvb_dmxdev.capabilities = 0; 311 312 ret = dvb_dmx_init(&as102_dev->dvb_dmx); 313 if (ret < 0) { 314 dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret); 315 goto edmxinit; 316 } 317 318 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap); 319 if (ret < 0) { 320 dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n", 321 __func__, ret); 322 goto edmxdinit; 323 } 324 325 /* Attach the frontend */ 326 as102_dev->dvb_fe = dvb_attach(as102_attach, as102_dev->name, 327 &as102_fe_ops, 328 &as102_dev->bus_adap, 329 as102_dev->elna_cfg); 330 if (!as102_dev->dvb_fe) { 331 ret = -ENODEV; 332 dev_err(dev, "%s: as102_attach() failed: %d", 333 __func__, ret); 334 goto efereg; 335 } 336 337 ret = dvb_register_frontend(&as102_dev->dvb_adap, as102_dev->dvb_fe); 338 if (ret < 0) { 339 dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d", 340 __func__, ret); 341 goto efereg; 342 } 343 344 /* init bus mutex for token locking */ 345 mutex_init(&as102_dev->bus_adap.lock); 346 347 /* init start / stop stream mutex */ 348 mutex_init(&as102_dev->sem); 349 350 /* 351 * try to load as102 firmware. If firmware upload failed, we'll be 352 * able to upload it later. 353 */ 354 if (fw_upload) 355 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap), 356 "firmware_class"); 357 358 pr_info("Registered device %s", as102_dev->name); 359 return 0; 360 361 efereg: 362 dvb_dmxdev_release(&as102_dev->dvb_dmxdev); 363 edmxdinit: 364 dvb_dmx_release(&as102_dev->dvb_dmx); 365 edmxinit: 366 dvb_unregister_adapter(&as102_dev->dvb_adap); 367 return ret; 368 } 369 370 void as102_dvb_unregister(struct as102_dev_t *as102_dev) 371 { 372 /* unregister as102 frontend */ 373 dvb_unregister_frontend(as102_dev->dvb_fe); 374 375 /* detach frontend */ 376 dvb_frontend_detach(as102_dev->dvb_fe); 377 378 /* unregister demux device */ 379 dvb_dmxdev_release(&as102_dev->dvb_dmxdev); 380 dvb_dmx_release(&as102_dev->dvb_dmx); 381 382 /* unregister dvb adapter */ 383 dvb_unregister_adapter(&as102_dev->dvb_adap); 384 385 pr_info("Unregistered device %s", as102_dev->name); 386 } 387 388 module_usb_driver(as102_usb_driver); 389 390 /* modinfo details */ 391 MODULE_DESCRIPTION(DRIVER_FULL_NAME); 392 MODULE_LICENSE("GPL"); 393 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>"); 394