Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / usb / as102 / as102_drv.c
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
32 int dual_tuner;
33 module_param_named(dual_tuner, dual_tuner, int, 0644);
34 MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
35
36 static int fw_upload = 1;
37 module_param_named(fw_upload, fw_upload, int, 0644);
38 MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
39
40 static int pid_filtering;
41 module_param_named(pid_filtering, pid_filtering, int, 0644);
42 MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
43
44 static int ts_auto_disable;
45 module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
46 MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
47
48 int elna_enable = 1;
49 module_param_named(elna_enable, elna_enable, int, 0644);
50 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
51
52 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
53
54 static 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
78 static 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
103 static 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
142 static 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
162 static 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
181 static 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
200 static 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
216 static 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
237 static 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
263 static 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
286 static 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
294 int 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
369 efereg:
370         dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
371 edmxdinit:
372         dvb_dmx_release(&as102_dev->dvb_dmx);
373 edmxinit:
374         dvb_unregister_adapter(&as102_dev->dvb_adap);
375         return ret;
376 }
377
378 void 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
396 module_usb_driver(as102_usb_driver);
397
398 /* modinfo details */
399 MODULE_DESCRIPTION(DRIVER_FULL_NAME);
400 MODULE_LICENSE("GPL");
401 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");