xref: /linux/drivers/media/usb/as102/as102_drv.c (revision b601d9a5d668119219d1db95cbe04fdc38eaf5a4)
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 "as102_fw.h"
28 #include "dvbdev.h"
29 
30 int dual_tuner;
31 module_param_named(dual_tuner, dual_tuner, int, 0644);
32 MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
33 
34 static int fw_upload = 1;
35 module_param_named(fw_upload, fw_upload, int, 0644);
36 MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
37 
38 static int pid_filtering;
39 module_param_named(pid_filtering, pid_filtering, int, 0644);
40 MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
41 
42 static int ts_auto_disable;
43 module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
44 MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
45 
46 int elna_enable = 1;
47 module_param_named(elna_enable, elna_enable, int, 0644);
48 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
49 
50 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
51 
52 static void as102_stop_stream(struct as102_dev_t *dev)
53 {
54 	struct as10x_bus_adapter_t *bus_adap;
55 
56 	if (dev != NULL)
57 		bus_adap = &dev->bus_adap;
58 	else
59 		return;
60 
61 	if (bus_adap->ops->stop_stream != NULL)
62 		bus_adap->ops->stop_stream(dev);
63 
64 	if (ts_auto_disable) {
65 		if (mutex_lock_interruptible(&dev->bus_adap.lock))
66 			return;
67 
68 		if (as10x_cmd_stop_streaming(bus_adap) < 0)
69 			dev_dbg(&dev->bus_adap.usb_dev->dev,
70 				"as10x_cmd_stop_streaming failed\n");
71 
72 		mutex_unlock(&dev->bus_adap.lock);
73 	}
74 }
75 
76 static int as102_start_stream(struct as102_dev_t *dev)
77 {
78 	struct as10x_bus_adapter_t *bus_adap;
79 	int ret = -EFAULT;
80 
81 	if (dev != NULL)
82 		bus_adap = &dev->bus_adap;
83 	else
84 		return ret;
85 
86 	if (bus_adap->ops->start_stream != NULL)
87 		ret = bus_adap->ops->start_stream(dev);
88 
89 	if (ts_auto_disable) {
90 		if (mutex_lock_interruptible(&dev->bus_adap.lock))
91 			return -EFAULT;
92 
93 		ret = as10x_cmd_start_streaming(bus_adap);
94 
95 		mutex_unlock(&dev->bus_adap.lock);
96 	}
97 
98 	return ret;
99 }
100 
101 static int as10x_pid_filter(struct as102_dev_t *dev,
102 			    int index, u16 pid, int onoff) {
103 
104 	struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
105 	int ret = -EFAULT;
106 
107 	if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
108 		dev_dbg(&dev->bus_adap.usb_dev->dev,
109 			"amutex_lock_interruptible(lock) failed !\n");
110 		return -EBUSY;
111 	}
112 
113 	switch (onoff) {
114 	case 0:
115 		ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
116 		dev_dbg(&dev->bus_adap.usb_dev->dev,
117 			"DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
118 			index, pid, ret);
119 		break;
120 	case 1:
121 	{
122 		struct as10x_ts_filter filter;
123 
124 		filter.type = TS_PID_TYPE_TS;
125 		filter.idx = 0xFF;
126 		filter.pid = pid;
127 
128 		ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
129 		dev_dbg(&dev->bus_adap.usb_dev->dev,
130 			"ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
131 			index, filter.idx, filter.pid, ret);
132 		break;
133 	}
134 	}
135 
136 	mutex_unlock(&dev->bus_adap.lock);
137 	return ret;
138 }
139 
140 static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
141 {
142 	int ret = 0;
143 	struct dvb_demux *demux = dvbdmxfeed->demux;
144 	struct as102_dev_t *as102_dev = demux->priv;
145 
146 	if (mutex_lock_interruptible(&as102_dev->sem))
147 		return -ERESTARTSYS;
148 
149 	if (pid_filtering)
150 		as10x_pid_filter(as102_dev, dvbdmxfeed->index,
151 				 dvbdmxfeed->pid, 1);
152 
153 	if (as102_dev->streaming++ == 0)
154 		ret = as102_start_stream(as102_dev);
155 
156 	mutex_unlock(&as102_dev->sem);
157 	return ret;
158 }
159 
160 static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
161 {
162 	struct dvb_demux *demux = dvbdmxfeed->demux;
163 	struct as102_dev_t *as102_dev = demux->priv;
164 
165 	if (mutex_lock_interruptible(&as102_dev->sem))
166 		return -ERESTARTSYS;
167 
168 	if (--as102_dev->streaming == 0)
169 		as102_stop_stream(as102_dev);
170 
171 	if (pid_filtering)
172 		as10x_pid_filter(as102_dev, dvbdmxfeed->index,
173 				 dvbdmxfeed->pid, 0);
174 
175 	mutex_unlock(&as102_dev->sem);
176 	return 0;
177 }
178 
179 int as102_dvb_register(struct as102_dev_t *as102_dev)
180 {
181 	struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
182 	int ret;
183 
184 	ret = dvb_register_adapter(&as102_dev->dvb_adap,
185 			   as102_dev->name, THIS_MODULE,
186 			   dev, adapter_nr);
187 	if (ret < 0) {
188 		dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
189 			__func__, ret);
190 		return ret;
191 	}
192 
193 	as102_dev->dvb_dmx.priv = as102_dev;
194 	as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
195 	as102_dev->dvb_dmx.feednum = 256;
196 	as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
197 	as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
198 
199 	as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
200 					      DMX_SECTION_FILTERING;
201 
202 	as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
203 	as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
204 	as102_dev->dvb_dmxdev.capabilities = 0;
205 
206 	ret = dvb_dmx_init(&as102_dev->dvb_dmx);
207 	if (ret < 0) {
208 		dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
209 		goto edmxinit;
210 	}
211 
212 	ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
213 	if (ret < 0) {
214 		dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
215 			__func__, ret);
216 		goto edmxdinit;
217 	}
218 
219 	/* Attach the frontend */
220 	as102_dev->dvb_fe = dvb_attach(as102_attach, as102_dev->name,
221 				       &as102_dev->bus_adap,
222 				       as102_dev->elna_cfg);
223 	if (!as102_dev->dvb_fe) {
224 		dev_err(dev, "%s: as102_attach() failed: %d",
225 		    __func__, ret);
226 		goto efereg;
227 	}
228 
229 	ret =  dvb_register_frontend(&as102_dev->dvb_adap, as102_dev->dvb_fe);
230 	if (ret < 0) {
231 		dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
232 		    __func__, ret);
233 		goto efereg;
234 	}
235 
236 	/* init bus mutex for token locking */
237 	mutex_init(&as102_dev->bus_adap.lock);
238 
239 	/* init start / stop stream mutex */
240 	mutex_init(&as102_dev->sem);
241 
242 	/*
243 	 * try to load as102 firmware. If firmware upload failed, we'll be
244 	 * able to upload it later.
245 	 */
246 	if (fw_upload)
247 		try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
248 				"firmware_class");
249 
250 	pr_info("Registered device %s", as102_dev->name);
251 	return 0;
252 
253 efereg:
254 	dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
255 edmxdinit:
256 	dvb_dmx_release(&as102_dev->dvb_dmx);
257 edmxinit:
258 	dvb_unregister_adapter(&as102_dev->dvb_adap);
259 	return ret;
260 }
261 
262 void as102_dvb_unregister(struct as102_dev_t *as102_dev)
263 {
264 	/* unregister as102 frontend */
265 	dvb_unregister_frontend(as102_dev->dvb_fe);
266 
267 	/* detach frontend */
268 	dvb_frontend_detach(as102_dev->dvb_fe);
269 
270 	/* unregister demux device */
271 	dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
272 	dvb_dmx_release(&as102_dev->dvb_dmx);
273 
274 	/* unregister dvb adapter */
275 	dvb_unregister_adapter(&as102_dev->dvb_adap);
276 
277 	pr_info("Unregistered device %s", as102_dev->name);
278 }
279 
280 module_usb_driver(as102_usb_driver);
281 
282 /* modinfo details */
283 MODULE_DESCRIPTION(DRIVER_FULL_NAME);
284 MODULE_LICENSE("GPL");
285 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
286