V4L/DVB (7682): pvrusb2-dvb: finish up stream & buffer handling
[linux-2.6] / drivers / media / video / pvrusb2 / pvrusb2-dvb.c
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
21 #include <linux/kthread.h>
22 #include <linux/freezer.h>
23 #include "dvbdev.h"
24 #include "pvrusb2-hdw-internal.h"
25 #include "pvrusb2-hdw.h"
26 #include "pvrusb2-io.h"
27 #include "pvrusb2-dvb.h"
28
29 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
30
31 #define BUFFER_COUNT 32
32 #define BUFFER_SIZE PAGE_ALIGN(0x4000)
33
34 struct pvr2_dvb_fh {
35         struct pvr2_channel     channel;
36         struct pvr2_stream      *stream;
37         struct pvr2_dvb_adapter *adap;
38         wait_queue_head_t       wait_data;
39         char                    *buffer_storage[BUFFER_COUNT];
40 };
41
42 static void pvr2_dvb_notify(struct pvr2_dvb_fh *fhp)
43 {
44         wake_up(&fhp->wait_data);
45 }
46
47 static int pvr2_dvb_fh_init(struct pvr2_dvb_fh *fh,
48                             struct pvr2_dvb_adapter *adap)
49 {
50         struct pvr2_context *pvr = adap->pvr;
51         unsigned int idx;
52         int ret;
53         struct pvr2_buffer *bp;
54
55         init_waitqueue_head(&fh->wait_data);
56
57         fh->adap = adap;
58
59         pvr2_channel_init(&fh->channel, adap->pvr);
60
61         ret = pvr2_channel_claim_stream(&fh->channel, &pvr->video_stream);
62         /* somebody else already has the stream */
63         if (ret != 0)
64                 return ret;
65
66         fh->stream = pvr->video_stream.stream;
67
68         for (idx = 0; idx < BUFFER_COUNT; idx++) {
69                 fh->buffer_storage[idx] = kmalloc(BUFFER_SIZE, GFP_KERNEL);
70                 if (!(fh->buffer_storage[idx]))
71                         break;
72         }
73
74         if (idx < BUFFER_COUNT) {
75                 /* An allocation appears to have failed */
76                 ret = -ENOMEM;
77                 goto cleanup;
78         }
79
80         pvr2_stream_set_callback(pvr->video_stream.stream,
81                                  (pvr2_stream_callback) pvr2_dvb_notify, fh);
82
83         ret = pvr2_stream_set_buffer_count(fh->stream, BUFFER_COUNT);
84         if (ret < 0)
85                 return ret;
86
87         for (idx = 0; idx < BUFFER_COUNT; idx++) {
88                 bp = pvr2_stream_get_buffer(fh->stream, idx);
89                 pvr2_buffer_set_buffer(bp,
90                                        fh->buffer_storage[idx],
91                                        BUFFER_SIZE);
92         }
93
94         ret = pvr2_hdw_set_streaming(fh->channel.hdw, 1);
95         if (ret < 0)
96                 goto cleanup;
97
98         while ((bp = pvr2_stream_get_idle_buffer(fh->stream)) != 0) {
99                 ret = pvr2_buffer_queue(bp);
100                 if (ret < 0)
101                         goto cleanup;
102         }
103
104         return ret;
105
106 cleanup:
107         if (fh->stream)
108                 pvr2_stream_kill(fh->stream);
109
110         for (idx = 0; idx < BUFFER_COUNT; idx++) {
111                 if (!(fh->buffer_storage[idx]))
112                         continue;
113
114                 kfree(fh->buffer_storage[idx]);
115         }
116         pvr2_channel_done(&fh->channel);
117
118         return ret;
119 }
120
121 static void pvr2_dvb_fh_done(struct pvr2_dvb_fh *fh)
122 {
123         unsigned int idx;
124
125         pvr2_hdw_set_streaming(fh->channel.hdw, 0);
126
127         pvr2_stream_kill(fh->stream);
128
129 //      pvr2_channel_claim_stream(&fh->channel, NULL);
130
131         for (idx = 0; idx < BUFFER_COUNT; idx++) {
132                 if (!(fh->buffer_storage[idx]))
133                         continue;
134
135                 kfree(fh->buffer_storage[idx]);
136         }
137
138         pvr2_channel_done(&fh->channel);
139 }
140
141 static int pvr2_dvb_feed_thread(void *data)
142 {
143         struct pvr2_dvb_adapter *adap = data;
144         struct pvr2_dvb_fh fh;
145         int ret;
146         unsigned int count;
147         struct pvr2_buffer *bp;
148
149         printk(KERN_DEBUG "dvb thread started\n");
150         set_freezable();
151
152         memset(&fh, 0, sizeof(fh));
153
154         ret = pvr2_dvb_fh_init(&fh, adap);
155         if (ret != 0)
156                 return ret;
157
158         for (;;) {
159                 if ((0 == adap->feedcount) || (kthread_should_stop()))
160                         break;
161
162                 /* Not sure about this... */
163                 try_to_freeze();
164
165                 bp = pvr2_stream_get_ready_buffer(fh.stream);
166                 if (bp != NULL) {
167                         count = pvr2_buffer_get_count(bp);
168                         if (count) {
169                                 dvb_dmx_swfilter(
170                                         &adap->demux,
171                                         fh.buffer_storage[
172                                                 pvr2_buffer_get_id(bp)],
173                                         count);
174                         } else {
175                                 ret = pvr2_buffer_get_status(bp);
176                                 if (ret < 0)
177                                         break;
178                         }
179                         ret = pvr2_buffer_queue(bp);
180                         if (ret < 0)
181                                 break;
182
183                         /* Since we know we did something to a buffer,
184                            just go back and try again.  No point in
185                            blocking unless we really ran out of
186                            buffers to process. */
187                         continue;
188                 }
189
190
191                 /* Wait until more buffers become available. */
192                 ret = wait_event_interruptible(
193                         fh.wait_data,
194                         pvr2_stream_get_ready_count(fh.stream) > 0);
195                 if (ret < 0)
196                         break;
197         }
198
199         pvr2_dvb_fh_done(&fh);
200
201         /* If we get here and ret is < 0, then an error has occurred.
202            Probably would be a good idea to communicate that to DVB core... */
203
204         printk(KERN_DEBUG "dvb thread stopped\n");
205
206         /* from videobuf-dvb.c: */
207         while (!kthread_should_stop()) {
208                 set_current_state(TASK_INTERRUPTIBLE);
209                 schedule();
210         }
211         return 0;
212 }
213
214 static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
215 {
216         struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
217         int newfeedcount, ret = 0;
218
219         if (adap == NULL)
220                 return -ENODEV;
221
222         mutex_lock(&adap->lock);
223         newfeedcount = adap->feedcount + (onoff ? 1 : -1);
224
225         if (newfeedcount == 0) {
226                 printk(KERN_DEBUG "stop feeding\n");
227
228                 ret = kthread_stop(adap->thread);
229                 adap->thread = NULL;
230         }
231
232         adap->feedcount = newfeedcount;
233
234         if (adap->feedcount == onoff && adap->feedcount > 0) {
235                 if (NULL != adap->thread)
236                         goto fail;
237
238                 printk(KERN_DEBUG "start feeding\n");
239
240                 adap->thread = kthread_run(pvr2_dvb_feed_thread,
241                                            adap, "pvrusb2-dvb");
242                 if (IS_ERR(adap->thread)) {
243                         ret = PTR_ERR(adap->thread);
244                         adap->thread = NULL;
245                 }
246                 //ret = newfeedcount;
247         }
248 fail:
249         mutex_unlock(&adap->lock);
250
251         return ret;
252 }
253
254 static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
255 {
256         printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
257                dvbdmxfeed->pid, dvbdmxfeed->type);
258         return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
259 }
260
261 static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
262 {
263         printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
264                dvbdmxfeed->pid, dvbdmxfeed->type);
265         return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
266 }
267
268 static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
269 {
270         /* TO DO: This function will call into the core and request for
271          * input to be set to 'dtv' if (acquire) and if it isn't set already.
272          *
273          * If (!acquire) then we should do nothing -- don't switch inputs
274          * again unless the analog side of the driver requests the bus.
275          */
276         return 0;
277 }
278
279 static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
280 {
281         int ret;
282
283         ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
284                                    THIS_MODULE/*&hdw->usb_dev->owner*/,
285                                    &adap->pvr->hdw->usb_dev->dev,
286                                    adapter_nr);
287         if (ret < 0) {
288                 err("dvb_register_adapter failed: error %d", ret);
289                 goto err;
290         }
291         adap->dvb_adap.priv = adap;
292
293         adap->demux.dmx.capabilities = DMX_TS_FILTERING |
294                                        DMX_SECTION_FILTERING |
295                                        DMX_MEMORY_BASED_FILTERING;
296         adap->demux.priv             = adap;
297         adap->demux.filternum        = 256;
298         adap->demux.feednum          = 256;
299         adap->demux.start_feed       = pvr2_dvb_start_feed;
300         adap->demux.stop_feed        = pvr2_dvb_stop_feed;
301         adap->demux.write_to_decoder = NULL;
302
303         ret = dvb_dmx_init(&adap->demux);
304         if (ret < 0) {
305                 err("dvb_dmx_init failed: error %d", ret);
306                 goto err_dmx;
307         }
308
309         adap->dmxdev.filternum       = adap->demux.filternum;
310         adap->dmxdev.demux           = &adap->demux.dmx;
311         adap->dmxdev.capabilities    = 0;
312
313         ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
314         if (ret < 0) {
315                 err("dvb_dmxdev_init failed: error %d", ret);
316                 goto err_dmx_dev;
317         }
318
319         dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
320
321         adap->digital_up = 1;
322
323         return 0;
324
325 err_dmx_dev:
326         dvb_dmx_release(&adap->demux);
327 err_dmx:
328         dvb_unregister_adapter(&adap->dvb_adap);
329 err:
330         return ret;
331 }
332
333 static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
334 {
335         if (adap->digital_up) {
336                 printk(KERN_DEBUG "unregistering DVB devices\n");
337                 dvb_net_release(&adap->dvb_net);
338                 adap->demux.dmx.close(&adap->demux.dmx);
339                 dvb_dmxdev_release(&adap->dmxdev);
340                 dvb_dmx_release(&adap->demux);
341                 dvb_unregister_adapter(&adap->dvb_adap);
342                 adap->digital_up = 0;
343         }
344         return 0;
345 }
346
347 static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
348 {
349         struct pvr2_dvb_props *dvb_props = adap->pvr->hdw->hdw_desc->dvb_props;
350
351         if (dvb_props == NULL) {
352                 err("fe_props not defined!");
353                 return -EINVAL;
354         }
355
356         if (dvb_props->frontend_attach == NULL) {
357                 err("frontend_attach not defined!");
358                 return -EINVAL;
359         }
360
361         if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
362
363                 if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
364                         err("frontend registration failed!");
365                         dvb_frontend_detach(adap->fe);
366                         adap->fe = NULL;
367                         return -ENODEV;
368                 }
369
370                 if (dvb_props->tuner_attach)
371                         dvb_props->tuner_attach(adap);
372
373                 if (adap->fe->ops.analog_ops.standby)
374                         adap->fe->ops.analog_ops.standby(adap->fe);
375
376                 /* Ensure all frontends negotiate bus access */
377                 adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
378
379         } else {
380                 err("no frontend was attached!");
381                 return -ENODEV;
382         }
383
384         return 0;
385 }
386
387 static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
388 {
389         if (adap->fe != NULL) {
390                 dvb_unregister_frontend(adap->fe);
391                 dvb_frontend_detach(adap->fe);
392         }
393         return 0;
394 }
395
396 int pvr2_dvb_init(struct pvr2_context *pvr)
397 {
398         int ret = 0;
399
400         pvr->hdw->dvb.pvr = pvr;
401         mutex_init(&pvr->hdw->dvb.lock);
402
403         ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb);
404         if (ret < 0)
405                 goto fail;
406
407         ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb);
408 fail:
409         return ret;
410 }
411
412 int pvr2_dvb_exit(struct pvr2_context *pvr)
413 {
414         pvr2_dvb_frontend_exit(&pvr->hdw->dvb);
415         pvr2_dvb_adapter_exit(&pvr->hdw->dvb);
416
417         pvr->hdw->dvb.pvr = NULL;
418
419         return 0;
420 }