2 * FireDTV driver (formerly known as FireSAT)
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
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.
13 #include <linux/bitops.h>
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/types.h>
22 #include <dvb_demux.h>
24 #include <dvb_frontend.h>
28 static int alloc_channel(struct firedtv
*fdtv
)
32 for (i
= 0; i
< 16; i
++)
33 if (!__test_and_set_bit(i
, &fdtv
->channel_active
))
38 static void collect_channels(struct firedtv
*fdtv
, int *pidc
, u16 pid
[])
42 for (i
= 0, n
= 0; i
< 16; i
++)
43 if (test_bit(i
, &fdtv
->channel_active
))
44 pid
[n
++] = fdtv
->channel_pid
[i
];
48 static inline void dealloc_channel(struct firedtv
*fdtv
, int i
)
50 __clear_bit(i
, &fdtv
->channel_active
);
53 int fdtv_start_feed(struct dvb_demux_feed
*dvbdmxfeed
)
55 struct firedtv
*fdtv
= dvbdmxfeed
->demux
->priv
;
59 switch (dvbdmxfeed
->type
) {
64 dev_err(fdtv
->device
, "can't start dmx feed: invalid type %u\n",
69 if (mutex_lock_interruptible(&fdtv
->demux_mutex
))
72 if (dvbdmxfeed
->type
== DMX_TYPE_TS
) {
73 switch (dvbdmxfeed
->pes_type
) {
76 case DMX_PES_TELETEXT
:
79 c
= alloc_channel(fdtv
);
83 "can't start dmx feed: invalid pes type %u\n",
84 dvbdmxfeed
->pes_type
);
89 c
= alloc_channel(fdtv
);
93 dev_err(fdtv
->device
, "can't start dmx feed: busy\n");
98 dvbdmxfeed
->priv
= (typeof(dvbdmxfeed
->priv
))(unsigned long)c
;
99 fdtv
->channel_pid
[c
] = dvbdmxfeed
->pid
;
100 collect_channels(fdtv
, &pidc
, pids
);
102 if (dvbdmxfeed
->pid
== 8192) {
103 ret
= avc_tuner_get_ts(fdtv
);
105 dealloc_channel(fdtv
, c
);
106 dev_err(fdtv
->device
, "can't get TS\n");
110 ret
= avc_tuner_set_pids(fdtv
, pidc
, pids
);
112 dealloc_channel(fdtv
, c
);
113 dev_err(fdtv
->device
, "can't set PIDs\n");
118 mutex_unlock(&fdtv
->demux_mutex
);
123 int fdtv_stop_feed(struct dvb_demux_feed
*dvbdmxfeed
)
125 struct dvb_demux
*demux
= dvbdmxfeed
->demux
;
126 struct firedtv
*fdtv
= demux
->priv
;
130 if (dvbdmxfeed
->type
== DMX_TYPE_TS
&&
131 !((dvbdmxfeed
->ts_type
& TS_PACKET
) &&
132 (demux
->dmx
.frontend
->source
!= DMX_MEMORY_FE
))) {
134 if (dvbdmxfeed
->ts_type
& TS_DECODER
) {
135 if (dvbdmxfeed
->pes_type
>= DMX_PES_OTHER
||
136 !demux
->pesfilter
[dvbdmxfeed
->pes_type
])
139 demux
->pids
[dvbdmxfeed
->pes_type
] |= 0x8000;
140 demux
->pesfilter
[dvbdmxfeed
->pes_type
] = NULL
;
143 if (!(dvbdmxfeed
->ts_type
& TS_DECODER
&&
144 dvbdmxfeed
->pes_type
< DMX_PES_OTHER
))
148 if (mutex_lock_interruptible(&fdtv
->demux_mutex
))
151 c
= (unsigned long)dvbdmxfeed
->priv
;
152 dealloc_channel(fdtv
, c
);
153 collect_channels(fdtv
, &pidc
, pids
);
155 ret
= avc_tuner_set_pids(fdtv
, pidc
, pids
);
157 mutex_unlock(&fdtv
->demux_mutex
);
162 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
164 int fdtv_dvb_register(struct firedtv
*fdtv
, const char *name
)
168 err
= dvb_register_adapter(&fdtv
->adapter
, name
,
169 THIS_MODULE
, fdtv
->device
, adapter_nr
);
173 /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
174 fdtv
->demux
.dmx
.capabilities
= 0;
176 fdtv
->demux
.priv
= fdtv
;
177 fdtv
->demux
.filternum
= 16;
178 fdtv
->demux
.feednum
= 16;
179 fdtv
->demux
.start_feed
= fdtv_start_feed
;
180 fdtv
->demux
.stop_feed
= fdtv_stop_feed
;
181 fdtv
->demux
.write_to_decoder
= NULL
;
183 err
= dvb_dmx_init(&fdtv
->demux
);
185 goto fail_unreg_adapter
;
187 fdtv
->dmxdev
.filternum
= 16;
188 fdtv
->dmxdev
.demux
= &fdtv
->demux
.dmx
;
189 fdtv
->dmxdev
.capabilities
= 0;
191 err
= dvb_dmxdev_init(&fdtv
->dmxdev
, &fdtv
->adapter
);
193 goto fail_dmx_release
;
195 fdtv
->frontend
.source
= DMX_FRONTEND_0
;
197 err
= fdtv
->demux
.dmx
.add_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
199 goto fail_dmxdev_release
;
201 err
= fdtv
->demux
.dmx
.connect_frontend(&fdtv
->demux
.dmx
,
204 goto fail_rem_frontend
;
206 err
= dvb_net_init(&fdtv
->adapter
, &fdtv
->dvbnet
, &fdtv
->demux
.dmx
);
208 goto fail_disconnect_frontend
;
210 fdtv_frontend_init(fdtv
, name
);
211 err
= dvb_register_frontend(&fdtv
->adapter
, &fdtv
->fe
);
213 goto fail_net_release
;
215 err
= fdtv_ca_register(fdtv
);
217 dev_info(fdtv
->device
,
218 "Conditional Access Module not enabled\n");
222 dvb_net_release(&fdtv
->dvbnet
);
223 fail_disconnect_frontend
:
224 fdtv
->demux
.dmx
.close(&fdtv
->demux
.dmx
);
226 fdtv
->demux
.dmx
.remove_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
228 dvb_dmxdev_release(&fdtv
->dmxdev
);
230 dvb_dmx_release(&fdtv
->demux
);
232 dvb_unregister_adapter(&fdtv
->adapter
);
234 dev_err(fdtv
->device
, "DVB initialization failed\n");
238 void fdtv_dvb_unregister(struct firedtv
*fdtv
)
240 fdtv_ca_release(fdtv
);
241 dvb_unregister_frontend(&fdtv
->fe
);
242 dvb_net_release(&fdtv
->dvbnet
);
243 fdtv
->demux
.dmx
.close(&fdtv
->demux
.dmx
);
244 fdtv
->demux
.dmx
.remove_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
245 dvb_dmxdev_release(&fdtv
->dmxdev
);
246 dvb_dmx_release(&fdtv
->demux
);
247 dvb_unregister_adapter(&fdtv
->adapter
);