0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/errno.h>
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011 #include <linux/mm.h>
0012 #include <linux/kref.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/usb.h>
0015
0016
0017 #include "as102_drv.h"
0018 #include "as10x_cmd.h"
0019 #include "as102_fe.h"
0020 #include "as102_fw.h"
0021 #include <media/dvbdev.h>
0022
0023 int dual_tuner;
0024 module_param_named(dual_tuner, dual_tuner, int, 0644);
0025 MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
0026
0027 static int fw_upload = 1;
0028 module_param_named(fw_upload, fw_upload, int, 0644);
0029 MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
0030
0031 static int pid_filtering;
0032 module_param_named(pid_filtering, pid_filtering, int, 0644);
0033 MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
0034
0035 static int ts_auto_disable;
0036 module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
0037 MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
0038
0039 int elna_enable = 1;
0040 module_param_named(elna_enable, elna_enable, int, 0644);
0041 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
0042
0043 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0044
0045 static void as102_stop_stream(struct as102_dev_t *dev)
0046 {
0047 struct as10x_bus_adapter_t *bus_adap;
0048
0049 if (dev != NULL)
0050 bus_adap = &dev->bus_adap;
0051 else
0052 return;
0053
0054 if (bus_adap->ops->stop_stream != NULL)
0055 bus_adap->ops->stop_stream(dev);
0056
0057 if (ts_auto_disable) {
0058 if (mutex_lock_interruptible(&dev->bus_adap.lock))
0059 return;
0060
0061 if (as10x_cmd_stop_streaming(bus_adap) < 0)
0062 dev_dbg(&dev->bus_adap.usb_dev->dev,
0063 "as10x_cmd_stop_streaming failed\n");
0064
0065 mutex_unlock(&dev->bus_adap.lock);
0066 }
0067 }
0068
0069 static int as102_start_stream(struct as102_dev_t *dev)
0070 {
0071 struct as10x_bus_adapter_t *bus_adap;
0072 int ret = -EFAULT;
0073
0074 if (dev != NULL)
0075 bus_adap = &dev->bus_adap;
0076 else
0077 return ret;
0078
0079 if (bus_adap->ops->start_stream != NULL)
0080 ret = bus_adap->ops->start_stream(dev);
0081
0082 if (ts_auto_disable) {
0083 if (mutex_lock_interruptible(&dev->bus_adap.lock))
0084 return -EFAULT;
0085
0086 ret = as10x_cmd_start_streaming(bus_adap);
0087
0088 mutex_unlock(&dev->bus_adap.lock);
0089 }
0090
0091 return ret;
0092 }
0093
0094 static int as10x_pid_filter(struct as102_dev_t *dev,
0095 int index, u16 pid, int onoff) {
0096
0097 struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
0098 int ret = -EFAULT;
0099
0100 if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
0101 dev_dbg(&dev->bus_adap.usb_dev->dev,
0102 "amutex_lock_interruptible(lock) failed !\n");
0103 return -EBUSY;
0104 }
0105
0106 switch (onoff) {
0107 case 0:
0108 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
0109 dev_dbg(&dev->bus_adap.usb_dev->dev,
0110 "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
0111 index, pid, ret);
0112 break;
0113 case 1:
0114 {
0115 struct as10x_ts_filter filter;
0116
0117 filter.type = TS_PID_TYPE_TS;
0118 filter.idx = 0xFF;
0119 filter.pid = pid;
0120
0121 ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
0122 dev_dbg(&dev->bus_adap.usb_dev->dev,
0123 "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
0124 index, filter.idx, filter.pid, ret);
0125 break;
0126 }
0127 }
0128
0129 mutex_unlock(&dev->bus_adap.lock);
0130 return ret;
0131 }
0132
0133 static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
0134 {
0135 int ret = 0;
0136 struct dvb_demux *demux = dvbdmxfeed->demux;
0137 struct as102_dev_t *as102_dev = demux->priv;
0138
0139 if (mutex_lock_interruptible(&as102_dev->sem))
0140 return -ERESTARTSYS;
0141
0142 if (pid_filtering)
0143 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
0144 dvbdmxfeed->pid, 1);
0145
0146 if (as102_dev->streaming++ == 0)
0147 ret = as102_start_stream(as102_dev);
0148
0149 mutex_unlock(&as102_dev->sem);
0150 return ret;
0151 }
0152
0153 static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
0154 {
0155 struct dvb_demux *demux = dvbdmxfeed->demux;
0156 struct as102_dev_t *as102_dev = demux->priv;
0157
0158 if (mutex_lock_interruptible(&as102_dev->sem))
0159 return -ERESTARTSYS;
0160
0161 if (--as102_dev->streaming == 0)
0162 as102_stop_stream(as102_dev);
0163
0164 if (pid_filtering)
0165 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
0166 dvbdmxfeed->pid, 0);
0167
0168 mutex_unlock(&as102_dev->sem);
0169 return 0;
0170 }
0171
0172 static int as102_set_tune(void *priv, struct as10x_tune_args *tune_args)
0173 {
0174 struct as10x_bus_adapter_t *bus_adap = priv;
0175 int ret;
0176
0177
0178 if (mutex_lock_interruptible(&bus_adap->lock))
0179 return -EBUSY;
0180
0181 ret = as10x_cmd_set_tune(bus_adap, tune_args);
0182 if (ret != 0)
0183 dev_dbg(&bus_adap->usb_dev->dev,
0184 "as10x_cmd_set_tune failed. (err = %d)\n", ret);
0185
0186 mutex_unlock(&bus_adap->lock);
0187
0188 return ret;
0189 }
0190
0191 static int as102_get_tps(void *priv, struct as10x_tps *tps)
0192 {
0193 struct as10x_bus_adapter_t *bus_adap = priv;
0194 int ret;
0195
0196 if (mutex_lock_interruptible(&bus_adap->lock))
0197 return -EBUSY;
0198
0199
0200 ret = as10x_cmd_get_tps(bus_adap, tps);
0201
0202 mutex_unlock(&bus_adap->lock);
0203
0204 return ret;
0205 }
0206
0207 static int as102_get_status(void *priv, struct as10x_tune_status *tstate)
0208 {
0209 struct as10x_bus_adapter_t *bus_adap = priv;
0210 int ret;
0211
0212 if (mutex_lock_interruptible(&bus_adap->lock))
0213 return -EBUSY;
0214
0215
0216 ret = as10x_cmd_get_tune_status(bus_adap, tstate);
0217 if (ret < 0) {
0218 dev_dbg(&bus_adap->usb_dev->dev,
0219 "as10x_cmd_get_tune_status failed (err = %d)\n",
0220 ret);
0221 }
0222
0223 mutex_unlock(&bus_adap->lock);
0224
0225 return ret;
0226 }
0227
0228 static int as102_get_stats(void *priv, struct as10x_demod_stats *demod_stats)
0229 {
0230 struct as10x_bus_adapter_t *bus_adap = priv;
0231 int ret;
0232
0233 if (mutex_lock_interruptible(&bus_adap->lock))
0234 return -EBUSY;
0235
0236
0237 ret = as10x_cmd_get_demod_stats(bus_adap, demod_stats);
0238 if (ret < 0) {
0239 dev_dbg(&bus_adap->usb_dev->dev,
0240 "as10x_cmd_get_demod_stats failed (probably not tuned)\n");
0241 } else {
0242 dev_dbg(&bus_adap->usb_dev->dev,
0243 "demod status: fc: 0x%08x, bad fc: 0x%08x, bytes corrected: 0x%08x , MER: 0x%04x\n",
0244 demod_stats->frame_count,
0245 demod_stats->bad_frame_count,
0246 demod_stats->bytes_fixed_by_rs,
0247 demod_stats->mer);
0248 }
0249 mutex_unlock(&bus_adap->lock);
0250
0251 return ret;
0252 }
0253
0254 static int as102_stream_ctrl(void *priv, int acquire, uint32_t elna_cfg)
0255 {
0256 struct as10x_bus_adapter_t *bus_adap = priv;
0257 int ret;
0258
0259 if (mutex_lock_interruptible(&bus_adap->lock))
0260 return -EBUSY;
0261
0262 if (acquire) {
0263 if (elna_enable)
0264 as10x_cmd_set_context(bus_adap,
0265 CONTEXT_LNA, elna_cfg);
0266
0267 ret = as10x_cmd_turn_on(bus_adap);
0268 } else {
0269 ret = as10x_cmd_turn_off(bus_adap);
0270 }
0271
0272 mutex_unlock(&bus_adap->lock);
0273
0274 return ret;
0275 }
0276
0277 static const struct as102_fe_ops as102_fe_ops = {
0278 .set_tune = as102_set_tune,
0279 .get_tps = as102_get_tps,
0280 .get_status = as102_get_status,
0281 .get_stats = as102_get_stats,
0282 .stream_ctrl = as102_stream_ctrl,
0283 };
0284
0285 int as102_dvb_register(struct as102_dev_t *as102_dev)
0286 {
0287 struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
0288 int ret;
0289
0290 ret = dvb_register_adapter(&as102_dev->dvb_adap,
0291 as102_dev->name, THIS_MODULE,
0292 dev, adapter_nr);
0293 if (ret < 0) {
0294 dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
0295 __func__, ret);
0296 return ret;
0297 }
0298
0299 as102_dev->dvb_dmx.priv = as102_dev;
0300 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
0301 as102_dev->dvb_dmx.feednum = 256;
0302 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
0303 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
0304
0305 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
0306 DMX_SECTION_FILTERING;
0307
0308 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
0309 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
0310 as102_dev->dvb_dmxdev.capabilities = 0;
0311
0312 ret = dvb_dmx_init(&as102_dev->dvb_dmx);
0313 if (ret < 0) {
0314 dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
0315 goto edmxinit;
0316 }
0317
0318 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
0319 if (ret < 0) {
0320 dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
0321 __func__, ret);
0322 goto edmxdinit;
0323 }
0324
0325
0326 as102_dev->dvb_fe = dvb_attach(as102_attach, as102_dev->name,
0327 &as102_fe_ops,
0328 &as102_dev->bus_adap,
0329 as102_dev->elna_cfg);
0330 if (!as102_dev->dvb_fe) {
0331 ret = -ENODEV;
0332 dev_err(dev, "%s: as102_attach() failed: %d",
0333 __func__, ret);
0334 goto efereg;
0335 }
0336
0337 ret = dvb_register_frontend(&as102_dev->dvb_adap, as102_dev->dvb_fe);
0338 if (ret < 0) {
0339 dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
0340 __func__, ret);
0341 goto efereg;
0342 }
0343
0344
0345 mutex_init(&as102_dev->bus_adap.lock);
0346
0347
0348 mutex_init(&as102_dev->sem);
0349
0350
0351
0352
0353
0354 if (fw_upload)
0355 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
0356 "firmware_class");
0357
0358 pr_info("Registered device %s", as102_dev->name);
0359 return 0;
0360
0361 efereg:
0362 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
0363 edmxdinit:
0364 dvb_dmx_release(&as102_dev->dvb_dmx);
0365 edmxinit:
0366 dvb_unregister_adapter(&as102_dev->dvb_adap);
0367 return ret;
0368 }
0369
0370 void as102_dvb_unregister(struct as102_dev_t *as102_dev)
0371 {
0372
0373 dvb_unregister_frontend(as102_dev->dvb_fe);
0374
0375
0376 dvb_frontend_detach(as102_dev->dvb_fe);
0377
0378
0379 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
0380 dvb_dmx_release(&as102_dev->dvb_dmx);
0381
0382
0383 dvb_unregister_adapter(&as102_dev->dvb_adap);
0384
0385 pr_info("Unregistered device %s", as102_dev->name);
0386 }
0387
0388 module_usb_driver(as102_usb_driver);
0389
0390
0391 MODULE_DESCRIPTION(DRIVER_FULL_NAME);
0392 MODULE_LICENSE("GPL");
0393 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");