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