Commit | Line | Data |
---|---|---|
04910bdc MK |
1 | /* |
2 | * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver. | |
3 | * | |
4 | * Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org> | |
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 of the License | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | * | |
19 | */ | |
20 | ||
d8abe97d | 21 | #include <linux/kthread.h> |
bb8ce9d9 | 22 | #include <linux/freezer.h> |
04910bdc MK |
23 | #include "dvbdev.h" |
24 | #include "pvrusb2-hdw-internal.h" | |
25 | #include "pvrusb2-hdw.h" | |
bb8ce9d9 | 26 | #include "pvrusb2-io.h" |
04910bdc MK |
27 | #include "pvrusb2-dvb.h" |
28 | ||
29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |
30 | ||
ceb4340d | 31 | static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) |
bb8ce9d9 | 32 | { |
bb8ce9d9 MI |
33 | int ret; |
34 | unsigned int count; | |
35 | struct pvr2_buffer *bp; | |
a36416d0 | 36 | struct pvr2_stream *stream; |
bb8ce9d9 MI |
37 | |
38 | printk(KERN_DEBUG "dvb thread started\n"); | |
39 | set_freezable(); | |
40 | ||
a36416d0 | 41 | stream = adap->channel.stream->stream; |
bb8ce9d9 MI |
42 | |
43 | for (;;) { | |
a36416d0 | 44 | if (kthread_should_stop()) break; |
bb8ce9d9 MI |
45 | |
46 | /* Not sure about this... */ | |
47 | try_to_freeze(); | |
48 | ||
a36416d0 | 49 | bp = pvr2_stream_get_ready_buffer(stream); |
bb8ce9d9 MI |
50 | if (bp != NULL) { |
51 | count = pvr2_buffer_get_count(bp); | |
52 | if (count) { | |
53 | dvb_dmx_swfilter( | |
54 | &adap->demux, | |
a36416d0 MI |
55 | adap->buffer_storage[ |
56 | pvr2_buffer_get_id(bp)], | |
bb8ce9d9 MI |
57 | count); |
58 | } else { | |
59 | ret = pvr2_buffer_get_status(bp); | |
a36416d0 | 60 | if (ret < 0) break; |
bb8ce9d9 MI |
61 | } |
62 | ret = pvr2_buffer_queue(bp); | |
a36416d0 | 63 | if (ret < 0) break; |
bb8ce9d9 MI |
64 | |
65 | /* Since we know we did something to a buffer, | |
66 | just go back and try again. No point in | |
67 | blocking unless we really ran out of | |
68 | buffers to process. */ | |
69 | continue; | |
70 | } | |
71 | ||
72 | ||
73 | /* Wait until more buffers become available. */ | |
74 | ret = wait_event_interruptible( | |
a36416d0 MI |
75 | adap->buffer_wait_data, |
76 | pvr2_stream_get_ready_count(stream) > 0); | |
77 | if (ret < 0) break; | |
bb8ce9d9 MI |
78 | } |
79 | ||
bb8ce9d9 MI |
80 | /* If we get here and ret is < 0, then an error has occurred. |
81 | Probably would be a good idea to communicate that to DVB core... */ | |
82 | ||
83 | printk(KERN_DEBUG "dvb thread stopped\n"); | |
84 | ||
ceb4340d MI |
85 | return 0; |
86 | } | |
87 | ||
88 | static int pvr2_dvb_feed_thread(void *data) | |
89 | { | |
90 | int stat = pvr2_dvb_feed_func(data); | |
bb8ce9d9 MI |
91 | /* from videobuf-dvb.c: */ |
92 | while (!kthread_should_stop()) { | |
93 | set_current_state(TASK_INTERRUPTIBLE); | |
94 | schedule(); | |
95 | } | |
ceb4340d | 96 | return stat; |
bb8ce9d9 MI |
97 | } |
98 | ||
a36416d0 | 99 | static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap) |
d8abe97d | 100 | { |
a36416d0 MI |
101 | wake_up(&adap->buffer_wait_data); |
102 | } | |
d8abe97d | 103 | |
a36416d0 MI |
104 | static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap) |
105 | { | |
106 | unsigned int idx; | |
107 | struct pvr2_stream *stream; | |
d8abe97d | 108 | |
a36416d0 MI |
109 | if (adap->thread) { |
110 | kthread_stop(adap->thread); | |
111 | adap->thread = NULL; | |
112 | } | |
113 | ||
114 | if (adap->channel.stream) { | |
115 | stream = adap->channel.stream->stream; | |
116 | } else { | |
117 | stream = NULL; | |
118 | } | |
119 | if (stream) { | |
120 | pvr2_hdw_set_streaming(adap->channel.hdw, 0); | |
121 | pvr2_stream_set_callback(stream, NULL, NULL); | |
122 | pvr2_stream_kill(stream); | |
123 | pvr2_stream_set_buffer_count(stream, 0); | |
124 | pvr2_channel_claim_stream(&adap->channel, NULL); | |
125 | } | |
126 | ||
127 | if (adap->stream_run) { | |
128 | for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { | |
129 | if (!(adap->buffer_storage[idx])) continue; | |
130 | kfree(adap->buffer_storage[idx]); | |
131 | adap->buffer_storage[idx] = 0; | |
132 | } | |
133 | adap->stream_run = 0; | |
134 | } | |
135 | } | |
136 | ||
137 | static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap) | |
138 | { | |
139 | struct pvr2_context *pvr = adap->channel.mc_head; | |
140 | unsigned int idx; | |
141 | int ret; | |
142 | struct pvr2_buffer *bp; | |
143 | struct pvr2_stream *stream = 0; | |
144 | ||
145 | if (adap->stream_run) return -EIO; | |
146 | ||
147 | ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream); | |
148 | /* somebody else already has the stream */ | |
149 | if (ret < 0) return ret; | |
150 | ||
151 | stream = adap->channel.stream->stream; | |
152 | ||
153 | for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { | |
154 | adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE, | |
155 | GFP_KERNEL); | |
156 | if (!(adap->buffer_storage[idx])) return -ENOMEM; | |
157 | } | |
158 | ||
159 | pvr2_stream_set_callback(pvr->video_stream.stream, | |
160 | (pvr2_stream_callback) pvr2_dvb_notify, adap); | |
161 | ||
162 | ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT); | |
163 | if (ret < 0) return ret; | |
d8abe97d | 164 | |
a36416d0 MI |
165 | for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { |
166 | bp = pvr2_stream_get_buffer(stream, idx); | |
167 | pvr2_buffer_set_buffer(bp, | |
168 | adap->buffer_storage[idx], | |
169 | PVR2_DVB_BUFFER_SIZE); | |
170 | } | |
171 | ||
172 | ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1); | |
173 | if (ret < 0) return ret; | |
174 | ||
175 | while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) { | |
176 | ret = pvr2_buffer_queue(bp); | |
177 | if (ret < 0) return ret; | |
178 | } | |
d8abe97d | 179 | |
a36416d0 MI |
180 | adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb"); |
181 | ||
182 | if (IS_ERR(adap->thread)) { | |
183 | ret = PTR_ERR(adap->thread); | |
d8abe97d | 184 | adap->thread = NULL; |
a36416d0 | 185 | return ret; |
d8abe97d MK |
186 | } |
187 | ||
a36416d0 | 188 | adap->stream_run = !0; |
d8abe97d | 189 | |
a36416d0 MI |
190 | return 0; |
191 | } | |
d8abe97d | 192 | |
a36416d0 MI |
193 | static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap) |
194 | { | |
195 | int ret = pvr2_dvb_stream_do_start(adap); | |
196 | if (ret < 0) pvr2_dvb_stream_end(adap); | |
197 | return ret; | |
198 | } | |
d8abe97d | 199 | |
a36416d0 MI |
200 | static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) |
201 | { | |
202 | struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; | |
203 | int ret = 0; | |
204 | ||
205 | if (adap == NULL) return -ENODEV; | |
206 | ||
207 | mutex_lock(&adap->lock); | |
208 | do { | |
209 | if (onoff) { | |
210 | if (!adap->feedcount) { | |
211 | printk(KERN_DEBUG "start feeding\n"); | |
212 | ret = pvr2_dvb_stream_start(adap); | |
213 | if (ret < 0) break; | |
214 | } | |
215 | (adap->feedcount)++; | |
216 | } else if (adap->feedcount > 0) { | |
217 | (adap->feedcount)--; | |
218 | if (!adap->feedcount) { | |
219 | printk(KERN_DEBUG "stop feeding\n"); | |
220 | pvr2_dvb_stream_end(adap); | |
221 | } | |
d8abe97d | 222 | } |
a36416d0 | 223 | } while (0); |
d8abe97d MK |
224 | mutex_unlock(&adap->lock); |
225 | ||
226 | return ret; | |
227 | } | |
228 | ||
04910bdc MK |
229 | static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) |
230 | { | |
231 | printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n", | |
232 | dvbdmxfeed->pid, dvbdmxfeed->type); | |
d8abe97d | 233 | return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); |
04910bdc MK |
234 | } |
235 | ||
236 | static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | |
237 | { | |
238 | printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n", | |
239 | dvbdmxfeed->pid, dvbdmxfeed->type); | |
d8abe97d | 240 | return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); |
04910bdc MK |
241 | } |
242 | ||
99443ae0 MK |
243 | static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) |
244 | { | |
245 | /* TO DO: This function will call into the core and request for | |
246 | * input to be set to 'dtv' if (acquire) and if it isn't set already. | |
247 | * | |
248 | * If (!acquire) then we should do nothing -- don't switch inputs | |
249 | * again unless the analog side of the driver requests the bus. | |
250 | */ | |
251 | return 0; | |
252 | } | |
253 | ||
04910bdc MK |
254 | static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) |
255 | { | |
256 | int ret; | |
257 | ||
258 | ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb", | |
259 | THIS_MODULE/*&hdw->usb_dev->owner*/, | |
a36416d0 | 260 | &adap->channel.hdw->usb_dev->dev, |
04910bdc MK |
261 | adapter_nr); |
262 | if (ret < 0) { | |
263 | err("dvb_register_adapter failed: error %d", ret); | |
264 | goto err; | |
265 | } | |
266 | adap->dvb_adap.priv = adap; | |
267 | ||
268 | adap->demux.dmx.capabilities = DMX_TS_FILTERING | | |
269 | DMX_SECTION_FILTERING | | |
270 | DMX_MEMORY_BASED_FILTERING; | |
271 | adap->demux.priv = adap; | |
272 | adap->demux.filternum = 256; | |
273 | adap->demux.feednum = 256; | |
274 | adap->demux.start_feed = pvr2_dvb_start_feed; | |
275 | adap->demux.stop_feed = pvr2_dvb_stop_feed; | |
276 | adap->demux.write_to_decoder = NULL; | |
277 | ||
278 | ret = dvb_dmx_init(&adap->demux); | |
279 | if (ret < 0) { | |
280 | err("dvb_dmx_init failed: error %d", ret); | |
281 | goto err_dmx; | |
282 | } | |
283 | ||
284 | adap->dmxdev.filternum = adap->demux.filternum; | |
285 | adap->dmxdev.demux = &adap->demux.dmx; | |
286 | adap->dmxdev.capabilities = 0; | |
287 | ||
288 | ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); | |
289 | if (ret < 0) { | |
290 | err("dvb_dmxdev_init failed: error %d", ret); | |
291 | goto err_dmx_dev; | |
292 | } | |
293 | ||
294 | dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); | |
295 | ||
04910bdc MK |
296 | return 0; |
297 | ||
298 | err_dmx_dev: | |
299 | dvb_dmx_release(&adap->demux); | |
300 | err_dmx: | |
301 | dvb_unregister_adapter(&adap->dvb_adap); | |
302 | err: | |
303 | return ret; | |
304 | } | |
305 | ||
306 | static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) | |
307 | { | |
7dcc48fb MI |
308 | printk(KERN_DEBUG "unregistering DVB devices\n"); |
309 | dvb_net_release(&adap->dvb_net); | |
310 | adap->demux.dmx.close(&adap->demux.dmx); | |
311 | dvb_dmxdev_release(&adap->dmxdev); | |
312 | dvb_dmx_release(&adap->demux); | |
313 | dvb_unregister_adapter(&adap->dvb_adap); | |
04910bdc MK |
314 | return 0; |
315 | } | |
316 | ||
317 | static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) | |
318 | { | |
a36416d0 | 319 | struct pvr2_hdw *hdw = adap->channel.hdw; |
bde316a4 MK |
320 | struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; |
321 | int ret; | |
04910bdc MK |
322 | |
323 | if (dvb_props == NULL) { | |
324 | err("fe_props not defined!"); | |
325 | return -EINVAL; | |
326 | } | |
327 | ||
bde316a4 MK |
328 | /* FIXME: This code should be moved into the core, |
329 | * and should only be called if we don't already have | |
330 | * control of the bus. | |
331 | * | |
332 | * We can't call "pvr2_dvb_bus_ctrl(adap->fe, 1)" from here, | |
333 | * because adap->fe isn't defined yet. | |
334 | */ | |
335 | ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_by_id(hdw, | |
336 | PVR2_CID_INPUT), | |
337 | PVR2_CVAL_INPUT_DTV); | |
338 | if (ret != 0) | |
339 | return ret; | |
340 | ||
341 | pvr2_hdw_commit_ctl(hdw); | |
342 | ||
343 | ||
04910bdc MK |
344 | if (dvb_props->frontend_attach == NULL) { |
345 | err("frontend_attach not defined!"); | |
346 | return -EINVAL; | |
347 | } | |
348 | ||
349 | if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) { | |
350 | ||
351 | if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) { | |
352 | err("frontend registration failed!"); | |
353 | dvb_frontend_detach(adap->fe); | |
354 | adap->fe = NULL; | |
355 | return -ENODEV; | |
356 | } | |
357 | ||
358 | if (dvb_props->tuner_attach) | |
359 | dvb_props->tuner_attach(adap); | |
360 | ||
361 | if (adap->fe->ops.analog_ops.standby) | |
362 | adap->fe->ops.analog_ops.standby(adap->fe); | |
363 | ||
99443ae0 MK |
364 | /* Ensure all frontends negotiate bus access */ |
365 | adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl; | |
366 | ||
04910bdc MK |
367 | } else { |
368 | err("no frontend was attached!"); | |
369 | return -ENODEV; | |
370 | } | |
371 | ||
372 | return 0; | |
373 | } | |
374 | ||
375 | static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) | |
376 | { | |
377 | if (adap->fe != NULL) { | |
378 | dvb_unregister_frontend(adap->fe); | |
379 | dvb_frontend_detach(adap->fe); | |
380 | } | |
381 | return 0; | |
382 | } | |
383 | ||
c5317b17 | 384 | static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap) |
891d99ef MI |
385 | { |
386 | pvr2_dvb_stream_end(adap); | |
387 | pvr2_dvb_frontend_exit(adap); | |
388 | pvr2_dvb_adapter_exit(adap); | |
389 | pvr2_channel_done(&adap->channel); | |
c5317b17 | 390 | kfree(adap); |
891d99ef MI |
391 | } |
392 | ||
393 | static void pvr2_dvb_internal_check(struct pvr2_channel *chp) | |
394 | { | |
395 | struct pvr2_dvb_adapter *adap; | |
396 | adap = container_of(chp, struct pvr2_dvb_adapter, channel); | |
397 | if (!adap->channel.mc_head->disconnect_flag) return; | |
c5317b17 | 398 | pvr2_dvb_destroy(adap); |
891d99ef MI |
399 | } |
400 | ||
c5317b17 | 401 | struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr) |
04910bdc MK |
402 | { |
403 | int ret = 0; | |
a36416d0 | 404 | struct pvr2_dvb_adapter *adap; |
129a2f5e MI |
405 | if (!pvr->hdw->hdw_desc->dvb_props) { |
406 | /* Device lacks a digital interface so don't set up | |
407 | the DVB side of the driver either. For now. */ | |
e6d11865 | 408 | return NULL; |
129a2f5e | 409 | } |
c5317b17 MI |
410 | adap = kzalloc(sizeof(*adap), GFP_KERNEL); |
411 | if (!adap) return adap; | |
a36416d0 | 412 | pvr2_channel_init(&adap->channel, pvr); |
891d99ef | 413 | adap->channel.check_func = pvr2_dvb_internal_check; |
a36416d0 | 414 | init_waitqueue_head(&adap->buffer_wait_data); |
c5317b17 MI |
415 | mutex_init(&adap->lock); |
416 | ret = pvr2_dvb_adapter_init(adap); | |
129a2f5e | 417 | if (ret < 0) goto fail1; |
c5317b17 | 418 | ret = pvr2_dvb_frontend_init(adap); |
129a2f5e | 419 | if (ret < 0) goto fail2; |
c5317b17 | 420 | return adap; |
129a2f5e MI |
421 | |
422 | fail2: | |
423 | pvr2_dvb_adapter_exit(adap); | |
424 | fail1: | |
891d99ef | 425 | pvr2_channel_done(&adap->channel); |
c5317b17 | 426 | return NULL; |
04910bdc MK |
427 | } |
428 |