Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / media / usb / as102 / as102_drv.c
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>");