staging: delete non-required instances of include <linux/init.h>
[deliverable/linux.git] / drivers / staging / media / as102 / as102_drv.c
CommitLineData
41b44e04
PH
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
c6ccdca9 4 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
41b44e04
PH
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/kernel.h>
21#include <linux/errno.h>
41b44e04
PH
22#include <linux/slab.h>
23#include <linux/module.h>
24#include <linux/mm.h>
25#include <linux/kref.h>
3288e201 26#include <linux/uaccess.h>
41b44e04
PH
27#include <linux/usb.h>
28
b47acf2a 29/* header file for usb device driver*/
41b44e04
PH
30#include "as102_drv.h"
31#include "as102_fw.h"
41b44e04 32#include "dvbdev.h"
41b44e04 33
d29387e8
RD
34int as102_debug;
35module_param_named(debug, as102_debug, int, 0644);
41b44e04
PH
36MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
37
c6ccdca9 38int dual_tuner;
41b44e04 39module_param_named(dual_tuner, dual_tuner, int, 0644);
c6ccdca9 40MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
41b44e04
PH
41
42static int fw_upload = 1;
43module_param_named(fw_upload, fw_upload, int, 0644);
44MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
45
c6ccdca9 46static int pid_filtering;
41b44e04
PH
47module_param_named(pid_filtering, pid_filtering, int, 0644);
48MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
49
c6ccdca9 50static int ts_auto_disable;
41b44e04
PH
51module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
52MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
53
54int elna_enable = 1;
55module_param_named(elna_enable, elna_enable, int, 0644);
56MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
57
41b44e04 58DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
41b44e04 59
c6ccdca9
DH
60static void as102_stop_stream(struct as102_dev_t *dev)
61{
34490a0a 62 struct as10x_bus_adapter_t *bus_adap;
41b44e04
PH
63
64 if (dev != NULL)
65 bus_adap = &dev->bus_adap;
66 else
67 return;
68
69 if (bus_adap->ops->stop_stream != NULL)
70 bus_adap->ops->stop_stream(dev);
71
72 if (ts_auto_disable) {
73 if (mutex_lock_interruptible(&dev->bus_adap.lock))
74 return;
75
c6ccdca9 76 if (as10x_cmd_stop_streaming(bus_adap) < 0)
41b44e04 77 dprintk(debug, "as10x_cmd_stop_streaming failed\n");
41b44e04
PH
78
79 mutex_unlock(&dev->bus_adap.lock);
80 }
81}
82
c6ccdca9
DH
83static int as102_start_stream(struct as102_dev_t *dev)
84{
34490a0a 85 struct as10x_bus_adapter_t *bus_adap;
41b44e04
PH
86 int ret = -EFAULT;
87
88 if (dev != NULL)
89 bus_adap = &dev->bus_adap;
90 else
91 return ret;
92
c6ccdca9 93 if (bus_adap->ops->start_stream != NULL)
41b44e04 94 ret = bus_adap->ops->start_stream(dev);
41b44e04
PH
95
96 if (ts_auto_disable) {
97 if (mutex_lock_interruptible(&dev->bus_adap.lock))
98 return -EFAULT;
99
100 ret = as10x_cmd_start_streaming(bus_adap);
101
102 mutex_unlock(&dev->bus_adap.lock);
103 }
104
105 return ret;
106}
107
108static int as10x_pid_filter(struct as102_dev_t *dev,
109 int index, u16 pid, int onoff) {
110
34490a0a 111 struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
41b44e04
PH
112 int ret = -EFAULT;
113
114 ENTER();
115
116 if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
117 dprintk(debug, "mutex_lock_interruptible(lock) failed !\n");
118 return -EBUSY;
119 }
120
c6ccdca9
DH
121 switch (onoff) {
122 case 0:
14e0e4bf
SN
123 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
124 dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
125 index, pid, ret);
126 break;
c6ccdca9
DH
127 case 1:
128 {
14e0e4bf 129 struct as10x_ts_filter filter;
c6ccdca9 130
14e0e4bf
SN
131 filter.type = TS_PID_TYPE_TS;
132 filter.idx = 0xFF;
133 filter.pid = pid;
c6ccdca9 134
14e0e4bf
SN
135 ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
136 dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
137 index, filter.idx, filter.pid, ret);
138 break;
c6ccdca9 139 }
41b44e04
PH
140 }
141
142 mutex_unlock(&dev->bus_adap.lock);
143
144 LEAVE();
145 return ret;
146}
147
c6ccdca9
DH
148static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
149{
41b44e04
PH
150 int ret = 0;
151 struct dvb_demux *demux = dvbdmxfeed->demux;
152 struct as102_dev_t *as102_dev = demux->priv;
153
154 ENTER();
155
156 if (mutex_lock_interruptible(&as102_dev->sem))
157 return -ERESTARTSYS;
158
14e0e4bf
SN
159 if (pid_filtering)
160 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
161 dvbdmxfeed->pid, 1);
41b44e04 162
c6ccdca9 163 if (as102_dev->streaming++ == 0)
41b44e04 164 ret = as102_start_stream(as102_dev);
41b44e04
PH
165
166 mutex_unlock(&as102_dev->sem);
167 LEAVE();
168 return ret;
169}
170
c6ccdca9
DH
171static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
172{
41b44e04
PH
173 struct dvb_demux *demux = dvbdmxfeed->demux;
174 struct as102_dev_t *as102_dev = demux->priv;
175
176 ENTER();
177
178 if (mutex_lock_interruptible(&as102_dev->sem))
179 return -ERESTARTSYS;
180
c6ccdca9 181 if (--as102_dev->streaming == 0)
41b44e04 182 as102_stop_stream(as102_dev);
41b44e04 183
14e0e4bf
SN
184 if (pid_filtering)
185 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
186 dvbdmxfeed->pid, 0);
41b44e04
PH
187
188 mutex_unlock(&as102_dev->sem);
189 LEAVE();
190 return 0;
191}
41b44e04 192
c6ccdca9
DH
193int as102_dvb_register(struct as102_dev_t *as102_dev)
194{
88010289
SN
195 struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
196 int ret;
41b44e04 197
41b44e04 198 ret = dvb_register_adapter(&as102_dev->dvb_adap,
88010289
SN
199 as102_dev->name, THIS_MODULE,
200 dev, adapter_nr);
41b44e04 201 if (ret < 0) {
88010289
SN
202 dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
203 __func__, ret);
204 return ret;
41b44e04
PH
205 }
206
207 as102_dev->dvb_dmx.priv = as102_dev;
208 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
209 as102_dev->dvb_dmx.feednum = 256;
210 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
211 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
212
213 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
214 DMX_SECTION_FILTERING;
215
216 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
217 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
218 as102_dev->dvb_dmxdev.capabilities = 0;
219
c6ccdca9
DH
220 ret = dvb_dmx_init(&as102_dev->dvb_dmx);
221 if (ret < 0) {
1ec9a35e 222 dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
88010289 223 goto edmxinit;
41b44e04
PH
224 }
225
226 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
227 if (ret < 0) {
88010289
SN
228 dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
229 __func__, ret);
230 goto edmxdinit;
41b44e04
PH
231 }
232
233 ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
234 if (ret < 0) {
88010289 235 dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
c6ccdca9 236 __func__, ret);
88010289 237 goto efereg;
41b44e04 238 }
41b44e04
PH
239
240 /* init bus mutex for token locking */
241 mutex_init(&as102_dev->bus_adap.lock);
242
243 /* init start / stop stream mutex */
244 mutex_init(&as102_dev->sem);
245
41b44e04
PH
246 /*
247 * try to load as102 firmware. If firmware upload failed, we'll be
248 * able to upload it later.
249 */
250 if (fw_upload)
251 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
252 "firmware_class");
88010289
SN
253
254 pr_info("Registered device %s", as102_dev->name);
255 return 0;
256
257efereg:
258 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
259edmxdinit:
260 dvb_dmx_release(&as102_dev->dvb_dmx);
261edmxinit:
262 dvb_unregister_adapter(&as102_dev->dvb_adap);
41b44e04
PH
263 return ret;
264}
265
c6ccdca9
DH
266void as102_dvb_unregister(struct as102_dev_t *as102_dev)
267{
41b44e04
PH
268 /* unregister as102 frontend */
269 as102_dvb_unregister_fe(&as102_dev->dvb_fe);
270
271 /* unregister demux device */
272 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
273 dvb_dmx_release(&as102_dev->dvb_dmx);
274
275 /* unregister dvb adapter */
276 dvb_unregister_adapter(&as102_dev->dvb_adap);
ff7029f5 277
88010289 278 pr_info("Unregistered device %s", as102_dev->name);
41b44e04
PH
279}
280
9451df0e 281module_usb_driver(as102_usb_driver);
41b44e04 282
41b44e04
PH
283/* modinfo details */
284MODULE_DESCRIPTION(DRIVER_FULL_NAME);
285MODULE_LICENSE("GPL");
286MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
This page took 0.193426 seconds and 5 git commands to generate.