firedtv: massive refactoring
[pandora-kernel.git] / drivers / media / dvb / firewire / firedtv-dvb.c
1 /*
2  * FireDTV driver (formerly known as FireSAT)
3  *
4  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
6  *
7  *      This program is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU General Public License as
9  *      published by the Free Software Foundation; either version 2 of
10  *      the License, or (at your option) any later version.
11  */
12
13 #include <linux/bitops.h>
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/module.h>
19 #include <linux/mutex.h>
20 #include <linux/slab.h>
21 #include <linux/string.h>
22 #include <linux/types.h>
23 #include <linux/wait.h>
24 #include <linux/workqueue.h>
25
26 #include <dmxdev.h>
27 #include <dvb_demux.h>
28 #include <dvbdev.h>
29 #include <dvb_frontend.h>
30
31 #include "firedtv.h"
32
33 static int alloc_channel(struct firedtv *fdtv)
34 {
35         int i;
36
37         for (i = 0; i < 16; i++)
38                 if (!__test_and_set_bit(i, &fdtv->channel_active))
39                         break;
40         return i;
41 }
42
43 static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
44 {
45         int i, n;
46
47         for (i = 0, n = 0; i < 16; i++)
48                 if (test_bit(i, &fdtv->channel_active))
49                         pid[n++] = fdtv->channel_pid[i];
50         *pidc = n;
51 }
52
53 static inline void dealloc_channel(struct firedtv *fdtv, int i)
54 {
55         __clear_bit(i, &fdtv->channel_active);
56 }
57
58 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
59 {
60         struct firedtv *fdtv = dvbdmxfeed->demux->priv;
61         int pidc, c, ret;
62         u16 pids[16];
63
64         switch (dvbdmxfeed->type) {
65         case DMX_TYPE_TS:
66         case DMX_TYPE_SEC:
67                 break;
68         default:
69                 dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
70                         dvbdmxfeed->type);
71                 return -EINVAL;
72         }
73
74         if (mutex_lock_interruptible(&fdtv->demux_mutex))
75                 return -EINTR;
76
77         if (dvbdmxfeed->type == DMX_TYPE_TS) {
78                 switch (dvbdmxfeed->pes_type) {
79                 case DMX_TS_PES_VIDEO:
80                 case DMX_TS_PES_AUDIO:
81                 case DMX_TS_PES_TELETEXT:
82                 case DMX_TS_PES_PCR:
83                 case DMX_TS_PES_OTHER:
84                         c = alloc_channel(fdtv);
85                         break;
86                 default:
87                         dev_err(fdtv->device,
88                                 "can't start dmx feed: invalid pes type %u\n",
89                                 dvbdmxfeed->pes_type);
90                         ret = -EINVAL;
91                         goto out;
92                 }
93         } else {
94                 c = alloc_channel(fdtv);
95         }
96
97         if (c > 15) {
98                 dev_err(fdtv->device, "can't start dmx feed: busy\n");
99                 ret = -EBUSY;
100                 goto out;
101         }
102
103         dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
104         fdtv->channel_pid[c] = dvbdmxfeed->pid;
105         collect_channels(fdtv, &pidc, pids);
106
107         if (dvbdmxfeed->pid == 8192) {
108                 ret = avc_tuner_get_ts(fdtv);
109                 if (ret) {
110                         dealloc_channel(fdtv, c);
111                         dev_err(fdtv->device, "can't get TS\n");
112                         goto out;
113                 }
114         } else {
115                 ret = avc_tuner_set_pids(fdtv, pidc, pids);
116                 if (ret) {
117                         dealloc_channel(fdtv, c);
118                         dev_err(fdtv->device, "can't set PIDs\n");
119                         goto out;
120                 }
121         }
122 out:
123         mutex_unlock(&fdtv->demux_mutex);
124
125         return ret;
126 }
127
128 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
129 {
130         struct dvb_demux *demux = dvbdmxfeed->demux;
131         struct firedtv *fdtv = demux->priv;
132         int pidc, c, ret;
133         u16 pids[16];
134
135         if (dvbdmxfeed->type == DMX_TYPE_TS &&
136             !((dvbdmxfeed->ts_type & TS_PACKET) &&
137               (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
138
139                 if (dvbdmxfeed->ts_type & TS_DECODER) {
140                         if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
141                             !demux->pesfilter[dvbdmxfeed->pes_type])
142                                 return -EINVAL;
143
144                         demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
145                         demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
146                 }
147
148                 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
149                       dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
150                         return 0;
151         }
152
153         if (mutex_lock_interruptible(&fdtv->demux_mutex))
154                 return -EINTR;
155
156         c = (unsigned long)dvbdmxfeed->priv;
157         dealloc_channel(fdtv, c);
158         collect_channels(fdtv, &pidc, pids);
159
160         ret = avc_tuner_set_pids(fdtv, pidc, pids);
161
162         mutex_unlock(&fdtv->demux_mutex);
163
164         return ret;
165 }
166
167 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
168
169 int fdtv_dvb_register(struct firedtv *fdtv)
170 {
171         int err;
172
173         err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
174                                    THIS_MODULE, fdtv->device, adapter_nr);
175         if (err < 0)
176                 goto fail_log;
177
178         /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
179         fdtv->demux.dmx.capabilities = 0;
180
181         fdtv->demux.priv        = fdtv;
182         fdtv->demux.filternum   = 16;
183         fdtv->demux.feednum     = 16;
184         fdtv->demux.start_feed  = fdtv_start_feed;
185         fdtv->demux.stop_feed   = fdtv_stop_feed;
186         fdtv->demux.write_to_decoder = NULL;
187
188         err = dvb_dmx_init(&fdtv->demux);
189         if (err)
190                 goto fail_unreg_adapter;
191
192         fdtv->dmxdev.filternum    = 16;
193         fdtv->dmxdev.demux        = &fdtv->demux.dmx;
194         fdtv->dmxdev.capabilities = 0;
195
196         err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
197         if (err)
198                 goto fail_dmx_release;
199
200         fdtv->frontend.source = DMX_FRONTEND_0;
201
202         err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
203         if (err)
204                 goto fail_dmxdev_release;
205
206         err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
207                                                &fdtv->frontend);
208         if (err)
209                 goto fail_rem_frontend;
210
211         dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
212
213         fdtv_frontend_init(fdtv);
214         err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
215         if (err)
216                 goto fail_net_release;
217
218         err = fdtv_ca_register(fdtv);
219         if (err)
220                 dev_info(fdtv->device,
221                          "Conditional Access Module not enabled\n");
222         return 0;
223
224 fail_net_release:
225         dvb_net_release(&fdtv->dvbnet);
226         fdtv->demux.dmx.close(&fdtv->demux.dmx);
227 fail_rem_frontend:
228         fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
229 fail_dmxdev_release:
230         dvb_dmxdev_release(&fdtv->dmxdev);
231 fail_dmx_release:
232         dvb_dmx_release(&fdtv->demux);
233 fail_unreg_adapter:
234         dvb_unregister_adapter(&fdtv->adapter);
235 fail_log:
236         dev_err(fdtv->device, "DVB initialization failed\n");
237         return err;
238 }
239
240 void fdtv_dvb_unregister(struct firedtv *fdtv)
241 {
242         fdtv_ca_release(fdtv);
243         dvb_unregister_frontend(&fdtv->fe);
244         dvb_net_release(&fdtv->dvbnet);
245         fdtv->demux.dmx.close(&fdtv->demux.dmx);
246         fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
247         dvb_dmxdev_release(&fdtv->dmxdev);
248         dvb_dmx_release(&fdtv->demux);
249         dvb_unregister_adapter(&fdtv->adapter);
250 }
251
252 const char *fdtv_model_names[] = {
253         [FIREDTV_UNKNOWN] = "unknown type",
254         [FIREDTV_DVB_S]   = "FireDTV S/CI",
255         [FIREDTV_DVB_C]   = "FireDTV C/CI",
256         [FIREDTV_DVB_T]   = "FireDTV T/CI",
257         [FIREDTV_DVB_S2]  = "FireDTV S2  ",
258 };
259
260 struct firedtv *fdtv_alloc(struct device *dev,
261                            const struct firedtv_backend *backend,
262                            const char *name, size_t name_len)
263 {
264         struct firedtv *fdtv;
265         int i;
266
267         fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
268         if (!fdtv)
269                 return NULL;
270
271         dev->driver_data        = fdtv;
272         fdtv->device            = dev;
273         fdtv->isochannel        = -1;
274         fdtv->voltage           = 0xff;
275         fdtv->tone              = 0xff;
276         fdtv->backend           = backend;
277
278         mutex_init(&fdtv->avc_mutex);
279         init_waitqueue_head(&fdtv->avc_wait);
280         fdtv->avc_reply_received = true;
281         mutex_init(&fdtv->demux_mutex);
282         INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
283
284         for (i = ARRAY_SIZE(fdtv_model_names); --i; )
285                 if (strlen(fdtv_model_names[i]) <= name_len &&
286                     strncmp(name, fdtv_model_names[i], name_len) == 0)
287                         break;
288         fdtv->type = i;
289
290         return fdtv;
291 }
292
293 #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
294                      IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
295
296 #define DIGITAL_EVERYWHERE_OUI  0x001287
297 #define AVC_UNIT_SPEC_ID_ENTRY  0x00a02d
298 #define AVC_SW_VERSION_ENTRY    0x010001
299
300 static struct ieee1394_device_id fdtv_id_table[] = {
301         {
302                 /* FloppyDTV S/CI and FloppyDTV S2 */
303                 .match_flags    = MATCH_FLAGS,
304                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
305                 .model_id       = 0x000024,
306                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
307                 .version        = AVC_SW_VERSION_ENTRY,
308         }, {
309                 /* FloppyDTV T/CI */
310                 .match_flags    = MATCH_FLAGS,
311                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
312                 .model_id       = 0x000025,
313                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
314                 .version        = AVC_SW_VERSION_ENTRY,
315         }, {
316                 /* FloppyDTV C/CI */
317                 .match_flags    = MATCH_FLAGS,
318                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
319                 .model_id       = 0x000026,
320                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
321                 .version        = AVC_SW_VERSION_ENTRY,
322         }, {
323                 /* FireDTV S/CI and FloppyDTV S2 */
324                 .match_flags    = MATCH_FLAGS,
325                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
326                 .model_id       = 0x000034,
327                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
328                 .version        = AVC_SW_VERSION_ENTRY,
329         }, {
330                 /* FireDTV T/CI */
331                 .match_flags    = MATCH_FLAGS,
332                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
333                 .model_id       = 0x000035,
334                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
335                 .version        = AVC_SW_VERSION_ENTRY,
336         }, {
337                 /* FireDTV C/CI */
338                 .match_flags    = MATCH_FLAGS,
339                 .vendor_id      = DIGITAL_EVERYWHERE_OUI,
340                 .model_id       = 0x000036,
341                 .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
342                 .version        = AVC_SW_VERSION_ENTRY,
343         }, {}
344 };
345 MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
346
347 static int __init fdtv_init(void)
348 {
349         return fdtv_1394_init(fdtv_id_table);
350 }
351
352 static void __exit fdtv_exit(void)
353 {
354         fdtv_1394_exit();
355 }
356
357 module_init(fdtv_init);
358 module_exit(fdtv_exit);
359
360 MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
361 MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
362 MODULE_DESCRIPTION("FireDTV DVB Driver");
363 MODULE_LICENSE("GPL");
364 MODULE_SUPPORTED_DEVICE("FireDTV DVB");