Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Abilis Systems Single DVB-T Receiver
0004  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
0005  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
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 /* header file for usb device driver*/
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     /* Set frontend arguments */
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     /* send abilis command: GET_TPS */
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     /* send abilis command: GET_TUNE_STATUS */
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     /* send abilis command: GET_TUNE_STATUS */
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     /* Attach the frontend */
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     /* init bus mutex for token locking */
0345     mutex_init(&as102_dev->bus_adap.lock);
0346 
0347     /* init start / stop stream mutex */
0348     mutex_init(&as102_dev->sem);
0349 
0350     /*
0351      * try to load as102 firmware. If firmware upload failed, we'll be
0352      * able to upload it later.
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     /* unregister as102 frontend */
0373     dvb_unregister_frontend(as102_dev->dvb_fe);
0374 
0375     /* detach frontend */
0376     dvb_frontend_detach(as102_dev->dvb_fe);
0377 
0378     /* unregister demux device */
0379     dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
0380     dvb_dmx_release(&as102_dev->dvb_dmx);
0381 
0382     /* unregister dvb adapter */
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 /* modinfo details */
0391 MODULE_DESCRIPTION(DRIVER_FULL_NAME);
0392 MODULE_LICENSE("GPL");
0393 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");