blob: dd693a1980e808e3147fc02af23c8c901e176c58 [file] [log] [blame]
Michael Krufky04910bd2008-02-03 23:46:16 -03001/*
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
Michael Krufkyd8abe972008-02-03 23:55:07 -030021#include <linux/kthread.h>
Mike Iselybb8ce9d2008-02-04 00:00:19 -030022#include <linux/freezer.h>
Michael Krufky04910bd2008-02-03 23:46:16 -030023#include "dvbdev.h"
24#include "pvrusb2-hdw-internal.h"
25#include "pvrusb2-hdw.h"
Mike Iselybb8ce9d2008-02-04 00:00:19 -030026#include "pvrusb2-io.h"
Michael Krufky04910bd2008-02-03 23:46:16 -030027#include "pvrusb2-dvb.h"
28
29DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
30
Mike Iselybb8ce9d2008-02-04 00:00:19 -030031#define BUFFER_COUNT 32
32#define BUFFER_SIZE PAGE_ALIGN(0x4000)
33
34struct 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
42static void pvr2_dvb_notify(struct pvr2_dvb_fh *fhp)
43{
44 wake_up(&fhp->wait_data);
45}
46
47static 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
106cleanup:
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
121static 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
Mike Iselyceb43402008-02-06 04:24:51 -0300141static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300142{
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300143 struct pvr2_dvb_fh fh;
144 int ret;
145 unsigned int count;
146 struct pvr2_buffer *bp;
147
148 printk(KERN_DEBUG "dvb thread started\n");
149 set_freezable();
150
151 memset(&fh, 0, sizeof(fh));
152
153 ret = pvr2_dvb_fh_init(&fh, adap);
154 if (ret != 0)
155 return ret;
156
157 for (;;) {
158 if ((0 == adap->feedcount) || (kthread_should_stop()))
159 break;
160
161 /* Not sure about this... */
162 try_to_freeze();
163
164 bp = pvr2_stream_get_ready_buffer(fh.stream);
165 if (bp != NULL) {
166 count = pvr2_buffer_get_count(bp);
167 if (count) {
168 dvb_dmx_swfilter(
169 &adap->demux,
170 fh.buffer_storage[
171 pvr2_buffer_get_id(bp)],
172 count);
173 } else {
174 ret = pvr2_buffer_get_status(bp);
175 if (ret < 0)
176 break;
177 }
178 ret = pvr2_buffer_queue(bp);
179 if (ret < 0)
180 break;
181
182 /* Since we know we did something to a buffer,
183 just go back and try again. No point in
184 blocking unless we really ran out of
185 buffers to process. */
186 continue;
187 }
188
189
190 /* Wait until more buffers become available. */
191 ret = wait_event_interruptible(
192 fh.wait_data,
193 pvr2_stream_get_ready_count(fh.stream) > 0);
194 if (ret < 0)
195 break;
196 }
197
198 pvr2_dvb_fh_done(&fh);
199
200 /* If we get here and ret is < 0, then an error has occurred.
201 Probably would be a good idea to communicate that to DVB core... */
202
203 printk(KERN_DEBUG "dvb thread stopped\n");
204
Mike Iselyceb43402008-02-06 04:24:51 -0300205 return 0;
206}
207
208static int pvr2_dvb_feed_thread(void *data)
209{
210 int stat = pvr2_dvb_feed_func(data);
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300211 /* from videobuf-dvb.c: */
212 while (!kthread_should_stop()) {
213 set_current_state(TASK_INTERRUPTIBLE);
214 schedule();
215 }
Mike Iselyceb43402008-02-06 04:24:51 -0300216 return stat;
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300217}
218
Michael Krufkyd8abe972008-02-03 23:55:07 -0300219static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
220{
221 struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
222 int newfeedcount, ret = 0;
223
224 if (adap == NULL)
225 return -ENODEV;
226
227 mutex_lock(&adap->lock);
228 newfeedcount = adap->feedcount + (onoff ? 1 : -1);
229
230 if (newfeedcount == 0) {
231 printk(KERN_DEBUG "stop feeding\n");
232
233 ret = kthread_stop(adap->thread);
234 adap->thread = NULL;
235 }
236
237 adap->feedcount = newfeedcount;
238
239 if (adap->feedcount == onoff && adap->feedcount > 0) {
240 if (NULL != adap->thread)
241 goto fail;
242
243 printk(KERN_DEBUG "start feeding\n");
244
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300245 adap->thread = kthread_run(pvr2_dvb_feed_thread,
246 adap, "pvrusb2-dvb");
Michael Krufkyd8abe972008-02-03 23:55:07 -0300247 if (IS_ERR(adap->thread)) {
248 ret = PTR_ERR(adap->thread);
249 adap->thread = NULL;
250 }
251 //ret = newfeedcount;
252 }
253fail:
254 mutex_unlock(&adap->lock);
255
256 return ret;
257}
258
Michael Krufky04910bd2008-02-03 23:46:16 -0300259static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
260{
261 printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
262 dvbdmxfeed->pid, dvbdmxfeed->type);
Michael Krufkyd8abe972008-02-03 23:55:07 -0300263 return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
Michael Krufky04910bd2008-02-03 23:46:16 -0300264}
265
266static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
267{
268 printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
269 dvbdmxfeed->pid, dvbdmxfeed->type);
Michael Krufkyd8abe972008-02-03 23:55:07 -0300270 return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
Michael Krufky04910bd2008-02-03 23:46:16 -0300271}
272
Michael Krufky99443ae2008-02-03 23:48:09 -0300273static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
274{
275 /* TO DO: This function will call into the core and request for
276 * input to be set to 'dtv' if (acquire) and if it isn't set already.
277 *
278 * If (!acquire) then we should do nothing -- don't switch inputs
279 * again unless the analog side of the driver requests the bus.
280 */
281 return 0;
282}
283
Michael Krufky04910bd2008-02-03 23:46:16 -0300284static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
285{
286 int ret;
287
288 ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
289 THIS_MODULE/*&hdw->usb_dev->owner*/,
290 &adap->pvr->hdw->usb_dev->dev,
291 adapter_nr);
292 if (ret < 0) {
293 err("dvb_register_adapter failed: error %d", ret);
294 goto err;
295 }
296 adap->dvb_adap.priv = adap;
297
298 adap->demux.dmx.capabilities = DMX_TS_FILTERING |
299 DMX_SECTION_FILTERING |
300 DMX_MEMORY_BASED_FILTERING;
301 adap->demux.priv = adap;
302 adap->demux.filternum = 256;
303 adap->demux.feednum = 256;
304 adap->demux.start_feed = pvr2_dvb_start_feed;
305 adap->demux.stop_feed = pvr2_dvb_stop_feed;
306 adap->demux.write_to_decoder = NULL;
307
308 ret = dvb_dmx_init(&adap->demux);
309 if (ret < 0) {
310 err("dvb_dmx_init failed: error %d", ret);
311 goto err_dmx;
312 }
313
314 adap->dmxdev.filternum = adap->demux.filternum;
315 adap->dmxdev.demux = &adap->demux.dmx;
316 adap->dmxdev.capabilities = 0;
317
318 ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
319 if (ret < 0) {
320 err("dvb_dmxdev_init failed: error %d", ret);
321 goto err_dmx_dev;
322 }
323
324 dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
325
326 adap->digital_up = 1;
327
328 return 0;
329
330err_dmx_dev:
331 dvb_dmx_release(&adap->demux);
332err_dmx:
333 dvb_unregister_adapter(&adap->dvb_adap);
334err:
335 return ret;
336}
337
338static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
339{
340 if (adap->digital_up) {
341 printk(KERN_DEBUG "unregistering DVB devices\n");
342 dvb_net_release(&adap->dvb_net);
343 adap->demux.dmx.close(&adap->demux.dmx);
344 dvb_dmxdev_release(&adap->dmxdev);
345 dvb_dmx_release(&adap->demux);
346 dvb_unregister_adapter(&adap->dvb_adap);
347 adap->digital_up = 0;
348 }
349 return 0;
350}
351
352static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
353{
Michael Krufkybde316a2008-02-10 05:33:37 -0300354 struct pvr2_hdw *hdw = adap->pvr->hdw;
355 struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
356 int ret;
Michael Krufky04910bd2008-02-03 23:46:16 -0300357
358 if (dvb_props == NULL) {
359 err("fe_props not defined!");
360 return -EINVAL;
361 }
362
Michael Krufkybde316a2008-02-10 05:33:37 -0300363 /* FIXME: This code should be moved into the core,
364 * and should only be called if we don't already have
365 * control of the bus.
366 *
367 * We can't call "pvr2_dvb_bus_ctrl(adap->fe, 1)" from here,
368 * because adap->fe isn't defined yet.
369 */
370 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_by_id(hdw,
371 PVR2_CID_INPUT),
372 PVR2_CVAL_INPUT_DTV);
373 if (ret != 0)
374 return ret;
375
376 pvr2_hdw_commit_ctl(hdw);
377
378
Michael Krufky04910bd2008-02-03 23:46:16 -0300379 if (dvb_props->frontend_attach == NULL) {
380 err("frontend_attach not defined!");
381 return -EINVAL;
382 }
383
384 if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
385
386 if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
387 err("frontend registration failed!");
388 dvb_frontend_detach(adap->fe);
389 adap->fe = NULL;
390 return -ENODEV;
391 }
392
393 if (dvb_props->tuner_attach)
394 dvb_props->tuner_attach(adap);
395
396 if (adap->fe->ops.analog_ops.standby)
397 adap->fe->ops.analog_ops.standby(adap->fe);
398
Michael Krufky99443ae2008-02-03 23:48:09 -0300399 /* Ensure all frontends negotiate bus access */
400 adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
401
Michael Krufky04910bd2008-02-03 23:46:16 -0300402 } else {
403 err("no frontend was attached!");
404 return -ENODEV;
405 }
406
407 return 0;
408}
409
410static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
411{
412 if (adap->fe != NULL) {
413 dvb_unregister_frontend(adap->fe);
414 dvb_frontend_detach(adap->fe);
415 }
416 return 0;
417}
418
419int pvr2_dvb_init(struct pvr2_context *pvr)
420{
421 int ret = 0;
422
423 pvr->hdw->dvb.pvr = pvr;
Michael Krufkyd8abe972008-02-03 23:55:07 -0300424 mutex_init(&pvr->hdw->dvb.lock);
Michael Krufky04910bd2008-02-03 23:46:16 -0300425
426 ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb);
427 if (ret < 0)
428 goto fail;
429
430 ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb);
431fail:
432 return ret;
433}
434
435int pvr2_dvb_exit(struct pvr2_context *pvr)
436{
437 pvr2_dvb_frontend_exit(&pvr->hdw->dvb);
438 pvr2_dvb_adapter_exit(&pvr->hdw->dvb);
439
440 pvr->hdw->dvb.pvr = NULL;
441
442 return 0;
443}