blob: bde85c9730583940cca430a4aa16045d402c52d2 [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
141static 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
Michael Krufkyd8abe972008-02-03 23:55:07 -0300214static 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
Mike Iselybb8ce9d2008-02-04 00:00:19 -0300240 adap->thread = kthread_run(pvr2_dvb_feed_thread,
241 adap, "pvrusb2-dvb");
Michael Krufkyd8abe972008-02-03 23:55:07 -0300242 if (IS_ERR(adap->thread)) {
243 ret = PTR_ERR(adap->thread);
244 adap->thread = NULL;
245 }
246 //ret = newfeedcount;
247 }
248fail:
249 mutex_unlock(&adap->lock);
250
251 return ret;
252}
253
Michael Krufky04910bd2008-02-03 23:46:16 -0300254static 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);
Michael Krufkyd8abe972008-02-03 23:55:07 -0300258 return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
Michael Krufky04910bd2008-02-03 23:46:16 -0300259}
260
261static 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);
Michael Krufkyd8abe972008-02-03 23:55:07 -0300265 return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
Michael Krufky04910bd2008-02-03 23:46:16 -0300266}
267
Michael Krufky99443ae2008-02-03 23:48:09 -0300268static 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
Michael Krufky04910bd2008-02-03 23:46:16 -0300279static 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
325err_dmx_dev:
326 dvb_dmx_release(&adap->demux);
327err_dmx:
328 dvb_unregister_adapter(&adap->dvb_adap);
329err:
330 return ret;
331}
332
333static 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
347static 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
Michael Krufky99443ae2008-02-03 23:48:09 -0300376 /* Ensure all frontends negotiate bus access */
377 adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
378
Michael Krufky04910bd2008-02-03 23:46:16 -0300379 } else {
380 err("no frontend was attached!");
381 return -ENODEV;
382 }
383
384 return 0;
385}
386
387static 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
396int pvr2_dvb_init(struct pvr2_context *pvr)
397{
398 int ret = 0;
399
400 pvr->hdw->dvb.pvr = pvr;
Michael Krufkyd8abe972008-02-03 23:55:07 -0300401 mutex_init(&pvr->hdw->dvb.lock);
Michael Krufky04910bd2008-02-03 23:46:16 -0300402
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);
408fail:
409 return ret;
410}
411
412int 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}