aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-02-23 08:21:10 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-02-24 08:51:29 -0500
commit154907957f9391b1af997b57507b16c018cc4995 (patch)
treef9033e7dc29d5406e871b8102ba0b588d34b50ec
parenta70f81c1c0dac113ac4705e7701e2676e67905cd (diff)
firedtv: massive refactoring
Combination of the following changes: Mon, 23 Feb 2009 14:21:10 +0100 (CET) firedtv: reinstate debug logging option Henrik Kurelid tells me that FCP debug logging (which I removed during cleanups) is still useful when working on driver issues together with end users. So bring it back in an updated form with only 60% of the original code footprint. Logging can be enabled with # echo -1 > /sys/module/firedtv/parameters/debug 1 instead of -1 enables only FCP header logging, 2 instead of -1 enables only hexdumps of the entire FCP frames. 0 switches logging off again. Fri, 20 Feb 2009 20:54:27 +0100 (CET) firedtv: build fix for INPUT=m and DVB_FIREDTV=y Thu, 19 Feb 2009 20:40:39 +0100 firedtv: use msecs_to_jiffies Pointed out by Mauro Carvalho Chehab. Sun Feb 15 20:50:46 CET 2009 firedtv: some more housekeeping Fix an old checkpatch warning and a new compiler warning. Sun Feb 15 15:33:17 CET 2009 firedtv: rename a file once more At the moment, about a third of avc.c is specific to FireDTVs rather than generic AV/C code. Rename it to firedtv-avc.c. Sun Feb 15 15:33:17 CET 2009 firedtv: dvb demux: more compact channels backing store Replace struct firedtv_channel { bool active; int pid; } channel[16]; by unsigned long channel_active; u16 channel_pid[16];. Sun Feb 15 15:33:17 CET 2009 firedtv: dvb demux: some simplifications c->active was unnecessarily cleared twice. Also, by marking the channel inactive before the for loop, the loop becomes identical with fdtv_channel_collect(). Sun Feb 15 15:33:17 CET 2009 firedtv: dvb demux: remove a bogus loop This loop is unnecessary because - only active channel[].pid's will be sent to the device, - when a channel is activated, its pid is set to dvbdmxfeed->pid. Perhaps the original code was there because it was initially not fully covered by the fdtv->demux_mutex. Sun Feb 15 15:33:17 CET 2009 firedtv: dvb demux: fix mutex protection fdtv_start_feed() accessed the channel list unsafely. Fully serialize it with itself and fdtv_stop_feed(). Sun Feb 15 15:33:17 CET 2009 firedtv: dvb demux: fix missing braces Original code was: ... case DMX_TS_PES_OTHER: //Dirty fix to keep firesat->channel pid-list up to date for(k=0;k<16;k++){ if(firesat->channel[k].active == 0) firesat->channel[k].pid = dvbdmxfeed->pid; break; } channel = firesat_channel_allocate(firesat); break; default: ... Looks bogus in several respects. For now let's just add braces to the if because that seems to be what the author meant. Sun Feb 15 15:33:17 CET 2009 firedtv: allow build without input subsystem !CONFIG_INPUT is very unlikely on systems on which firedtv is of interest. But we can easily support it. Sun Feb 15 15:33:17 CET 2009 firedtv: replace EXTRA_CFLAGS by ccflags The former are deprecated. The latter can depend on Kconfig variables. Sun Feb 15 15:33:17 CET 2009 firedtv: concentrate ieee1394 dependencies Move the entire interface with drivers/ieee1394 to firedtv-1394.c. Move 1394-independent module initialization code to firedtv-dvb.c. This prepares interfacing with drivers/firewire. Sun Feb 15 15:33:17 CET 2009 firedtv: amend Kconfig menu prompt Sun Feb 15 15:33:17 CET 2009 firedtv: remove kernel version compatibility macro Sun Feb 15 15:33:17 CET 2009 firedtv: combine header files avc.h and firedtv-*.h are small and currently not shared with other drivers, hence concatenate them all into firedtv.h. Sun Feb 15 15:33:17 CET 2009 firedtv: misc style touch-ups Standardize on lower-case hexadecimal constants. Adjust whitespace. Omit unnecessary pointer type casts and an unnecessary list head initialization. Use dev_printk. Wed Feb 11 21:21:04 CET 2009 firedtv: avc, ci: remove unused constants Wed Feb 11 21:21:04 CET 2009 firedtv: avc: remove bitfields from read descriptor response operands Don't use bitfields in struct types of on-the-wire data. Wed Feb 11 21:21:04 CET 2009 firedtv: avc: remove bitfields from DSD command operands Don't use bitfields in struct types of on-the-wire data. Wed Feb 11 21:21:04 CET 2009 firedtv: avc: header file cleanup Remove unused constants and declarations. Move privately used constants into .c files. Wed Feb 11 21:21:04 CET 2009 firedtv: avc: remove bitfields from FCP frame types Don't use bitfields in struct types of on-the-wire data. Also move many privately used constants from avc.h to avc.c and remove some unused constants. Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: avc: fix offset in avc_tuner_get_ts The parentheses were wrong. It didn't matter though because this code only writes a 0 into an area which is already initialized to 0. Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: avc: reduce stack usage, remove two typedefs It is safe to share a memory buffer for command frame and response frame because the response data come in after the command frame was last used. Even less stack would be required if only the actual required frame size instead of the entire FCP register size was allocated. Also, rename the defined types AVCCmdFrm and AVCRspFrm to struct avc_command_frame and struct avc_response_frame. TODO: Remove the bitfields in these types. Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: cmp: move code to avc Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: iso: move code to firedtv-1394 Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: iso: remove unnecessary struct type definitions Sun, 18 Jan 2009 16:30:00 +0100 (CET) firedtv: iso: style changes and fixlets Add cleanup after failure in setup_iso_channel. Replace printk() by dv_err(). Decrease indentation level in rawiso_activity_cb(). Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/media/dvb/Kconfig2
-rw-r--r--drivers/media/dvb/firewire/Kconfig26
-rw-r--r--drivers/media/dvb/firewire/Makefile17
-rw-r--r--drivers/media/dvb/firewire/avc.c1051
-rw-r--r--drivers/media/dvb/firewire/avc.h432
-rw-r--r--drivers/media/dvb/firewire/cmp.c171
-rw-r--r--drivers/media/dvb/firewire/cmp.h9
-rw-r--r--drivers/media/dvb/firewire/firedtv-1394.c332
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c1315
-rw-r--r--drivers/media/dvb/firewire/firedtv-ci.c93
-rw-r--r--drivers/media/dvb/firewire/firedtv-ci.h9
-rw-r--r--drivers/media/dvb/firewire/firedtv-dvb.c328
-rw-r--r--drivers/media/dvb/firewire/firedtv-fe.c61
-rw-r--r--drivers/media/dvb/firewire/firedtv-iso.c111
-rw-r--r--drivers/media/dvb/firewire/firedtv-rc.c1
-rw-r--r--drivers/media/dvb/firewire/firedtv-rc.h11
-rw-r--r--drivers/media/dvb/firewire/firedtv.h257
17 files changed, 1895 insertions, 2331 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 5a74c5c62f15..b0198691892a 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -51,6 +51,8 @@ comment "Supported SDMC DM1105 Adapters"
51 depends on DVB_CORE && PCI && I2C 51 depends on DVB_CORE && PCI && I2C
52source "drivers/media/dvb/dm1105/Kconfig" 52source "drivers/media/dvb/dm1105/Kconfig"
53 53
54comment "Supported FireWire (IEEE 1394) Adapters"
55 depends on DVB_CORE && IEEE1394
54source "drivers/media/dvb/firewire/Kconfig" 56source "drivers/media/dvb/firewire/Kconfig"
55 57
56comment "Supported DVB Frontends" 58comment "Supported DVB Frontends"
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig
index 03d25ad10350..69028253e984 100644
--- a/drivers/media/dvb/firewire/Kconfig
+++ b/drivers/media/dvb/firewire/Kconfig
@@ -1,12 +1,22 @@
1config DVB_FIREDTV 1config DVB_FIREDTV
2 tristate "FireDTV (FireWire attached DVB receivers)" 2 tristate "FireDTV and FloppyDTV"
3 depends on DVB_CORE && IEEE1394 && INPUT 3 depends on DVB_CORE && IEEE1394
4 help 4 help
5 Support for DVB receivers from Digital Everywhere, known as FireDTV 5 Support for DVB receivers from Digital Everywhere
6 and FloppyDTV, which are connected via IEEE 1394 (FireWire). 6 which are connected via IEEE 1394 (FireWire).
7 7
8 These devices don't have an MPEG decoder built in, so you need 8 These devices don't have an MPEG decoder built in,
9 an external software decoder to watch TV. 9 so you need an external software decoder to watch TV.
10 10
11 To compile this driver as a module, say M here: the module will be 11 To compile this driver as a module, say M here:
12 called firedtv. 12 the module will be called firedtv.
13
14if DVB_FIREDTV
15
16config DVB_FIREDTV_IEEE1394
17 def_bool IEEE1394
18
19config DVB_FIREDTV_INPUT
20 def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
21
22endif # DVB_FIREDTV
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile
index 628dacd10daf..2034695ba194 100644
--- a/drivers/media/dvb/firewire/Makefile
+++ b/drivers/media/dvb/firewire/Makefile
@@ -1,13 +1,8 @@
1firedtv-objs := firedtv-1394.o \
2 firedtv-dvb.o \
3 firedtv-fe.o \
4 firedtv-iso.o \
5 avc.o \
6 cmp.o \
7 firedtv-rc.o \
8 firedtv-ci.o
9
10obj-$(CONFIG_DVB_FIREDTV) += firedtv.o 1obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
11 2
12EXTRA_CFLAGS := -Idrivers/ieee1394 3firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
13EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core 4firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
5firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o
6
7ccflags-y += -Idrivers/media/dvb/dvb-core
8ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
diff --git a/drivers/media/dvb/firewire/avc.c b/drivers/media/dvb/firewire/avc.c
deleted file mode 100644
index 847a537b1f58..000000000000
--- a/drivers/media/dvb/firewire/avc.c
+++ /dev/null
@@ -1,1051 +0,0 @@
1/*
2 * FireDTV driver (formerly known as FireSAT)
3 *
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 */
13
14#include <linux/bug.h>
15#include <linux/crc32.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/kernel.h>
19#include <linux/moduleparam.h>
20#include <linux/mutex.h>
21#include <linux/string.h>
22#include <linux/wait.h>
23#include <linux/workqueue.h>
24
25#include <ieee1394_transactions.h>
26#include <nodemgr.h>
27
28#include "avc.h"
29#include "firedtv.h"
30#include "firedtv-rc.h"
31
32#define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
33
34static int __avc_write(struct firedtv *fdtv,
35 const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
36{
37 int err, retry;
38
39 if (RspFrm)
40 fdtv->avc_reply_received = false;
41
42 for (retry = 0; retry < 6; retry++) {
43 err = hpsb_node_write(fdtv->ud->ne, FCP_COMMAND_REGISTER,
44 (quadlet_t *)CmdFrm, CmdFrm->length);
45 if (err) {
46 fdtv->avc_reply_received = true;
47 dev_err(&fdtv->ud->device,
48 "FCP command write failed\n");
49 return err;
50 }
51
52 if (!RspFrm)
53 return 0;
54
55 /*
56 * AV/C specs say that answers should be sent within 150 ms.
57 * Time out after 200 ms.
58 */
59 if (wait_event_timeout(fdtv->avc_wait,
60 fdtv->avc_reply_received,
61 HZ / 5) != 0) {
62 memcpy(RspFrm, fdtv->respfrm, fdtv->resp_length);
63 RspFrm->length = fdtv->resp_length;
64
65 return 0;
66 }
67 }
68 dev_err(&fdtv->ud->device, "FCP response timed out\n");
69 return -ETIMEDOUT;
70}
71
72static int avc_write(struct firedtv *fdtv,
73 const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
74{
75 int ret;
76
77 if (mutex_lock_interruptible(&fdtv->avc_mutex))
78 return -EINTR;
79
80 ret = __avc_write(fdtv, CmdFrm, RspFrm);
81
82 mutex_unlock(&fdtv->avc_mutex);
83 return ret;
84}
85
86int avc_recv(struct firedtv *fdtv, u8 *data, size_t length)
87{
88 AVCRspFrm *RspFrm = (AVCRspFrm *)data;
89
90 if (length >= 8 &&
91 RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
92 RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
93 RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
94 RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
95 if (RspFrm->resp == CHANGED) {
96 fdtv_handle_rc(fdtv,
97 RspFrm->operand[4] << 8 | RspFrm->operand[5]);
98 schedule_work(&fdtv->remote_ctrl_work);
99 } else if (RspFrm->resp != INTERIM) {
100 dev_info(&fdtv->ud->device,
101 "remote control result = %d\n", RspFrm->resp);
102 }
103 return 0;
104 }
105
106 if (fdtv->avc_reply_received) {
107 dev_err(&fdtv->ud->device,
108 "received out-of-order AVC response, ignored\n");
109 return -EIO;
110 }
111
112 memcpy(fdtv->respfrm, data, length);
113 fdtv->resp_length = length;
114
115 fdtv->avc_reply_received = true;
116 wake_up(&fdtv->avc_wait);
117
118 return 0;
119}
120
121/*
122 * tuning command for setting the relative LNB frequency
123 * (not supported by the AVC standard)
124 */
125static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
126 struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm)
127{
128 CmdFrm->opcode = VENDOR;
129
130 CmdFrm->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
131 CmdFrm->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
132 CmdFrm->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
133 CmdFrm->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
134
135 CmdFrm->operand[4] = (params->frequency >> 24) & 0xff;
136 CmdFrm->operand[5] = (params->frequency >> 16) & 0xff;
137 CmdFrm->operand[6] = (params->frequency >> 8) & 0xff;
138 CmdFrm->operand[7] = params->frequency & 0xff;
139
140 CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
141 CmdFrm->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
142
143 switch(params->u.qpsk.fec_inner) {
144 case FEC_1_2:
145 CmdFrm->operand[10] = 0x1; break;
146 case FEC_2_3:
147 CmdFrm->operand[10] = 0x2; break;
148 case FEC_3_4:
149 CmdFrm->operand[10] = 0x3; break;
150 case FEC_5_6:
151 CmdFrm->operand[10] = 0x4; break;
152 case FEC_7_8:
153 CmdFrm->operand[10] = 0x5; break;
154 case FEC_4_5:
155 case FEC_8_9:
156 case FEC_AUTO:
157 default:
158 CmdFrm->operand[10] = 0x0;
159 }
160
161 if (fdtv->voltage == 0xff)
162 CmdFrm->operand[11] = 0xff;
163 else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
164 CmdFrm->operand[11] = 0;
165 else
166 CmdFrm->operand[11] = 1;
167
168 if (fdtv->tone == 0xff)
169 CmdFrm->operand[12] = 0xff;
170 else if (fdtv->tone == SEC_TONE_ON) /* band */
171 CmdFrm->operand[12] = 1;
172 else
173 CmdFrm->operand[12] = 0;
174
175 if (fdtv->type == FIREDTV_DVB_S2) {
176 CmdFrm->operand[13] = 0x1;
177 CmdFrm->operand[14] = 0xff;
178 CmdFrm->operand[15] = 0xff;
179 CmdFrm->length = 20;
180 } else {
181 CmdFrm->length = 16;
182 }
183}
184
185static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
186 AVCCmdFrm *CmdFrm)
187{
188 M_VALID_FLAGS flags;
189
190 flags.Bits.Modulation = params->u.qam.modulation != QAM_AUTO;
191 flags.Bits.FEC_inner = params->u.qam.fec_inner != FEC_AUTO;
192 flags.Bits.FEC_outer = 0;
193 flags.Bits.Symbol_Rate = 1;
194 flags.Bits.Frequency = 1;
195 flags.Bits.Orbital_Pos = 0;
196 flags.Bits.Polarisation = 0;
197 flags.Bits.reserved_fields = 0;
198 flags.Bits.reserved1 = 0;
199 flags.Bits.Network_ID = 0;
200
201 CmdFrm->opcode = DSD;
202
203 CmdFrm->operand[0] = 0; /* source plug */
204 CmdFrm->operand[1] = 0xd2; /* subfunction replace */
205 CmdFrm->operand[2] = 0x20; /* system id = DVB */
206 CmdFrm->operand[3] = 0x00; /* antenna number */
207 /* system_specific_multiplex selection_length */
208 CmdFrm->operand[4] = 0x11;
209 CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */
210 CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */
211 CmdFrm->operand[7] = 0x00;
212 CmdFrm->operand[8] = 0x00;
213 CmdFrm->operand[9] = 0x00;
214 CmdFrm->operand[10] = 0x00;
215
216 CmdFrm->operand[11] =
217 (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
218 CmdFrm->operand[12] =
219 ((params->frequency / 4000) >> 8) & 0xff;
220 CmdFrm->operand[13] = (params->frequency / 4000) & 0xff;
221 CmdFrm->operand[14] =
222 ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
223 CmdFrm->operand[15] =
224 ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
225 CmdFrm->operand[16] =
226 ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
227 CmdFrm->operand[17] = 0x00;
228
229 switch (params->u.qpsk.fec_inner) {
230 case FEC_1_2:
231 CmdFrm->operand[18] = 0x1; break;
232 case FEC_2_3:
233 CmdFrm->operand[18] = 0x2; break;
234 case FEC_3_4:
235 CmdFrm->operand[18] = 0x3; break;
236 case FEC_5_6:
237 CmdFrm->operand[18] = 0x4; break;
238 case FEC_7_8:
239 CmdFrm->operand[18] = 0x5; break;
240 case FEC_8_9:
241 CmdFrm->operand[18] = 0x6; break;
242 case FEC_4_5:
243 CmdFrm->operand[18] = 0x8; break;
244 case FEC_AUTO:
245 default:
246 CmdFrm->operand[18] = 0x0;
247 }
248 switch (params->u.qam.modulation) {
249 case QAM_16:
250 CmdFrm->operand[19] = 0x08; break;
251 case QAM_32:
252 CmdFrm->operand[19] = 0x10; break;
253 case QAM_64:
254 CmdFrm->operand[19] = 0x18; break;
255 case QAM_128:
256 CmdFrm->operand[19] = 0x20; break;
257 case QAM_256:
258 CmdFrm->operand[19] = 0x28; break;
259 case QAM_AUTO:
260 default:
261 CmdFrm->operand[19] = 0x00;
262 }
263 CmdFrm->operand[20] = 0x00;
264 CmdFrm->operand[21] = 0x00;
265 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
266 CmdFrm->operand[22] = 0x00;
267
268 CmdFrm->length = 28;
269}
270
271static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
272 AVCCmdFrm *CmdFrm)
273{
274 M_VALID_FLAGS flags;
275
276 flags.Bits_T.GuardInterval =
277 params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO;
278 flags.Bits_T.CodeRateLPStream =
279 params->u.ofdm.code_rate_LP != FEC_AUTO;
280 flags.Bits_T.CodeRateHPStream =
281 params->u.ofdm.code_rate_HP != FEC_AUTO;
282 flags.Bits_T.HierarchyInfo =
283 params->u.ofdm.hierarchy_information != HIERARCHY_AUTO;
284 flags.Bits_T.Constellation =
285 params->u.ofdm.constellation != QAM_AUTO;
286 flags.Bits_T.Bandwidth =
287 params->u.ofdm.bandwidth != BANDWIDTH_AUTO;
288 flags.Bits_T.CenterFrequency = 1;
289 flags.Bits_T.reserved1 = 0;
290 flags.Bits_T.reserved2 = 0;
291 flags.Bits_T.OtherFrequencyFlag = 0;
292 flags.Bits_T.TransmissionMode =
293 params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO;
294 flags.Bits_T.NetworkId = 0;
295
296 CmdFrm->opcode = DSD;
297
298 CmdFrm->operand[0] = 0; /* source plug */
299 CmdFrm->operand[1] = 0xd2; /* subfunction replace */
300 CmdFrm->operand[2] = 0x20; /* system id = DVB */
301 CmdFrm->operand[3] = 0x00; /* antenna number */
302 /* system_specific_multiplex selection_length */
303 CmdFrm->operand[4] = 0x0c;
304 CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */
305 CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */
306 CmdFrm->operand[7] = 0x0;
307 CmdFrm->operand[8] = (params->frequency / 10) >> 24;
308 CmdFrm->operand[9] = ((params->frequency / 10) >> 16) & 0xff;
309 CmdFrm->operand[10] = ((params->frequency / 10) >> 8) & 0xff;
310 CmdFrm->operand[11] = (params->frequency / 10) & 0xff;
311
312 switch (params->u.ofdm.bandwidth) {
313 case BANDWIDTH_7_MHZ:
314 CmdFrm->operand[12] = 0x20; break;
315 case BANDWIDTH_8_MHZ:
316 case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
317 case BANDWIDTH_AUTO:
318 default:
319 CmdFrm->operand[12] = 0x00;
320 }
321 switch (params->u.ofdm.constellation) {
322 case QAM_16:
323 CmdFrm->operand[13] = 1 << 6; break;
324 case QAM_64:
325 CmdFrm->operand[13] = 2 << 6; break;
326 case QPSK:
327 default:
328 CmdFrm->operand[13] = 0x00;
329 }
330 switch (params->u.ofdm.hierarchy_information) {
331 case HIERARCHY_1:
332 CmdFrm->operand[13] |= 1 << 3; break;
333 case HIERARCHY_2:
334 CmdFrm->operand[13] |= 2 << 3; break;
335 case HIERARCHY_4:
336 CmdFrm->operand[13] |= 3 << 3; break;
337 case HIERARCHY_AUTO:
338 case HIERARCHY_NONE:
339 default:
340 break;
341 }
342 switch (params->u.ofdm.code_rate_HP) {
343 case FEC_2_3:
344 CmdFrm->operand[13] |= 1; break;
345 case FEC_3_4:
346 CmdFrm->operand[13] |= 2; break;
347 case FEC_5_6:
348 CmdFrm->operand[13] |= 3; break;
349 case FEC_7_8:
350 CmdFrm->operand[13] |= 4; break;
351 case FEC_1_2:
352 default:
353 break;
354 }
355 switch (params->u.ofdm.code_rate_LP) {
356 case FEC_2_3:
357 CmdFrm->operand[14] = 1 << 5; break;
358 case FEC_3_4:
359 CmdFrm->operand[14] = 2 << 5; break;
360 case FEC_5_6:
361 CmdFrm->operand[14] = 3 << 5; break;
362 case FEC_7_8:
363 CmdFrm->operand[14] = 4 << 5; break;
364 case FEC_1_2:
365 default:
366 CmdFrm->operand[14] = 0x00; break;
367 }
368 switch (params->u.ofdm.guard_interval) {
369 case GUARD_INTERVAL_1_16:
370 CmdFrm->operand[14] |= 1 << 3; break;
371 case GUARD_INTERVAL_1_8:
372 CmdFrm->operand[14] |= 2 << 3; break;
373 case GUARD_INTERVAL_1_4:
374 CmdFrm->operand[14] |= 3 << 3; break;
375 case GUARD_INTERVAL_1_32:
376 case GUARD_INTERVAL_AUTO:
377 default:
378 break;
379 }
380 switch (params->u.ofdm.transmission_mode) {
381 case TRANSMISSION_MODE_8K:
382 CmdFrm->operand[14] |= 1 << 1; break;
383 case TRANSMISSION_MODE_2K:
384 case TRANSMISSION_MODE_AUTO:
385 default:
386 break;
387 }
388
389 CmdFrm->operand[15] = 0x00; /* network_ID[0] */
390 CmdFrm->operand[16] = 0x00; /* network_ID[1] */
391 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
392 CmdFrm->operand[17] = 0x00;
393
394 CmdFrm->length = 24;
395}
396
397int avc_tuner_dsd(struct firedtv *fdtv,
398 struct dvb_frontend_parameters *params)
399{
400 AVCCmdFrm CmdFrm;
401 AVCRspFrm RspFrm;
402
403 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
404
405 CmdFrm.cts = AVC;
406 CmdFrm.ctype = CONTROL;
407 CmdFrm.sutyp = 0x5;
408 CmdFrm.suid = fdtv->subunit;
409
410 switch (fdtv->type) {
411 case FIREDTV_DVB_S:
412 case FIREDTV_DVB_S2:
413 avc_tuner_tuneqpsk(fdtv, params, &CmdFrm); break;
414 case FIREDTV_DVB_C:
415 avc_tuner_dsd_dvb_c(params, &CmdFrm); break;
416 case FIREDTV_DVB_T:
417 avc_tuner_dsd_dvb_t(params, &CmdFrm); break;
418 default:
419 BUG();
420 }
421
422 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
423 return -EIO;
424
425 msleep(500);
426#if 0
427 /* FIXME: */
428 /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
429 if(status)
430 *status=RspFrm.operand[2];
431#endif
432 return 0;
433}
434
435int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
436{
437 AVCCmdFrm CmdFrm;
438 AVCRspFrm RspFrm;
439 int pos, k;
440
441 if (pidc > 16 && pidc != 0xff)
442 return -EINVAL;
443
444 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
445
446 CmdFrm.cts = AVC;
447 CmdFrm.ctype = CONTROL;
448 CmdFrm.sutyp = 0x5;
449 CmdFrm.suid = fdtv->subunit;
450 CmdFrm.opcode = DSD;
451
452 CmdFrm.operand[0] = 0; // source plug
453 CmdFrm.operand[1] = 0xD2; // subfunction replace
454 CmdFrm.operand[2] = 0x20; // system id = DVB
455 CmdFrm.operand[3] = 0x00; // antenna number
456 CmdFrm.operand[4] = 0x00; // system_specific_multiplex selection_length
457 CmdFrm.operand[5] = pidc; // Nr_of_dsd_sel_specs
458
459 pos = 6;
460 if (pidc != 0xff)
461 for (k = 0; k < pidc; k++) {
462 CmdFrm.operand[pos++] = 0x13; // flowfunction relay
463 CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
464 CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
465 CmdFrm.operand[pos++] = pid[k] & 0xFF;
466 CmdFrm.operand[pos++] = 0x00; // tableID
467 CmdFrm.operand[pos++] = 0x00; // filter_length
468 }
469
470 CmdFrm.length = ALIGN(3 + pos, 4);
471
472 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
473 return -EIO;
474
475 msleep(50);
476 return 0;
477}
478
479int avc_tuner_get_ts(struct firedtv *fdtv)
480{
481 AVCCmdFrm CmdFrm;
482 AVCRspFrm RspFrm;
483
484 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
485
486 CmdFrm.cts = AVC;
487 CmdFrm.ctype = CONTROL;
488 CmdFrm.sutyp = 0x5;
489 CmdFrm.suid = fdtv->subunit;
490 CmdFrm.opcode = DSIT;
491
492 CmdFrm.operand[0] = 0; // source plug
493 CmdFrm.operand[1] = 0xD2; // subfunction replace
494 CmdFrm.operand[2] = 0xFF; //status
495 CmdFrm.operand[3] = 0x20; // system id = DVB
496 CmdFrm.operand[4] = 0x00; // antenna number
497 CmdFrm.operand[5] = 0x0; // system_specific_search_flags
498 CmdFrm.operand[6] = (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
499 CmdFrm.operand[7] = 0x00; // valid_flags [0]
500 CmdFrm.operand[8] = 0x00; // valid_flags [1]
501 CmdFrm.operand[7 + (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0)
502
503 CmdFrm.length = (fdtv->type == FIREDTV_DVB_T)?24:28;
504
505 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
506 return -EIO;
507
508 msleep(250);
509 return 0;
510}
511
512int avc_identify_subunit(struct firedtv *fdtv)
513{
514 AVCCmdFrm CmdFrm;
515 AVCRspFrm RspFrm;
516
517 memset(&CmdFrm,0,sizeof(AVCCmdFrm));
518
519 CmdFrm.cts = AVC;
520 CmdFrm.ctype = CONTROL;
521 CmdFrm.sutyp = 0x5; // tuner
522 CmdFrm.suid = fdtv->subunit;
523 CmdFrm.opcode = READ_DESCRIPTOR;
524
525 CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
526 CmdFrm.operand[1]=0xff;
527 CmdFrm.operand[2]=0x00;
528 CmdFrm.operand[3]=0x00; // length highbyte
529 CmdFrm.operand[4]=0x08; // length lowbyte
530 CmdFrm.operand[5]=0x00; // offset highbyte
531 CmdFrm.operand[6]=0x0d; // offset lowbyte
532
533 CmdFrm.length=12;
534
535 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
536 return -EIO;
537
538 if ((RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) ||
539 (RspFrm.operand[3] << 8) + RspFrm.operand[4] != 8) {
540 dev_err(&fdtv->ud->device,
541 "cannot read subunit identifier\n");
542 return -EINVAL;
543 }
544 return 0;
545}
546
547int avc_tuner_status(struct firedtv *fdtv,
548 ANTENNA_INPUT_INFO *antenna_input_info)
549{
550 AVCCmdFrm CmdFrm;
551 AVCRspFrm RspFrm;
552 int length;
553
554 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
555
556 CmdFrm.cts=AVC;
557 CmdFrm.ctype=CONTROL;
558 CmdFrm.sutyp=0x05; // tuner
559 CmdFrm.suid=fdtv->subunit;
560 CmdFrm.opcode=READ_DESCRIPTOR;
561
562 CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
563 CmdFrm.operand[1]=0xff; //read_result_status
564 CmdFrm.operand[2]=0x00; // reserver
565 CmdFrm.operand[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8;
566 CmdFrm.operand[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF;
567 CmdFrm.operand[5]=0x00;
568 CmdFrm.operand[6]=0x00;
569 CmdFrm.length=12;
570
571 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
572 return -EIO;
573
574 if (RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
575 dev_err(&fdtv->ud->device, "cannot read tuner status\n");
576 return -EINVAL;
577 }
578
579 length = RspFrm.operand[9];
580 if (RspFrm.operand[1] != 0x10 || length != sizeof(ANTENNA_INPUT_INFO)) {
581 dev_err(&fdtv->ud->device, "got invalid tuner status\n");
582 return -EINVAL;
583 }
584
585 memcpy(antenna_input_info, &RspFrm.operand[10], length);
586 return 0;
587}
588
589int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
590 char conttone, char nrdiseq,
591 struct dvb_diseqc_master_cmd *diseqcmd)
592{
593 AVCCmdFrm CmdFrm;
594 AVCRspFrm RspFrm;
595 int i, j, k;
596
597 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
598
599 CmdFrm.cts=AVC;
600 CmdFrm.ctype=CONTROL;
601 CmdFrm.sutyp=0x05;
602 CmdFrm.suid=fdtv->subunit;
603 CmdFrm.opcode=VENDOR;
604
605 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
606 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
607 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
608 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
609
610 CmdFrm.operand[4]=voltage;
611 CmdFrm.operand[5]=nrdiseq;
612
613 i=6;
614
615 for (j = 0; j < nrdiseq; j++) {
616 CmdFrm.operand[i++] = diseqcmd[j].msg_len;
617
618 for (k = 0; k < diseqcmd[j].msg_len; k++)
619 CmdFrm.operand[i++] = diseqcmd[j].msg[k];
620 }
621
622 CmdFrm.operand[i++]=burst;
623 CmdFrm.operand[i++]=conttone;
624
625 CmdFrm.length = ALIGN(3 + i, 4);
626
627 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
628 return -EIO;
629
630 if (RspFrm.resp != ACCEPTED) {
631 dev_err(&fdtv->ud->device, "LNB control failed\n");
632 return -EINVAL;
633 }
634
635 return 0;
636}
637
638int avc_register_remote_control(struct firedtv *fdtv)
639{
640 AVCCmdFrm CmdFrm;
641
642 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
643
644 CmdFrm.cts = AVC;
645 CmdFrm.ctype = NOTIFY;
646 CmdFrm.sutyp = 0x1f;
647 CmdFrm.suid = 0x7;
648 CmdFrm.opcode = VENDOR;
649
650 CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
651 CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
652 CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
653 CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
654
655 CmdFrm.length = 8;
656
657 return avc_write(fdtv, &CmdFrm, NULL);
658}
659
660void avc_remote_ctrl_work(struct work_struct *work)
661{
662 struct firedtv *fdtv =
663 container_of(work, struct firedtv, remote_ctrl_work);
664
665 /* Should it be rescheduled in failure cases? */
666 avc_register_remote_control(fdtv);
667}
668
669#if 0 /* FIXME: unused */
670int avc_tuner_host2ca(struct firedtv *fdtv)
671{
672 AVCCmdFrm CmdFrm;
673 AVCRspFrm RspFrm;
674
675 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
676 CmdFrm.cts = AVC;
677 CmdFrm.ctype = CONTROL;
678 CmdFrm.sutyp = 0x5;
679 CmdFrm.suid = fdtv->subunit;
680 CmdFrm.opcode = VENDOR;
681
682 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
683 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
684 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
685 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
686 CmdFrm.operand[4] = 0; // slot
687 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
688 CmdFrm.operand[6] = 0; // more/last
689 CmdFrm.operand[7] = 0; // length
690 CmdFrm.length = 12;
691
692 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
693 return -EIO;
694
695 return 0;
696}
697#endif
698
699static int get_ca_object_pos(AVCRspFrm *RspFrm)
700{
701 int length = 1;
702
703 /* Check length of length field */
704 if (RspFrm->operand[7] & 0x80)
705 length = (RspFrm->operand[7] & 0x7f) + 1;
706 return length + 7;
707}
708
709static int get_ca_object_length(AVCRspFrm *RspFrm)
710{
711#if 0 /* FIXME: unused */
712 int size = 0;
713 int i;
714
715 if (RspFrm->operand[7] & 0x80)
716 for (i = 0; i < (RspFrm->operand[7] & 0x7f); i++) {
717 size <<= 8;
718 size += RspFrm->operand[8 + i];
719 }
720#endif
721 return RspFrm->operand[7];
722}
723
724int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
725{
726 AVCCmdFrm CmdFrm;
727 AVCRspFrm RspFrm;
728 int pos;
729
730 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
731 CmdFrm.cts = AVC;
732 CmdFrm.ctype = STATUS;
733 CmdFrm.sutyp = 0x5;
734 CmdFrm.suid = fdtv->subunit;
735 CmdFrm.opcode = VENDOR;
736
737 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
738 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
739 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
740 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
741 CmdFrm.operand[4] = 0; // slot
742 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
743 CmdFrm.length = 12;
744
745 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
746 return -EIO;
747
748 /* FIXME: check response code and validate response data */
749
750 pos = get_ca_object_pos(&RspFrm);
751 app_info[0] = (TAG_APP_INFO >> 16) & 0xFF;
752 app_info[1] = (TAG_APP_INFO >> 8) & 0xFF;
753 app_info[2] = (TAG_APP_INFO >> 0) & 0xFF;
754 app_info[3] = 6 + RspFrm.operand[pos + 4];
755 app_info[4] = 0x01;
756 memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]);
757 *len = app_info[3] + 4;
758
759 return 0;
760}
761
762int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
763{
764 AVCCmdFrm CmdFrm;
765 AVCRspFrm RspFrm;
766 int pos;
767
768 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
769 CmdFrm.cts = AVC;
770 CmdFrm.ctype = STATUS;
771 CmdFrm.sutyp = 0x5;
772 CmdFrm.suid = fdtv->subunit;
773 CmdFrm.opcode = VENDOR;
774
775 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
776 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
777 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
778 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
779 CmdFrm.operand[4] = 0; // slot
780 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
781 CmdFrm.length = 12;
782
783 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
784 return -EIO;
785
786 pos = get_ca_object_pos(&RspFrm);
787 app_info[0] = (TAG_CA_INFO >> 16) & 0xFF;
788 app_info[1] = (TAG_CA_INFO >> 8) & 0xFF;
789 app_info[2] = (TAG_CA_INFO >> 0) & 0xFF;
790 app_info[3] = 2;
791 app_info[4] = RspFrm.operand[pos + 0];
792 app_info[5] = RspFrm.operand[pos + 1];
793 *len = app_info[3] + 4;
794
795 return 0;
796}
797
798int avc_ca_reset(struct firedtv *fdtv)
799{
800 AVCCmdFrm CmdFrm;
801 AVCRspFrm RspFrm;
802
803 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
804 CmdFrm.cts = AVC;
805 CmdFrm.ctype = CONTROL;
806 CmdFrm.sutyp = 0x5;
807 CmdFrm.suid = fdtv->subunit;
808 CmdFrm.opcode = VENDOR;
809
810 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
811 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
812 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
813 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
814 CmdFrm.operand[4] = 0; // slot
815 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_RESET; // ca tag
816 CmdFrm.operand[6] = 0; // more/last
817 CmdFrm.operand[7] = 1; // length
818 CmdFrm.operand[8] = 0; // force hardware reset
819 CmdFrm.length = 12;
820
821 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
822 return -EIO;
823
824 return 0;
825}
826
827int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
828{
829 AVCCmdFrm CmdFrm;
830 AVCRspFrm RspFrm;
831 int list_management;
832 int program_info_length;
833 int pmt_cmd_id;
834 int read_pos;
835 int write_pos;
836 int es_info_length;
837 int crc32_csum;
838
839 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
840 CmdFrm.cts = AVC;
841 CmdFrm.ctype = CONTROL;
842 CmdFrm.sutyp = 0x5;
843 CmdFrm.suid = fdtv->subunit;
844 CmdFrm.opcode = VENDOR;
845
846 if (msg[0] != LIST_MANAGEMENT_ONLY) {
847 dev_info(&fdtv->ud->device,
848 "forcing list_management to ONLY\n");
849 msg[0] = LIST_MANAGEMENT_ONLY;
850 }
851 // We take the cmd_id from the programme level only!
852 list_management = msg[0];
853 program_info_length = ((msg[4] & 0x0F) << 8) + msg[5];
854 if (program_info_length > 0)
855 program_info_length--; // Remove pmt_cmd_id
856 pmt_cmd_id = msg[6];
857
858 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
859 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
860 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
861 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
862 CmdFrm.operand[4] = 0; // slot
863 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_PMT; // ca tag
864 CmdFrm.operand[6] = 0; // more/last
865 //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length
866 CmdFrm.operand[8] = list_management;
867 CmdFrm.operand[9] = 0x01; // pmt_cmd=OK_descramble
868
869 // TS program map table
870
871 // Table id=2
872 CmdFrm.operand[10] = 0x02;
873 // Section syntax + length
874 CmdFrm.operand[11] = 0x80;
875 //CmdFrm.operand[12] = XXXprogram_info_length + 12;
876 // Program number
877 CmdFrm.operand[13] = msg[1];
878 CmdFrm.operand[14] = msg[2];
879 // Version number=0 + current/next=1
880 CmdFrm.operand[15] = 0x01;
881 // Section number=0
882 CmdFrm.operand[16] = 0x00;
883 // Last section number=0
884 CmdFrm.operand[17] = 0x00;
885 // PCR_PID=1FFF
886 CmdFrm.operand[18] = 0x1F;
887 CmdFrm.operand[19] = 0xFF;
888 // Program info length
889 CmdFrm.operand[20] = (program_info_length >> 8);
890 CmdFrm.operand[21] = (program_info_length & 0xFF);
891 // CA descriptors at programme level
892 read_pos = 6;
893 write_pos = 22;
894 if (program_info_length > 0) {
895 pmt_cmd_id = msg[read_pos++];
896 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
897 dev_err(&fdtv->ud->device,
898 "invalid pmt_cmd_id %d\n", pmt_cmd_id);
899
900 memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
901 program_info_length);
902 read_pos += program_info_length;
903 write_pos += program_info_length;
904 }
905 while (read_pos < length) {
906 CmdFrm.operand[write_pos++] = msg[read_pos++];
907 CmdFrm.operand[write_pos++] = msg[read_pos++];
908 CmdFrm.operand[write_pos++] = msg[read_pos++];
909 es_info_length =
910 ((msg[read_pos] & 0x0F) << 8) + msg[read_pos + 1];
911 read_pos += 2;
912 if (es_info_length > 0)
913 es_info_length--; // Remove pmt_cmd_id
914 CmdFrm.operand[write_pos++] = es_info_length >> 8;
915 CmdFrm.operand[write_pos++] = es_info_length & 0xFF;
916 if (es_info_length > 0) {
917 pmt_cmd_id = msg[read_pos++];
918 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
919 dev_err(&fdtv->ud->device,
920 "invalid pmt_cmd_id %d "
921 "at stream level\n", pmt_cmd_id);
922
923 memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
924 es_info_length);
925 read_pos += es_info_length;
926 write_pos += es_info_length;
927 }
928 }
929
930 // CRC
931 CmdFrm.operand[write_pos++] = 0x00;
932 CmdFrm.operand[write_pos++] = 0x00;
933 CmdFrm.operand[write_pos++] = 0x00;
934 CmdFrm.operand[write_pos++] = 0x00;
935
936 CmdFrm.operand[7] = write_pos - 8;
937 CmdFrm.operand[12] = write_pos - 13;
938
939 crc32_csum = crc32_be(0, &CmdFrm.operand[10],
940 CmdFrm.operand[12] - 1);
941 CmdFrm.operand[write_pos - 4] = (crc32_csum >> 24) & 0xFF;
942 CmdFrm.operand[write_pos - 3] = (crc32_csum >> 16) & 0xFF;
943 CmdFrm.operand[write_pos - 2] = (crc32_csum >> 8) & 0xFF;
944 CmdFrm.operand[write_pos - 1] = (crc32_csum >> 0) & 0xFF;
945
946 CmdFrm.length = ALIGN(3 + write_pos, 4);
947
948 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
949 return -EIO;
950
951 if (RspFrm.resp != ACCEPTED) {
952 dev_err(&fdtv->ud->device,
953 "CA PMT failed with response 0x%x\n", RspFrm.resp);
954 return -EFAULT;
955 }
956
957 return 0;
958}
959
960int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
961{
962 AVCCmdFrm CmdFrm;
963 AVCRspFrm RspFrm;
964
965 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
966 CmdFrm.cts = AVC;
967 CmdFrm.ctype = STATUS;
968 CmdFrm.sutyp = 0x5;
969 CmdFrm.suid = fdtv->subunit;
970 CmdFrm.opcode = VENDOR;
971
972 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
973 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
974 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
975 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
976 CmdFrm.operand[4] = 0; // slot
977 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; // ca tag
978 CmdFrm.operand[6] = 0; // more/last
979 CmdFrm.operand[7] = 0; // length
980 CmdFrm.length = 12;
981
982 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
983 return -EIO;
984
985 /* FIXME: check response code and validate response data */
986
987 *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)];
988
989 return 0;
990}
991
992int avc_ca_enter_menu(struct firedtv *fdtv)
993{
994 AVCCmdFrm CmdFrm;
995 AVCRspFrm RspFrm;
996
997 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
998 CmdFrm.cts = AVC;
999 CmdFrm.ctype = STATUS;
1000 CmdFrm.sutyp = 0x5;
1001 CmdFrm.suid = fdtv->subunit;
1002 CmdFrm.opcode = VENDOR;
1003
1004 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
1005 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
1006 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
1007 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
1008 CmdFrm.operand[4] = 0; // slot
1009 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
1010 CmdFrm.operand[6] = 0; // more/last
1011 CmdFrm.operand[7] = 0; // length
1012 CmdFrm.length = 12;
1013
1014 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
1015 return -EIO;
1016
1017 return 0;
1018}
1019
1020int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1021{
1022 AVCCmdFrm CmdFrm;
1023 AVCRspFrm RspFrm;
1024
1025 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
1026 CmdFrm.cts = AVC;
1027 CmdFrm.ctype = STATUS;
1028 CmdFrm.sutyp = 0x5;
1029 CmdFrm.suid = fdtv->subunit;
1030 CmdFrm.opcode = VENDOR;
1031
1032 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
1033 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
1034 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
1035 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
1036 CmdFrm.operand[4] = 0; // slot
1037 CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_MMI;
1038 CmdFrm.operand[6] = 0; // more/last
1039 CmdFrm.operand[7] = 0; // length
1040 CmdFrm.length = 12;
1041
1042 if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
1043 return -EIO;
1044
1045 /* FIXME: check response code and validate response data */
1046
1047 *len = get_ca_object_length(&RspFrm);
1048 memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *len);
1049
1050 return 0;
1051}
diff --git a/drivers/media/dvb/firewire/avc.h b/drivers/media/dvb/firewire/avc.h
deleted file mode 100644
index 168f371dbde0..000000000000
--- a/drivers/media/dvb/firewire/avc.h
+++ /dev/null
@@ -1,432 +0,0 @@
1/*
2 * AV/C API
3 *
4 * Copyright (C) 2000 Manfred Weihs
5 * Copyright (C) 2003 Philipp Gutgsell <0014guph@edu.fh-kaernten.ac.at>
6 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
7 * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
8 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
9 *
10 * This is based on code written by Peter Halwachs, Thomas Groiss and
11 * Andreas Monitzer.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
17 */
18
19#ifndef _AVC_API_H
20#define _AVC_API_H
21
22#include <linux/types.h>
23
24/*************************************************************
25 Constants from EN510221
26**************************************************************/
27#define LIST_MANAGEMENT_ONLY 0x03
28
29/************************************************************
30 definition of structures
31*************************************************************/
32typedef struct {
33 int Nr_SourcePlugs;
34 int Nr_DestinationPlugs;
35} TunerInfo;
36
37
38/***********************************************
39
40 supported cts
41
42************************************************/
43
44#define AVC 0x0
45
46// FCP command frame with ctype = 0x0 is AVC command frame
47
48#ifdef __LITTLE_ENDIAN
49
50// Definition FCP Command Frame
51typedef struct _AVCCmdFrm
52{
53 // AV/C command frame
54 __u8 ctype : 4 ; // command type
55 __u8 cts : 4 ; // always 0x0 for AVC
56 __u8 suid : 3 ; // subunit ID
57 __u8 sutyp : 5 ; // subunit_typ
58 __u8 opcode : 8 ; // opcode
59 __u8 operand[509] ; // array of operands [1-507]
60 int length; //length of the command frame
61} AVCCmdFrm ;
62
63// Definition FCP Response Frame
64typedef struct _AVCRspFrm
65{
66 // AV/C response frame
67 __u8 resp : 4 ; // response type
68 __u8 cts : 4 ; // always 0x0 for AVC
69 __u8 suid : 3 ; // subunit ID
70 __u8 sutyp : 5 ; // subunit_typ
71 __u8 opcode : 8 ; // opcode
72 __u8 operand[509] ; // array of operands [1-507]
73 int length; //length of the response frame
74} AVCRspFrm ;
75
76#else
77
78typedef struct _AVCCmdFrm
79{
80 __u8 cts:4;
81 __u8 ctype:4;
82 __u8 sutyp:5;
83 __u8 suid:3;
84 __u8 opcode;
85 __u8 operand[509];
86 int length;
87} AVCCmdFrm;
88
89typedef struct _AVCRspFrm
90{
91 __u8 cts:4;
92 __u8 resp:4;
93 __u8 sutyp:5;
94 __u8 suid:3;
95 __u8 opcode;
96 __u8 operand[509];
97 int length;
98} AVCRspFrm;
99
100#endif
101
102/*************************************************************
103 AVC command types (ctype)
104**************************************************************///
105#define CONTROL 0x00
106#define STATUS 0x01
107#define INQUIRY 0x02
108#define NOTIFY 0x03
109
110/*************************************************************
111 AVC respond types
112**************************************************************///
113#define NOT_IMPLEMENTED 0x8
114#define ACCEPTED 0x9
115#define REJECTED 0xA
116#define STABLE 0xC
117#define CHANGED 0xD
118#define INTERIM 0xF
119
120/*************************************************************
121 AVC opcodes
122**************************************************************///
123#define CONNECT 0x24
124#define DISCONNECT 0x25
125#define UNIT_INFO 0x30
126#define SUBUNIT_Info 0x31
127#define VENDOR 0x00
128
129#define PLUG_INFO 0x02
130#define OPEN_DESCRIPTOR 0x08
131#define READ_DESCRIPTOR 0x09
132#define OBJECT_NUMBER_SELECT 0x0D
133
134/*************************************************************
135 AVCTuner opcodes
136**************************************************************/
137
138#define DSIT 0xC8
139#define DSD 0xCB
140#define DESCRIPTOR_TUNER_STATUS 0x80
141#define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00
142
143/*************************************************************
144 AVCTuner list types
145**************************************************************/
146#define Multiplex_List 0x80
147#define Service_List 0x82
148
149/*************************************************************
150 AVCTuner object entries
151**************************************************************/
152#define Multiplex 0x80
153#define Service 0x82
154#define Service_with_specified_components 0x83
155#define Preferred_components 0x90
156#define Component 0x84
157
158/*************************************************************
159 Vendor-specific commands
160**************************************************************/
161
162// digital everywhere vendor ID
163#define SFE_VENDOR_DE_COMPANYID_0 0x00
164#define SFE_VENDOR_DE_COMPANYID_1 0x12
165#define SFE_VENDOR_DE_COMPANYID_2 0x87
166
167#define SFE_VENDOR_MAX_NR_COMPONENTS 0x4
168#define SFE_VENDOR_MAX_NR_SERVICES 0x3
169#define SFE_VENDOR_MAX_NR_DSD_ELEMENTS 0x10
170
171// vendor commands
172#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0A
173#define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52
174#define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 // QPSK command for DVB-S
175
176// TODO: following vendor specific commands needs to be implemented
177#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
178#define SFE_VENDOR_OPCODE_HOST2CA 0x56
179#define SFE_VENDOR_OPCODE_CA2HOST 0x57
180#define SFE_VENDOR_OPCODE_CISTATUS 0x59
181#define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 // QPSK command for DVB-S2 devices
182
183// CA Tags
184#define SFE_VENDOR_TAG_CA_RESET 0x00
185#define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
186#define SFE_VENDOR_TAG_CA_PMT 0x02
187#define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
188#define SFE_VENDOR_TAG_CA_MMI 0x05
189#define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
190
191
192//AVCTuner DVB identifier service_ID
193#define DVB 0x20
194
195/*************************************************************
196 AVC descriptor types
197**************************************************************/
198
199#define Subunit_Identifier_Descriptor 0x00
200#define Tuner_Status_Descriptor 0x80
201
202typedef struct {
203 __u8 Subunit_Type;
204 __u8 Max_Subunit_ID;
205} SUBUNIT_INFO;
206
207/*************************************************************
208
209 AVCTuner DVB object IDs are 6 byte long
210
211**************************************************************/
212
213typedef struct {
214 __u8 Byte0;
215 __u8 Byte1;
216 __u8 Byte2;
217 __u8 Byte3;
218 __u8 Byte4;
219 __u8 Byte5;
220}OBJECT_ID;
221
222/*************************************************************
223 MULIPLEX Structs
224**************************************************************/
225typedef struct
226{
227#ifdef __LITTLE_ENDIAN
228 __u8 RF_frequency_hByte:6;
229 __u8 raster_Frequency:2;//Bit7,6 raster frequency
230#else
231 __u8 raster_Frequency:2;
232 __u8 RF_frequency_hByte:6;
233#endif
234 __u8 RF_frequency_mByte;
235 __u8 RF_frequency_lByte;
236
237}FREQUENCY;
238
239#ifdef __LITTLE_ENDIAN
240
241typedef struct
242{
243 __u8 Modulation :1;
244 __u8 FEC_inner :1;
245 __u8 FEC_outer :1;
246 __u8 Symbol_Rate :1;
247 __u8 Frequency :1;
248 __u8 Orbital_Pos :1;
249 __u8 Polarisation :1;
250 __u8 reserved_fields :1;
251 __u8 reserved1 :7;
252 __u8 Network_ID :1;
253
254}MULTIPLEX_VALID_FLAGS;
255
256typedef struct
257{
258 __u8 GuardInterval:1;
259 __u8 CodeRateLPStream:1;
260 __u8 CodeRateHPStream:1;
261 __u8 HierarchyInfo:1;
262 __u8 Constellation:1;
263 __u8 Bandwidth:1;
264 __u8 CenterFrequency:1;
265 __u8 reserved1:1;
266 __u8 reserved2:5;
267 __u8 OtherFrequencyFlag:1;
268 __u8 TransmissionMode:1;
269 __u8 NetworkId:1;
270}MULTIPLEX_VALID_FLAGS_DVBT;
271
272#else
273
274typedef struct {
275 __u8 reserved_fields:1;
276 __u8 Polarisation:1;
277 __u8 Orbital_Pos:1;
278 __u8 Frequency:1;
279 __u8 Symbol_Rate:1;
280 __u8 FEC_outer:1;
281 __u8 FEC_inner:1;
282 __u8 Modulation:1;
283 __u8 Network_ID:1;
284 __u8 reserved1:7;
285}MULTIPLEX_VALID_FLAGS;
286
287typedef struct {
288 __u8 reserved1:1;
289 __u8 CenterFrequency:1;
290 __u8 Bandwidth:1;
291 __u8 Constellation:1;
292 __u8 HierarchyInfo:1;
293 __u8 CodeRateHPStream:1;
294 __u8 CodeRateLPStream:1;
295 __u8 GuardInterval:1;
296 __u8 NetworkId:1;
297 __u8 TransmissionMode:1;
298 __u8 OtherFrequencyFlag:1;
299 __u8 reserved2:5;
300}MULTIPLEX_VALID_FLAGS_DVBT;
301
302#endif
303
304typedef union {
305 MULTIPLEX_VALID_FLAGS Bits;
306 MULTIPLEX_VALID_FLAGS_DVBT Bits_T;
307 struct {
308 __u8 ByteHi;
309 __u8 ByteLo;
310 } Valid_Word;
311} M_VALID_FLAGS;
312
313typedef struct
314{
315#ifdef __LITTLE_ENDIAN
316 __u8 ActiveSystem;
317 __u8 reserved:5;
318 __u8 NoRF:1;
319 __u8 Moving:1;
320 __u8 Searching:1;
321
322 __u8 SelectedAntenna:7;
323 __u8 Input:1;
324
325 __u8 BER[4];
326
327 __u8 SignalStrength;
328 FREQUENCY Frequency;
329
330 __u8 ManDepInfoLength;
331
332 __u8 PowerSupply:1;
333 __u8 FrontEndPowerStatus:1;
334 __u8 reserved3:1;
335 __u8 AntennaError:1;
336 __u8 FrontEndError:1;
337 __u8 reserved2:3;
338
339 __u8 CarrierNoiseRatio[2];
340 __u8 reserved4[2];
341 __u8 PowerSupplyVoltage;
342 __u8 AntennaVoltage;
343 __u8 FirewireBusVoltage;
344
345 __u8 CaMmi:1;
346 __u8 reserved5:7;
347
348 __u8 reserved6:1;
349 __u8 CaInitializationStatus:1;
350 __u8 CaErrorFlag:1;
351 __u8 CaDvbFlag:1;
352 __u8 CaModulePresentStatus:1;
353 __u8 CaApplicationInfo:1;
354 __u8 CaDateTimeRequest:1;
355 __u8 CaPmtReply:1;
356
357#else
358 __u8 ActiveSystem;
359 __u8 Searching:1;
360 __u8 Moving:1;
361 __u8 NoRF:1;
362 __u8 reserved:5;
363
364 __u8 Input:1;
365 __u8 SelectedAntenna:7;
366
367 __u8 BER[4];
368
369 __u8 SignalStrength;
370 FREQUENCY Frequency;
371
372 __u8 ManDepInfoLength;
373
374 __u8 reserved2:3;
375 __u8 FrontEndError:1;
376 __u8 AntennaError:1;
377 __u8 reserved3:1;
378 __u8 FrontEndPowerStatus:1;
379 __u8 PowerSupply:1;
380
381 __u8 CarrierNoiseRatio[2];
382 __u8 reserved4[2];
383 __u8 PowerSupplyVoltage;
384 __u8 AntennaVoltage;
385 __u8 FirewireBusVoltage;
386
387 __u8 reserved5:7;
388 __u8 CaMmi:1;
389 __u8 CaPmtReply:1;
390 __u8 CaDateTimeRequest:1;
391 __u8 CaApplicationInfo:1;
392 __u8 CaModulePresentStatus:1;
393 __u8 CaDvbFlag:1;
394 __u8 CaErrorFlag:1;
395 __u8 CaInitializationStatus:1;
396 __u8 reserved6:1;
397
398#endif
399} ANTENNA_INPUT_INFO; // 22 Byte
400
401#define LNBCONTROL_DONTCARE 0xff
402
403struct dvb_diseqc_master_cmd;
404struct dvb_frontend_parameters;
405struct firedtv;
406
407int avc_recv(struct firedtv *fdtv, u8 *data, size_t length);
408
409int AVCTuner_DSIT(struct firedtv *fdtv, int Source_Plug,
410 struct dvb_frontend_parameters *params, __u8 *status);
411
412int avc_tuner_status(struct firedtv *fdtv,
413 ANTENNA_INPUT_INFO *antenna_input_info);
414int avc_tuner_dsd(struct firedtv *fdtv,
415 struct dvb_frontend_parameters *params);
416int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
417int avc_tuner_get_ts(struct firedtv *fdtv);
418int avc_identify_subunit(struct firedtv *fdtv);
419int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
420 char conttone, char nrdiseq,
421 struct dvb_diseqc_master_cmd *diseqcmd);
422void avc_remote_ctrl_work(struct work_struct *work);
423int avc_register_remote_control(struct firedtv *fdtv);
424int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
425int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
426int avc_ca_reset(struct firedtv *fdtv);
427int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
428int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
429int avc_ca_enter_menu(struct firedtv *fdtv);
430int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
431
432#endif /* _AVC_API_H */
diff --git a/drivers/media/dvb/firewire/cmp.c b/drivers/media/dvb/firewire/cmp.c
deleted file mode 100644
index 821e033d8195..000000000000
--- a/drivers/media/dvb/firewire/cmp.c
+++ /dev/null
@@ -1,171 +0,0 @@
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/device.h>
14#include <linux/kernel.h>
15#include <linux/mutex.h>
16#include <linux/types.h>
17
18#include <asm/byteorder.h>
19
20#include <ieee1394.h>
21#include <nodemgr.h>
22
23#include "avc.h"
24#include "cmp.h"
25#include "firedtv.h"
26
27#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
28
29static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
30{
31 int ret;
32
33 if (mutex_lock_interruptible(&fdtv->avc_mutex))
34 return -EINTR;
35
36 ret = hpsb_node_read(fdtv->ud->ne, addr, buf, len);
37 if (ret < 0)
38 dev_err(&fdtv->ud->device, "CMP: read I/O error\n");
39
40 mutex_unlock(&fdtv->avc_mutex);
41 return ret;
42}
43
44static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg,
45 int ext_tcode)
46{
47 int ret;
48
49 if (mutex_lock_interruptible(&fdtv->avc_mutex))
50 return -EINTR;
51
52 ret = hpsb_node_lock(fdtv->ud->ne, addr, ext_tcode, data,
53 (__force quadlet_t)arg);
54 if (ret < 0)
55 dev_err(&fdtv->ud->device, "CMP: lock I/O error\n");
56
57 mutex_unlock(&fdtv->avc_mutex);
58 return ret;
59}
60
61static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
62{
63 return (be32_to_cpu(opcr) >> shift) & mask;
64}
65
66static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
67{
68 *opcr &= ~cpu_to_be32(mask << shift);
69 *opcr |= cpu_to_be32((value & mask) << shift);
70}
71
72#define get_opcr_online(v) get_opcr((v), 0x1, 31)
73#define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
74#define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
75
76#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
77#define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
78#define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
79#define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
80
81int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
82{
83 __be32 old_opcr, opcr;
84 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
85 int attempts = 0;
86 int ret;
87
88 ret = cmp_read(fdtv, &opcr, opcr_address, 4);
89 if (ret < 0)
90 return ret;
91
92repeat:
93 if (!get_opcr_online(opcr)) {
94 dev_err(&fdtv->ud->device, "CMP: output offline\n");
95 return -EBUSY;
96 }
97
98 old_opcr = opcr;
99
100 if (get_opcr_p2p_connections(opcr)) {
101 if (get_opcr_channel(opcr) != channel) {
102 dev_err(&fdtv->ud->device,
103 "CMP: cannot change channel\n");
104 return -EBUSY;
105 }
106 dev_info(&fdtv->ud->device,
107 "CMP: overlaying existing connection\n");
108
109 /* We don't allocate isochronous resources. */
110 } else {
111 set_opcr_channel(&opcr, channel);
112 set_opcr_data_rate(&opcr, IEEE1394_SPEED_400);
113
114 /* FIXME: this is for the worst case - optimize */
115 set_opcr_overhead_id(&opcr, 0);
116
117 /* FIXME: allocate isochronous channel and bandwidth at IRM */
118 }
119
120 set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
121
122 ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2);
123 if (ret < 0)
124 return ret;
125
126 if (old_opcr != opcr) {
127 /*
128 * FIXME: if old_opcr.P2P_Connections > 0,
129 * deallocate isochronous channel and bandwidth at IRM
130 */
131
132 if (++attempts < 6) /* arbitrary limit */
133 goto repeat;
134 return -EBUSY;
135 }
136
137 return 0;
138}
139
140void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
141{
142 __be32 old_opcr, opcr;
143 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
144 int attempts = 0;
145
146 if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
147 return;
148
149repeat:
150 if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
151 get_opcr_channel(opcr) != channel) {
152 dev_err(&fdtv->ud->device, "CMP: no connection to break\n");
153 return;
154 }
155
156 old_opcr = opcr;
157 set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
158
159 if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2) < 0)
160 return;
161
162 if (old_opcr != opcr) {
163 /*
164 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
165 * owner, deallocate isochronous channel and bandwidth at IRM
166 */
167
168 if (++attempts < 6) /* arbitrary limit */
169 goto repeat;
170 }
171}
diff --git a/drivers/media/dvb/firewire/cmp.h b/drivers/media/dvb/firewire/cmp.h
deleted file mode 100644
index 17e182cf29a9..000000000000
--- a/drivers/media/dvb/firewire/cmp.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#ifndef _CMP_H
2#define _CMP_H
3
4struct firedtv;
5
6int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
7void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
8
9#endif /* _CMP_H */
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 953618246e8e..4e207658c5d9 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -15,162 +15,181 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h> 18#include <linux/spinlock.h>
22#include <linux/string.h>
23#include <linux/types.h> 19#include <linux/types.h>
24 20
25#include <dmxdev.h> 21#include <dma.h>
26#include <dvb_demux.h>
27#include <dvb_frontend.h>
28#include <dvbdev.h>
29
30#include <csr1212.h> 22#include <csr1212.h>
31#include <highlevel.h> 23#include <highlevel.h>
32#include <hosts.h> 24#include <hosts.h>
33#include <ieee1394_hotplug.h> 25#include <ieee1394.h>
26#include <iso.h>
34#include <nodemgr.h> 27#include <nodemgr.h>
35 28
36#include "avc.h"
37#include "cmp.h"
38#include "firedtv.h" 29#include "firedtv.h"
39#include "firedtv-ci.h"
40#include "firedtv-rc.h"
41
42#define MATCH_FLAGS IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
43 IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION
44#define DIGITAL_EVERYWHERE_OUI 0x001287
45
46static struct ieee1394_device_id fdtv_id_table[] = {
47
48 {
49 /* FloppyDTV S/CI and FloppyDTV S2 */
50 .match_flags = MATCH_FLAGS,
51 .vendor_id = DIGITAL_EVERYWHERE_OUI,
52 .model_id = 0x000024,
53 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
54 .version = AVC_SW_VERSION_ENTRY,
55 },{
56 /* FloppyDTV T/CI */
57 .match_flags = MATCH_FLAGS,
58 .vendor_id = DIGITAL_EVERYWHERE_OUI,
59 .model_id = 0x000025,
60 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
61 .version = AVC_SW_VERSION_ENTRY,
62 },{
63 /* FloppyDTV C/CI */
64 .match_flags = MATCH_FLAGS,
65 .vendor_id = DIGITAL_EVERYWHERE_OUI,
66 .model_id = 0x000026,
67 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
68 .version = AVC_SW_VERSION_ENTRY,
69 },{
70 /* FireDTV S/CI and FloppyDTV S2 */
71 .match_flags = MATCH_FLAGS,
72 .vendor_id = DIGITAL_EVERYWHERE_OUI,
73 .model_id = 0x000034,
74 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
75 .version = AVC_SW_VERSION_ENTRY,
76 },{
77 /* FireDTV T/CI */
78 .match_flags = MATCH_FLAGS,
79 .vendor_id = DIGITAL_EVERYWHERE_OUI,
80 .model_id = 0x000035,
81 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
82 .version = AVC_SW_VERSION_ENTRY,
83 },{
84 /* FireDTV C/CI */
85 .match_flags = MATCH_FLAGS,
86 .vendor_id = DIGITAL_EVERYWHERE_OUI,
87 .model_id = 0x000036,
88 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
89 .version = AVC_SW_VERSION_ENTRY,
90 }, { }
91};
92 30
93MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); 31static LIST_HEAD(node_list);
32static DEFINE_SPINLOCK(node_list_lock);
94 33
95/* list of all firedtv devices */ 34#define FIREWIRE_HEADER_SIZE 4
96LIST_HEAD(fdtv_list); 35#define CIP_HEADER_SIZE 8
97DEFINE_SPINLOCK(fdtv_list_lock);
98 36
99static void fcp_request(struct hpsb_host *host, 37static void rawiso_activity_cb(struct hpsb_iso *iso)
100 int nodeid,
101 int direction,
102 int cts,
103 u8 *data,
104 size_t length)
105{ 38{
106 struct firedtv *fdtv = NULL; 39 struct firedtv *f, *fdtv = NULL;
107 struct firedtv *fdtv_entry; 40 unsigned int i, num, packet;
41 unsigned char *buf;
108 unsigned long flags; 42 unsigned long flags;
43 int count;
44
45 spin_lock_irqsave(&node_list_lock, flags);
46 list_for_each_entry(f, &node_list, list)
47 if (f->backend_data == iso) {
48 fdtv = f;
49 break;
50 }
51 spin_unlock_irqrestore(&node_list_lock, flags);
52
53 packet = iso->first_packet;
54 num = hpsb_iso_n_ready(iso);
55
56 if (!fdtv) {
57 dev_err(fdtv->device, "received at unknown iso channel\n");
58 goto out;
59 }
109 60
110 if (length > 0 && ((data[0] & 0xf0) >> 4) == 0) { 61 for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
111 62 buf = dma_region_i(&iso->data_buf, unsigned char,
112 spin_lock_irqsave(&fdtv_list_lock, flags); 63 iso->infos[packet].offset + CIP_HEADER_SIZE);
113 list_for_each_entry(fdtv_entry,&fdtv_list,list) { 64 count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
114 if (fdtv_entry->ud->ne->host == host && 65 (188 + FIREWIRE_HEADER_SIZE);
115 fdtv_entry->ud->ne->nodeid == nodeid && 66
116 (fdtv_entry->subunit == (data[1]&0x7) || 67 /* ignore empty packet */
117 (fdtv_entry->subunit == 0 && 68 if (iso->infos[packet].len <= CIP_HEADER_SIZE)
118 (data[1]&0x7) == 0x7))) { 69 continue;
119 fdtv=fdtv_entry; 70
120 break; 71 while (count--) {
121 } 72 if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
73 dvb_dmx_swfilter_packets(&fdtv->demux,
74 &buf[FIREWIRE_HEADER_SIZE], 1);
75 else
76 dev_err(fdtv->device,
77 "skipping invalid packet\n");
78 buf += 188 + FIREWIRE_HEADER_SIZE;
122 } 79 }
123 spin_unlock_irqrestore(&fdtv_list_lock, flags); 80 }
81out:
82 hpsb_iso_recv_release_packets(iso, num);
83}
84
85static inline struct node_entry *node_of(struct firedtv *fdtv)
86{
87 return container_of(fdtv->device, struct unit_directory, device)->ne;
88}
89
90static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
91{
92 return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
93 (__force quadlet_t)arg);
94}
95
96static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
97{
98 return hpsb_node_read(node_of(fdtv), addr, data, len);
99}
100
101static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
102{
103 return hpsb_node_write(node_of(fdtv), addr, data, len);
104}
105
106#define FDTV_ISO_BUFFER_PACKETS 256
107#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
108
109static int start_iso(struct firedtv *fdtv)
110{
111 struct hpsb_iso *iso_handle;
112 int ret;
113
114 iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
115 FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
116 fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
117 -1, /* stat.config.irq_interval */
118 rawiso_activity_cb);
119 if (iso_handle == NULL) {
120 dev_err(fdtv->device, "cannot initialize iso receive\n");
121 return -ENOMEM;
122 }
123 fdtv->backend_data = iso_handle;
124
125 ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
126 if (ret != 0) {
127 dev_err(fdtv->device, "cannot start iso receive\n");
128 hpsb_iso_shutdown(iso_handle);
129 fdtv->backend_data = NULL;
130 }
131 return ret;
132}
133
134static void stop_iso(struct firedtv *fdtv)
135{
136 struct hpsb_iso *iso_handle = fdtv->backend_data;
124 137
125 if (fdtv) 138 if (iso_handle != NULL) {
126 avc_recv(fdtv, data, length); 139 hpsb_iso_stop(iso_handle);
140 hpsb_iso_shutdown(iso_handle);
127 } 141 }
142 fdtv->backend_data = NULL;
128} 143}
129 144
130const char *fdtv_model_names[] = { 145static const struct firedtv_backend fdtv_1394_backend = {
131 [FIREDTV_UNKNOWN] = "unknown type", 146 .lock = node_lock,
132 [FIREDTV_DVB_S] = "FireDTV S/CI", 147 .read = node_read,
133 [FIREDTV_DVB_C] = "FireDTV C/CI", 148 .write = node_write,
134 [FIREDTV_DVB_T] = "FireDTV T/CI", 149 .start_iso = start_iso,
135 [FIREDTV_DVB_S2] = "FireDTV S2 ", 150 .stop_iso = stop_iso,
136}; 151};
137 152
138static int fdtv_probe(struct device *dev) 153static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
154 int cts, u8 *data, size_t length)
139{ 155{
140 struct unit_directory *ud = 156 struct firedtv *f, *fdtv = NULL;
141 container_of(dev, struct unit_directory, device);
142 struct firedtv *fdtv;
143 unsigned long flags; 157 unsigned long flags;
144 int kv_len; 158 int su;
145 void *kv_str;
146 int i;
147 int err = -ENOMEM;
148 159
149 fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); 160 if (length == 0 || (data[0] & 0xf0) != 0)
150 if (!fdtv) 161 return;
151 return -ENOMEM;
152 162
153 dev->driver_data = fdtv; 163 su = data[1] & 0x7;
154 fdtv->ud = ud; 164
155 fdtv->subunit = 0; 165 spin_lock_irqsave(&node_list_lock, flags);
156 fdtv->isochannel = -1; 166 list_for_each_entry(f, &node_list, list)
157 fdtv->tone = 0xff; 167 if (node_of(f)->host == host &&
158 fdtv->voltage = 0xff; 168 node_of(f)->nodeid == nodeid &&
169 (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
170 fdtv = f;
171 break;
172 }
173 spin_unlock_irqrestore(&node_list_lock, flags);
159 174
160 mutex_init(&fdtv->avc_mutex); 175 if (fdtv)
161 init_waitqueue_head(&fdtv->avc_wait); 176 avc_recv(fdtv, data, length);
162 fdtv->avc_reply_received = true; 177}
163 mutex_init(&fdtv->demux_mutex); 178
164 INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); 179static int node_probe(struct device *dev)
180{
181 struct unit_directory *ud =
182 container_of(dev, struct unit_directory, device);
183 struct firedtv *fdtv;
184 int kv_len, err;
185 void *kv_str;
165 186
166 /* Reading device model from ROM */
167 kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); 187 kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
168 kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); 188 kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
169 for (i = ARRAY_SIZE(fdtv_model_names); --i;) 189
170 if (strlen(fdtv_model_names[i]) <= kv_len && 190 fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
171 strncmp(kv_str, fdtv_model_names[i], kv_len) == 0) 191 if (!fdtv)
172 break; 192 return -ENOMEM;
173 fdtv->type = i;
174 193
175 /* 194 /*
176 * Work around a bug in udev's path_id script: Use the fw-host's dev 195 * Work around a bug in udev's path_id script: Use the fw-host's dev
@@ -180,50 +199,39 @@ static int fdtv_probe(struct device *dev)
180 if (err) 199 if (err)
181 goto fail_free; 200 goto fail_free;
182 201
183 INIT_LIST_HEAD(&fdtv->list); 202 spin_lock_irq(&node_list_lock);
184 spin_lock_irqsave(&fdtv_list_lock, flags); 203 list_add_tail(&fdtv->list, &node_list);
185 list_add_tail(&fdtv->list, &fdtv_list); 204 spin_unlock_irq(&node_list_lock);
186 spin_unlock_irqrestore(&fdtv_list_lock, flags);
187 205
188 err = avc_identify_subunit(fdtv); 206 err = avc_identify_subunit(fdtv);
189 if (err) 207 if (err)
190 goto fail; 208 goto fail;
191 209
192 err = fdtv_dvbdev_init(fdtv, dev); 210 err = fdtv_dvb_register(fdtv);
193 if (err) 211 if (err)
194 goto fail; 212 goto fail;
195 213
196 avc_register_remote_control(fdtv); 214 avc_register_remote_control(fdtv);
197 return 0; 215 return 0;
198
199fail: 216fail:
200 spin_lock_irqsave(&fdtv_list_lock, flags); 217 spin_lock_irq(&node_list_lock);
201 list_del(&fdtv->list); 218 list_del(&fdtv->list);
202 spin_unlock_irqrestore(&fdtv_list_lock, flags); 219 spin_unlock_irq(&node_list_lock);
203 fdtv_unregister_rc(fdtv); 220 fdtv_unregister_rc(fdtv);
204fail_free: 221fail_free:
205 kfree(fdtv); 222 kfree(fdtv);
206 return err; 223 return err;
207} 224}
208 225
209static int fdtv_remove(struct device *dev) 226static int node_remove(struct device *dev)
210{ 227{
211 struct firedtv *fdtv = dev->driver_data; 228 struct firedtv *fdtv = dev->driver_data;
212 unsigned long flags;
213 229
214 fdtv_ca_release(fdtv); 230 fdtv_dvb_unregister(fdtv);
215 dvb_unregister_frontend(&fdtv->fe); 231
216 dvb_net_release(&fdtv->dvbnet); 232 spin_lock_irq(&node_list_lock);
217 fdtv->demux.dmx.close(&fdtv->demux.dmx);
218 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx,
219 &fdtv->frontend);
220 dvb_dmxdev_release(&fdtv->dmxdev);
221 dvb_dmx_release(&fdtv->demux);
222 dvb_unregister_adapter(&fdtv->adapter);
223
224 spin_lock_irqsave(&fdtv_list_lock, flags);
225 list_del(&fdtv->list); 233 list_del(&fdtv->list);
226 spin_unlock_irqrestore(&fdtv_list_lock, flags); 234 spin_unlock_irq(&node_list_lock);
227 235
228 cancel_work_sync(&fdtv->remote_ctrl_work); 236 cancel_work_sync(&fdtv->remote_ctrl_work);
229 fdtv_unregister_rc(fdtv); 237 fdtv_unregister_rc(fdtv);
@@ -232,7 +240,7 @@ static int fdtv_remove(struct device *dev)
232 return 0; 240 return 0;
233} 241}
234 242
235static int fdtv_update(struct unit_directory *ud) 243static int node_update(struct unit_directory *ud)
236{ 244{
237 struct firedtv *fdtv = ud->device.driver_data; 245 struct firedtv *fdtv = ud->device.driver_data;
238 246
@@ -243,17 +251,11 @@ static int fdtv_update(struct unit_directory *ud)
243} 251}
244 252
245static struct hpsb_protocol_driver fdtv_driver = { 253static struct hpsb_protocol_driver fdtv_driver = {
246
247 .name = "firedtv", 254 .name = "firedtv",
248 .id_table = fdtv_id_table, 255 .update = node_update,
249 .update = fdtv_update,
250
251 .driver = { 256 .driver = {
252 //.name and .bus are filled in for us in more recent linux versions 257 .probe = node_probe,
253 //.name = "FireDTV", 258 .remove = node_remove,
254 //.bus = &ieee1394_bus_type,
255 .probe = fdtv_probe,
256 .remove = fdtv_remove,
257 }, 259 },
258}; 260};
259 261
@@ -262,11 +264,12 @@ static struct hpsb_highlevel fdtv_highlevel = {
262 .fcp_request = fcp_request, 264 .fcp_request = fcp_request,
263}; 265};
264 266
265static int __init fdtv_init(void) 267int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
266{ 268{
267 int ret; 269 int ret;
268 270
269 hpsb_register_highlevel(&fdtv_highlevel); 271 hpsb_register_highlevel(&fdtv_highlevel);
272 fdtv_driver.id_table = id_table;
270 ret = hpsb_register_protocol(&fdtv_driver); 273 ret = hpsb_register_protocol(&fdtv_driver);
271 if (ret) { 274 if (ret) {
272 printk(KERN_ERR "firedtv: failed to register protocol\n"); 275 printk(KERN_ERR "firedtv: failed to register protocol\n");
@@ -275,17 +278,8 @@ static int __init fdtv_init(void)
275 return ret; 278 return ret;
276} 279}
277 280
278static void __exit fdtv_exit(void) 281void __exit fdtv_1394_exit(void)
279{ 282{
280 hpsb_unregister_protocol(&fdtv_driver); 283 hpsb_unregister_protocol(&fdtv_driver);
281 hpsb_unregister_highlevel(&fdtv_highlevel); 284 hpsb_unregister_highlevel(&fdtv_highlevel);
282} 285}
283
284module_init(fdtv_init);
285module_exit(fdtv_exit);
286
287MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
288MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
289MODULE_DESCRIPTION("FireDTV DVB Driver");
290MODULE_LICENSE("GPL");
291MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
new file mode 100644
index 000000000000..b55d9ccaf33e
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -0,0 +1,1315 @@
1/*
2 * FireDTV driver (formerly known as FireSAT)
3 *
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 */
13
14#include <linux/bug.h>
15#include <linux/crc32.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/jiffies.h>
19#include <linux/kernel.h>
20#include <linux/moduleparam.h>
21#include <linux/mutex.h>
22#include <linux/string.h>
23#include <linux/stringify.h>
24#include <linux/wait.h>
25#include <linux/workqueue.h>
26
27#include "firedtv.h"
28
29#define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
30
31#define AVC_CTYPE_CONTROL 0x0
32#define AVC_CTYPE_STATUS 0x1
33#define AVC_CTYPE_NOTIFY 0x3
34
35#define AVC_RESPONSE_ACCEPTED 0x9
36#define AVC_RESPONSE_STABLE 0xc
37#define AVC_RESPONSE_CHANGED 0xd
38#define AVC_RESPONSE_INTERIM 0xf
39
40#define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3)
41#define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3)
42
43#define AVC_OPCODE_VENDOR 0x00
44#define AVC_OPCODE_READ_DESCRIPTOR 0x09
45#define AVC_OPCODE_DSIT 0xc8
46#define AVC_OPCODE_DSD 0xcb
47
48#define DESCRIPTOR_TUNER_STATUS 0x80
49#define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00
50
51#define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */
52#define SFE_VENDOR_DE_COMPANYID_1 0x12
53#define SFE_VENDOR_DE_COMPANYID_2 0x87
54
55#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
56#define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52
57#define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */
58
59#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
60#define SFE_VENDOR_OPCODE_HOST2CA 0x56
61#define SFE_VENDOR_OPCODE_CA2HOST 0x57
62#define SFE_VENDOR_OPCODE_CISTATUS 0x59
63#define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */
64
65#define SFE_VENDOR_TAG_CA_RESET 0x00
66#define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
67#define SFE_VENDOR_TAG_CA_PMT 0x02
68#define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
69#define SFE_VENDOR_TAG_CA_MMI 0x05
70#define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
71
72#define EN50221_LIST_MANAGEMENT_ONLY 0x03
73#define EN50221_TAG_APP_INFO 0x9f8021
74#define EN50221_TAG_CA_INFO 0x9f8031
75
76struct avc_command_frame {
77 int length;
78 u8 ctype;
79 u8 subunit;
80 u8 opcode;
81 u8 operand[509];
82};
83
84struct avc_response_frame {
85 int length;
86 u8 response;
87 u8 subunit;
88 u8 opcode;
89 u8 operand[509];
90};
91
92#define AVC_DEBUG_FCP_SUBACTIONS 1
93#define AVC_DEBUG_FCP_PAYLOADS 2
94
95static int avc_debug;
96module_param_named(debug, avc_debug, int, 0644);
97MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
98 ", FCP subactions = " __stringify(AVC_DEBUG_FCP_SUBACTIONS)
99 ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS)
100 ", or all = -1)");
101
102static const char *debug_fcp_ctype(unsigned int ctype)
103{
104 static const char *ctypes[] = {
105 [0x0] = "CONTROL", [0x1] = "STATUS",
106 [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY",
107 [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED",
108 [0x9] = "ACCEPTED", [0xa] = "REJECTED",
109 [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE",
110 [0xd] = "CHANGED", [0xf] = "INTERIM",
111 };
112 const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
113
114 return ret ? ret : "?";
115}
116
117static const char *debug_fcp_opcode(unsigned int opcode,
118 const u8 *data, size_t length)
119{
120 switch (opcode) {
121 case AVC_OPCODE_VENDOR: break;
122 case AVC_OPCODE_READ_DESCRIPTOR: return "ReadDescriptor";
123 case AVC_OPCODE_DSIT: return "DirectSelectInfo.Type";
124 case AVC_OPCODE_DSD: return "DirectSelectData";
125 default: return "?";
126 }
127
128 if (length < 7 ||
129 data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
130 data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
131 data[5] != SFE_VENDOR_DE_COMPANYID_2)
132 return "Vendor";
133
134 switch (data[6]) {
135 case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC";
136 case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl";
137 case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK";
138 case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA";
139 case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host";
140 }
141 return "Vendor";
142}
143
144static void debug_fcp(const u8 *data, size_t length)
145{
146 unsigned int subunit_type, subunit_id, op;
147 const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
148
149 if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) {
150 subunit_type = data[1] >> 3;
151 subunit_id = data[1] & 7;
152 op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
153 printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
154 prefix, subunit_type, subunit_id, length,
155 debug_fcp_ctype(data[0]),
156 debug_fcp_opcode(op, data, length));
157 }
158
159 if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
160 print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1,
161 data, length, false);
162}
163
164static int __avc_write(struct firedtv *fdtv,
165 const struct avc_command_frame *c, struct avc_response_frame *r)
166{
167 int err, retry;
168
169 if (r)
170 fdtv->avc_reply_received = false;
171
172 for (retry = 0; retry < 6; retry++) {
173 if (unlikely(avc_debug))
174 debug_fcp(&c->ctype, c->length);
175
176 err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
177 (void *)&c->ctype, c->length);
178 if (err) {
179 fdtv->avc_reply_received = true;
180 dev_err(fdtv->device, "FCP command write failed\n");
181 return err;
182 }
183
184 if (!r)
185 return 0;
186
187 /*
188 * AV/C specs say that answers should be sent within 150 ms.
189 * Time out after 200 ms.
190 */
191 if (wait_event_timeout(fdtv->avc_wait,
192 fdtv->avc_reply_received,
193 msecs_to_jiffies(200)) != 0) {
194 r->length = fdtv->response_length;
195 memcpy(&r->response, fdtv->response, r->length);
196
197 return 0;
198 }
199 }
200 dev_err(fdtv->device, "FCP response timed out\n");
201 return -ETIMEDOUT;
202}
203
204static int avc_write(struct firedtv *fdtv,
205 const struct avc_command_frame *c, struct avc_response_frame *r)
206{
207 int ret;
208
209 if (mutex_lock_interruptible(&fdtv->avc_mutex))
210 return -EINTR;
211
212 ret = __avc_write(fdtv, c, r);
213
214 mutex_unlock(&fdtv->avc_mutex);
215 return ret;
216}
217
218int avc_recv(struct firedtv *fdtv, void *data, size_t length)
219{
220 struct avc_response_frame *r =
221 data - offsetof(struct avc_response_frame, response);
222
223 if (unlikely(avc_debug))
224 debug_fcp(data, length);
225
226 if (length >= 8 &&
227 r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
228 r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
229 r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
230 r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
231 if (r->response == AVC_RESPONSE_CHANGED) {
232 fdtv_handle_rc(fdtv,
233 r->operand[4] << 8 | r->operand[5]);
234 schedule_work(&fdtv->remote_ctrl_work);
235 } else if (r->response != AVC_RESPONSE_INTERIM) {
236 dev_info(fdtv->device,
237 "remote control result = %d\n", r->response);
238 }
239 return 0;
240 }
241
242 if (fdtv->avc_reply_received) {
243 dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
244 return -EIO;
245 }
246
247 memcpy(fdtv->response, data, length);
248 fdtv->response_length = length;
249
250 fdtv->avc_reply_received = true;
251 wake_up(&fdtv->avc_wait);
252
253 return 0;
254}
255
256/*
257 * tuning command for setting the relative LNB frequency
258 * (not supported by the AVC standard)
259 */
260static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
261 struct dvb_frontend_parameters *params,
262 struct avc_command_frame *c)
263{
264 c->opcode = AVC_OPCODE_VENDOR;
265
266 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
267 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
268 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
269 c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
270
271 c->operand[4] = (params->frequency >> 24) & 0xff;
272 c->operand[5] = (params->frequency >> 16) & 0xff;
273 c->operand[6] = (params->frequency >> 8) & 0xff;
274 c->operand[7] = params->frequency & 0xff;
275
276 c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
277 c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
278
279 switch (params->u.qpsk.fec_inner) {
280 case FEC_1_2: c->operand[10] = 0x1; break;
281 case FEC_2_3: c->operand[10] = 0x2; break;
282 case FEC_3_4: c->operand[10] = 0x3; break;
283 case FEC_5_6: c->operand[10] = 0x4; break;
284 case FEC_7_8: c->operand[10] = 0x5; break;
285 case FEC_4_5:
286 case FEC_8_9:
287 case FEC_AUTO:
288 default: c->operand[10] = 0x0;
289 }
290
291 if (fdtv->voltage == 0xff)
292 c->operand[11] = 0xff;
293 else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
294 c->operand[11] = 0;
295 else
296 c->operand[11] = 1;
297
298 if (fdtv->tone == 0xff)
299 c->operand[12] = 0xff;
300 else if (fdtv->tone == SEC_TONE_ON) /* band */
301 c->operand[12] = 1;
302 else
303 c->operand[12] = 0;
304
305 if (fdtv->type == FIREDTV_DVB_S2) {
306 c->operand[13] = 0x1;
307 c->operand[14] = 0xff;
308 c->operand[15] = 0xff;
309 c->length = 20;
310 } else {
311 c->length = 16;
312 }
313}
314
315static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
316 struct avc_command_frame *c)
317{
318 c->opcode = AVC_OPCODE_DSD;
319
320 c->operand[0] = 0; /* source plug */
321 c->operand[1] = 0xd2; /* subfunction replace */
322 c->operand[2] = 0x20; /* system id = DVB */
323 c->operand[3] = 0x00; /* antenna number */
324 c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
325
326 /* multiplex_valid_flags, high byte */
327 c->operand[5] = 0 << 7 /* reserved */
328 | 0 << 6 /* Polarisation */
329 | 0 << 5 /* Orbital_Pos */
330 | 1 << 4 /* Frequency */
331 | 1 << 3 /* Symbol_Rate */
332 | 0 << 2 /* FEC_outer */
333 | (params->u.qam.fec_inner != FEC_AUTO ? 1 << 1 : 0)
334 | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
335
336 /* multiplex_valid_flags, low byte */
337 c->operand[6] = 0 << 7 /* NetworkID */
338 | 0 << 0 /* reserved */ ;
339
340 c->operand[7] = 0x00;
341 c->operand[8] = 0x00;
342 c->operand[9] = 0x00;
343 c->operand[10] = 0x00;
344
345 c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
346 c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
347 c->operand[13] = (params->frequency / 4000) & 0xff;
348 c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
349 c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
350 c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
351 c->operand[17] = 0x00;
352
353 switch (params->u.qpsk.fec_inner) {
354 case FEC_1_2: c->operand[18] = 0x1; break;
355 case FEC_2_3: c->operand[18] = 0x2; break;
356 case FEC_3_4: c->operand[18] = 0x3; break;
357 case FEC_5_6: c->operand[18] = 0x4; break;
358 case FEC_7_8: c->operand[18] = 0x5; break;
359 case FEC_8_9: c->operand[18] = 0x6; break;
360 case FEC_4_5: c->operand[18] = 0x8; break;
361 case FEC_AUTO:
362 default: c->operand[18] = 0x0;
363 }
364
365 switch (params->u.qam.modulation) {
366 case QAM_16: c->operand[19] = 0x08; break;
367 case QAM_32: c->operand[19] = 0x10; break;
368 case QAM_64: c->operand[19] = 0x18; break;
369 case QAM_128: c->operand[19] = 0x20; break;
370 case QAM_256: c->operand[19] = 0x28; break;
371 case QAM_AUTO:
372 default: c->operand[19] = 0x00;
373 }
374
375 c->operand[20] = 0x00;
376 c->operand[21] = 0x00;
377 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
378 c->operand[22] = 0x00;
379
380 c->length = 28;
381}
382
383static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
384 struct avc_command_frame *c)
385{
386 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
387
388 c->opcode = AVC_OPCODE_DSD;
389
390 c->operand[0] = 0; /* source plug */
391 c->operand[1] = 0xd2; /* subfunction replace */
392 c->operand[2] = 0x20; /* system id = DVB */
393 c->operand[3] = 0x00; /* antenna number */
394 c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
395
396 /* multiplex_valid_flags, high byte */
397 c->operand[5] =
398 0 << 7 /* reserved */
399 | 1 << 6 /* CenterFrequency */
400 | (ofdm->bandwidth != BANDWIDTH_AUTO ? 1 << 5 : 0)
401 | (ofdm->constellation != QAM_AUTO ? 1 << 4 : 0)
402 | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
403 | (ofdm->code_rate_HP != FEC_AUTO ? 1 << 2 : 0)
404 | (ofdm->code_rate_LP != FEC_AUTO ? 1 << 1 : 0)
405 | (ofdm->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0);
406
407 /* multiplex_valid_flags, low byte */
408 c->operand[6] =
409 0 << 7 /* NetworkID */
410 | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
411 | 0 << 5 /* OtherFrequencyFlag */
412 | 0 << 0 /* reserved */ ;
413
414 c->operand[7] = 0x0;
415 c->operand[8] = (params->frequency / 10) >> 24;
416 c->operand[9] = ((params->frequency / 10) >> 16) & 0xff;
417 c->operand[10] = ((params->frequency / 10) >> 8) & 0xff;
418 c->operand[11] = (params->frequency / 10) & 0xff;
419
420 switch (ofdm->bandwidth) {
421 case BANDWIDTH_7_MHZ: c->operand[12] = 0x20; break;
422 case BANDWIDTH_8_MHZ:
423 case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
424 case BANDWIDTH_AUTO:
425 default: c->operand[12] = 0x00;
426 }
427
428 switch (ofdm->constellation) {
429 case QAM_16: c->operand[13] = 1 << 6; break;
430 case QAM_64: c->operand[13] = 2 << 6; break;
431 case QPSK:
432 default: c->operand[13] = 0x00;
433 }
434
435 switch (ofdm->hierarchy_information) {
436 case HIERARCHY_1: c->operand[13] |= 1 << 3; break;
437 case HIERARCHY_2: c->operand[13] |= 2 << 3; break;
438 case HIERARCHY_4: c->operand[13] |= 3 << 3; break;
439 case HIERARCHY_AUTO:
440 case HIERARCHY_NONE:
441 default: break;
442 }
443
444 switch (ofdm->code_rate_HP) {
445 case FEC_2_3: c->operand[13] |= 1; break;
446 case FEC_3_4: c->operand[13] |= 2; break;
447 case FEC_5_6: c->operand[13] |= 3; break;
448 case FEC_7_8: c->operand[13] |= 4; break;
449 case FEC_1_2:
450 default: break;
451 }
452
453 switch (ofdm->code_rate_LP) {
454 case FEC_2_3: c->operand[14] = 1 << 5; break;
455 case FEC_3_4: c->operand[14] = 2 << 5; break;
456 case FEC_5_6: c->operand[14] = 3 << 5; break;
457 case FEC_7_8: c->operand[14] = 4 << 5; break;
458 case FEC_1_2:
459 default: c->operand[14] = 0x00; break;
460 }
461
462 switch (ofdm->guard_interval) {
463 case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break;
464 case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break;
465 case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break;
466 case GUARD_INTERVAL_1_32:
467 case GUARD_INTERVAL_AUTO:
468 default: break;
469 }
470
471 switch (ofdm->transmission_mode) {
472 case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break;
473 case TRANSMISSION_MODE_2K:
474 case TRANSMISSION_MODE_AUTO:
475 default: break;
476 }
477
478 c->operand[15] = 0x00; /* network_ID[0] */
479 c->operand[16] = 0x00; /* network_ID[1] */
480 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
481 c->operand[17] = 0x00;
482
483 c->length = 24;
484}
485
486int avc_tuner_dsd(struct firedtv *fdtv,
487 struct dvb_frontend_parameters *params)
488{
489 char buffer[sizeof(struct avc_command_frame)];
490 struct avc_command_frame *c = (void *)buffer;
491 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
492
493 memset(c, 0, sizeof(*c));
494
495 c->ctype = AVC_CTYPE_CONTROL;
496 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
497
498 switch (fdtv->type) {
499 case FIREDTV_DVB_S:
500 case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
501 case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break;
502 case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break;
503 default:
504 BUG();
505 }
506
507 if (avc_write(fdtv, c, r) < 0)
508 return -EIO;
509
510 msleep(500);
511#if 0
512 /* FIXME: */
513 /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
514 if (status)
515 *status = r->operand[2];
516#endif
517 return 0;
518}
519
520int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
521{
522 char buffer[sizeof(struct avc_command_frame)];
523 struct avc_command_frame *c = (void *)buffer;
524 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
525 int pos, k;
526
527 if (pidc > 16 && pidc != 0xff)
528 return -EINVAL;
529
530 memset(c, 0, sizeof(*c));
531
532 c->ctype = AVC_CTYPE_CONTROL;
533 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
534 c->opcode = AVC_OPCODE_DSD;
535
536 c->operand[0] = 0; /* source plug */
537 c->operand[1] = 0xd2; /* subfunction replace */
538 c->operand[2] = 0x20; /* system id = DVB */
539 c->operand[3] = 0x00; /* antenna number */
540 c->operand[4] = 0x00; /* system_specific_multiplex selection_length */
541 c->operand[5] = pidc; /* Nr_of_dsd_sel_specs */
542
543 pos = 6;
544 if (pidc != 0xff)
545 for (k = 0; k < pidc; k++) {
546 c->operand[pos++] = 0x13; /* flowfunction relay */
547 c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
548 c->operand[pos++] = (pid[k] >> 8) & 0x1f;
549 c->operand[pos++] = pid[k] & 0xff;
550 c->operand[pos++] = 0x00; /* tableID */
551 c->operand[pos++] = 0x00; /* filter_length */
552 }
553
554 c->length = ALIGN(3 + pos, 4);
555
556 if (avc_write(fdtv, c, r) < 0)
557 return -EIO;
558
559 msleep(50);
560 return 0;
561}
562
563int avc_tuner_get_ts(struct firedtv *fdtv)
564{
565 char buffer[sizeof(struct avc_command_frame)];
566 struct avc_command_frame *c = (void *)buffer;
567 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
568 int sl;
569
570 memset(c, 0, sizeof(*c));
571
572 c->ctype = AVC_CTYPE_CONTROL;
573 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
574 c->opcode = AVC_OPCODE_DSIT;
575
576 sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
577
578 c->operand[0] = 0; /* source plug */
579 c->operand[1] = 0xd2; /* subfunction replace */
580 c->operand[2] = 0xff; /* status */
581 c->operand[3] = 0x20; /* system id = DVB */
582 c->operand[4] = 0x00; /* antenna number */
583 c->operand[5] = 0x0; /* system_specific_search_flags */
584 c->operand[6] = sl; /* system_specific_multiplex selection_length */
585 c->operand[7] = 0x00; /* valid_flags [0] */
586 c->operand[8] = 0x00; /* valid_flags [1] */
587 c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
588
589 c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
590
591 if (avc_write(fdtv, c, r) < 0)
592 return -EIO;
593
594 msleep(250);
595 return 0;
596}
597
598int avc_identify_subunit(struct firedtv *fdtv)
599{
600 char buffer[sizeof(struct avc_command_frame)];
601 struct avc_command_frame *c = (void *)buffer;
602 struct avc_response_frame *r = (void *)buffer;
603
604 memset(c, 0, sizeof(*c));
605
606 c->ctype = AVC_CTYPE_CONTROL;
607 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
608 c->opcode = AVC_OPCODE_READ_DESCRIPTOR;
609
610 c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
611 c->operand[1] = 0xff;
612 c->operand[2] = 0x00;
613 c->operand[3] = 0x00; /* length highbyte */
614 c->operand[4] = 0x08; /* length lowbyte */
615 c->operand[5] = 0x00; /* offset highbyte */
616 c->operand[6] = 0x0d; /* offset lowbyte */
617
618 c->length = 12;
619
620 if (avc_write(fdtv, c, r) < 0)
621 return -EIO;
622
623 if ((r->response != AVC_RESPONSE_STABLE &&
624 r->response != AVC_RESPONSE_ACCEPTED) ||
625 (r->operand[3] << 8) + r->operand[4] != 8) {
626 dev_err(fdtv->device, "cannot read subunit identifier\n");
627 return -EINVAL;
628 }
629 return 0;
630}
631
632#define SIZEOF_ANTENNA_INPUT_INFO 22
633
634int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
635{
636 char buffer[sizeof(struct avc_command_frame)];
637 struct avc_command_frame *c = (void *)buffer;
638 struct avc_response_frame *r = (void *)buffer;
639 int length;
640
641 memset(c, 0, sizeof(*c));
642
643 c->ctype = AVC_CTYPE_CONTROL;
644 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
645 c->opcode = AVC_OPCODE_READ_DESCRIPTOR;
646
647 c->operand[0] = DESCRIPTOR_TUNER_STATUS;
648 c->operand[1] = 0xff; /* read_result_status */
649 c->operand[2] = 0x00; /* reserved */
650 c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
651 c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
652 c->operand[5] = 0x00;
653 c->operand[6] = 0x00;
654
655 c->length = 12;
656
657 if (avc_write(fdtv, c, r) < 0)
658 return -EIO;
659
660 if (r->response != AVC_RESPONSE_STABLE &&
661 r->response != AVC_RESPONSE_ACCEPTED) {
662 dev_err(fdtv->device, "cannot read tuner status\n");
663 return -EINVAL;
664 }
665
666 length = r->operand[9];
667 if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
668 dev_err(fdtv->device, "got invalid tuner status\n");
669 return -EINVAL;
670 }
671
672 stat->active_system = r->operand[10];
673 stat->searching = r->operand[11] >> 7 & 1;
674 stat->moving = r->operand[11] >> 6 & 1;
675 stat->no_rf = r->operand[11] >> 5 & 1;
676 stat->input = r->operand[12] >> 7 & 1;
677 stat->selected_antenna = r->operand[12] & 0x7f;
678 stat->ber = r->operand[13] << 24 |
679 r->operand[14] << 16 |
680 r->operand[15] << 8 |
681 r->operand[16];
682 stat->signal_strength = r->operand[17];
683 stat->raster_frequency = r->operand[18] >> 6 & 2;
684 stat->rf_frequency = (r->operand[18] & 0x3f) << 16 |
685 r->operand[19] << 8 |
686 r->operand[20];
687 stat->man_dep_info_length = r->operand[21];
688 stat->front_end_error = r->operand[22] >> 4 & 1;
689 stat->antenna_error = r->operand[22] >> 3 & 1;
690 stat->front_end_power_status = r->operand[22] >> 1 & 1;
691 stat->power_supply = r->operand[22] & 1;
692 stat->carrier_noise_ratio = r->operand[23] << 8 |
693 r->operand[24];
694 stat->power_supply_voltage = r->operand[27];
695 stat->antenna_voltage = r->operand[28];
696 stat->firewire_bus_voltage = r->operand[29];
697 stat->ca_mmi = r->operand[30] & 1;
698 stat->ca_pmt_reply = r->operand[31] >> 7 & 1;
699 stat->ca_date_time_request = r->operand[31] >> 6 & 1;
700 stat->ca_application_info = r->operand[31] >> 5 & 1;
701 stat->ca_module_present_status = r->operand[31] >> 4 & 1;
702 stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
703 stat->ca_error_flag = r->operand[31] >> 2 & 1;
704 stat->ca_initialization_status = r->operand[31] >> 1 & 1;
705
706 return 0;
707}
708
709int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
710 char conttone, char nrdiseq,
711 struct dvb_diseqc_master_cmd *diseqcmd)
712{
713 char buffer[sizeof(struct avc_command_frame)];
714 struct avc_command_frame *c = (void *)buffer;
715 struct avc_response_frame *r = (void *)buffer;
716 int i, j, k;
717
718 memset(c, 0, sizeof(*c));
719
720 c->ctype = AVC_CTYPE_CONTROL;
721 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
722 c->opcode = AVC_OPCODE_VENDOR;
723
724 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
725 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
726 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
727 c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
728
729 c->operand[4] = voltage;
730 c->operand[5] = nrdiseq;
731
732 i = 6;
733
734 for (j = 0; j < nrdiseq; j++) {
735 c->operand[i++] = diseqcmd[j].msg_len;
736
737 for (k = 0; k < diseqcmd[j].msg_len; k++)
738 c->operand[i++] = diseqcmd[j].msg[k];
739 }
740
741 c->operand[i++] = burst;
742 c->operand[i++] = conttone;
743
744 c->length = ALIGN(3 + i, 4);
745
746 if (avc_write(fdtv, c, r) < 0)
747 return -EIO;
748
749 if (r->response != AVC_RESPONSE_ACCEPTED) {
750 dev_err(fdtv->device, "LNB control failed\n");
751 return -EINVAL;
752 }
753
754 return 0;
755}
756
757int avc_register_remote_control(struct firedtv *fdtv)
758{
759 char buffer[sizeof(struct avc_command_frame)];
760 struct avc_command_frame *c = (void *)buffer;
761
762 memset(c, 0, sizeof(*c));
763
764 c->ctype = AVC_CTYPE_NOTIFY;
765 c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
766 c->opcode = AVC_OPCODE_VENDOR;
767
768 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
769 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
770 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
771 c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
772
773 c->length = 8;
774
775 return avc_write(fdtv, c, NULL);
776}
777
778void avc_remote_ctrl_work(struct work_struct *work)
779{
780 struct firedtv *fdtv =
781 container_of(work, struct firedtv, remote_ctrl_work);
782
783 /* Should it be rescheduled in failure cases? */
784 avc_register_remote_control(fdtv);
785}
786
787#if 0 /* FIXME: unused */
788int avc_tuner_host2ca(struct firedtv *fdtv)
789{
790 char buffer[sizeof(struct avc_command_frame)];
791 struct avc_command_frame *c = (void *)buffer;
792 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
793
794 memset(c, 0, sizeof(*c));
795
796 c->ctype = AVC_CTYPE_CONTROL;
797 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
798 c->opcode = AVC_OPCODE_VENDOR;
799
800 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
801 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
802 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
803 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
804 c->operand[4] = 0; /* slot */
805 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
806 c->operand[6] = 0; /* more/last */
807 c->operand[7] = 0; /* length */
808
809 c->length = 12;
810
811 if (avc_write(fdtv, c, r) < 0)
812 return -EIO;
813
814 return 0;
815}
816#endif
817
818static int get_ca_object_pos(struct avc_response_frame *r)
819{
820 int length = 1;
821
822 /* Check length of length field */
823 if (r->operand[7] & 0x80)
824 length = (r->operand[7] & 0x7f) + 1;
825 return length + 7;
826}
827
828static int get_ca_object_length(struct avc_response_frame *r)
829{
830#if 0 /* FIXME: unused */
831 int size = 0;
832 int i;
833
834 if (r->operand[7] & 0x80)
835 for (i = 0; i < (r->operand[7] & 0x7f); i++) {
836 size <<= 8;
837 size += r->operand[8 + i];
838 }
839#endif
840 return r->operand[7];
841}
842
843int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
844{
845 char buffer[sizeof(struct avc_command_frame)];
846 struct avc_command_frame *c = (void *)buffer;
847 struct avc_response_frame *r = (void *)buffer;
848 int pos;
849
850 memset(c, 0, sizeof(*c));
851
852 c->ctype = AVC_CTYPE_STATUS;
853 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
854 c->opcode = AVC_OPCODE_VENDOR;
855
856 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
857 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
858 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
859 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
860 c->operand[4] = 0; /* slot */
861 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
862
863 c->length = 12;
864
865 if (avc_write(fdtv, c, r) < 0)
866 return -EIO;
867
868 /* FIXME: check response code and validate response data */
869
870 pos = get_ca_object_pos(r);
871 app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
872 app_info[1] = (EN50221_TAG_APP_INFO >> 8) & 0xff;
873 app_info[2] = (EN50221_TAG_APP_INFO >> 0) & 0xff;
874 app_info[3] = 6 + r->operand[pos + 4];
875 app_info[4] = 0x01;
876 memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
877 *len = app_info[3] + 4;
878
879 return 0;
880}
881
882int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
883{
884 char buffer[sizeof(struct avc_command_frame)];
885 struct avc_command_frame *c = (void *)buffer;
886 struct avc_response_frame *r = (void *)buffer;
887 int pos;
888
889 memset(c, 0, sizeof(*c));
890
891 c->ctype = AVC_CTYPE_STATUS;
892 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
893 c->opcode = AVC_OPCODE_VENDOR;
894
895 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
896 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
897 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
898 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
899 c->operand[4] = 0; /* slot */
900 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
901
902 c->length = 12;
903
904 if (avc_write(fdtv, c, r) < 0)
905 return -EIO;
906
907 pos = get_ca_object_pos(r);
908 app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
909 app_info[1] = (EN50221_TAG_CA_INFO >> 8) & 0xff;
910 app_info[2] = (EN50221_TAG_CA_INFO >> 0) & 0xff;
911 app_info[3] = 2;
912 app_info[4] = r->operand[pos + 0];
913 app_info[5] = r->operand[pos + 1];
914 *len = app_info[3] + 4;
915
916 return 0;
917}
918
919int avc_ca_reset(struct firedtv *fdtv)
920{
921 char buffer[sizeof(struct avc_command_frame)];
922 struct avc_command_frame *c = (void *)buffer;
923 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
924
925 memset(c, 0, sizeof(*c));
926
927 c->ctype = AVC_CTYPE_CONTROL;
928 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
929 c->opcode = AVC_OPCODE_VENDOR;
930
931 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
932 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
933 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
934 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
935 c->operand[4] = 0; /* slot */
936 c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
937 c->operand[6] = 0; /* more/last */
938 c->operand[7] = 1; /* length */
939 c->operand[8] = 0; /* force hardware reset */
940
941 c->length = 12;
942
943 if (avc_write(fdtv, c, r) < 0)
944 return -EIO;
945
946 return 0;
947}
948
949int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
950{
951 char buffer[sizeof(struct avc_command_frame)];
952 struct avc_command_frame *c = (void *)buffer;
953 struct avc_response_frame *r = (void *)buffer;
954 int list_management;
955 int program_info_length;
956 int pmt_cmd_id;
957 int read_pos;
958 int write_pos;
959 int es_info_length;
960 int crc32_csum;
961
962 memset(c, 0, sizeof(*c));
963
964 c->ctype = AVC_CTYPE_CONTROL;
965 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
966 c->opcode = AVC_OPCODE_VENDOR;
967
968 if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
969 dev_info(fdtv->device, "forcing list_management to ONLY\n");
970 msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
971 }
972 /* We take the cmd_id from the programme level only! */
973 list_management = msg[0];
974 program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
975 if (program_info_length > 0)
976 program_info_length--; /* Remove pmt_cmd_id */
977 pmt_cmd_id = msg[6];
978
979 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
980 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
981 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
982 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
983 c->operand[4] = 0; /* slot */
984 c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
985 c->operand[6] = 0; /* more/last */
986 /* c->operand[7] = XXXprogram_info_length + 17; */ /* length */
987 c->operand[8] = list_management;
988 c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */
989
990 /* TS program map table */
991
992 c->operand[10] = 0x02; /* Table id=2 */
993 c->operand[11] = 0x80; /* Section syntax + length */
994 /* c->operand[12] = XXXprogram_info_length + 12; */
995 c->operand[13] = msg[1]; /* Program number */
996 c->operand[14] = msg[2];
997 c->operand[15] = 0x01; /* Version number=0 + current/next=1 */
998 c->operand[16] = 0x00; /* Section number=0 */
999 c->operand[17] = 0x00; /* Last section number=0 */
1000 c->operand[18] = 0x1f; /* PCR_PID=1FFF */
1001 c->operand[19] = 0xff;
1002 c->operand[20] = (program_info_length >> 8); /* Program info length */
1003 c->operand[21] = (program_info_length & 0xff);
1004
1005 /* CA descriptors at programme level */
1006 read_pos = 6;
1007 write_pos = 22;
1008 if (program_info_length > 0) {
1009 pmt_cmd_id = msg[read_pos++];
1010 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1011 dev_err(fdtv->device,
1012 "invalid pmt_cmd_id %d\n", pmt_cmd_id);
1013
1014 memcpy(&c->operand[write_pos], &msg[read_pos],
1015 program_info_length);
1016 read_pos += program_info_length;
1017 write_pos += program_info_length;
1018 }
1019 while (read_pos < length) {
1020 c->operand[write_pos++] = msg[read_pos++];
1021 c->operand[write_pos++] = msg[read_pos++];
1022 c->operand[write_pos++] = msg[read_pos++];
1023 es_info_length =
1024 ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
1025 read_pos += 2;
1026 if (es_info_length > 0)
1027 es_info_length--; /* Remove pmt_cmd_id */
1028 c->operand[write_pos++] = es_info_length >> 8;
1029 c->operand[write_pos++] = es_info_length & 0xff;
1030 if (es_info_length > 0) {
1031 pmt_cmd_id = msg[read_pos++];
1032 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1033 dev_err(fdtv->device, "invalid pmt_cmd_id %d "
1034 "at stream level\n", pmt_cmd_id);
1035
1036 memcpy(&c->operand[write_pos], &msg[read_pos],
1037 es_info_length);
1038 read_pos += es_info_length;
1039 write_pos += es_info_length;
1040 }
1041 }
1042
1043 /* CRC */
1044 c->operand[write_pos++] = 0x00;
1045 c->operand[write_pos++] = 0x00;
1046 c->operand[write_pos++] = 0x00;
1047 c->operand[write_pos++] = 0x00;
1048
1049 c->operand[7] = write_pos - 8;
1050 c->operand[12] = write_pos - 13;
1051
1052 crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
1053 c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
1054 c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
1055 c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
1056 c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
1057
1058 c->length = ALIGN(3 + write_pos, 4);
1059
1060 if (avc_write(fdtv, c, r) < 0)
1061 return -EIO;
1062
1063 if (r->response != AVC_RESPONSE_ACCEPTED) {
1064 dev_err(fdtv->device,
1065 "CA PMT failed with response 0x%x\n", r->response);
1066 return -EFAULT;
1067 }
1068
1069 return 0;
1070}
1071
1072int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1073{
1074 char buffer[sizeof(struct avc_command_frame)];
1075 struct avc_command_frame *c = (void *)buffer;
1076 struct avc_response_frame *r = (void *)buffer;
1077
1078 memset(c, 0, sizeof(*c));
1079
1080 c->ctype = AVC_CTYPE_STATUS;
1081 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1082 c->opcode = AVC_OPCODE_VENDOR;
1083
1084 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1085 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1086 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1087 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1088 c->operand[4] = 0; /* slot */
1089 c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
1090 c->operand[6] = 0; /* more/last */
1091 c->operand[7] = 0; /* length */
1092
1093 c->length = 12;
1094
1095 if (avc_write(fdtv, c, r) < 0)
1096 return -EIO;
1097
1098 /* FIXME: check response code and validate response data */
1099
1100 *interval = r->operand[get_ca_object_pos(r)];
1101
1102 return 0;
1103}
1104
1105int avc_ca_enter_menu(struct firedtv *fdtv)
1106{
1107 char buffer[sizeof(struct avc_command_frame)];
1108 struct avc_command_frame *c = (void *)buffer;
1109 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
1110
1111 memset(c, 0, sizeof(*c));
1112
1113 c->ctype = AVC_CTYPE_STATUS;
1114 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1115 c->opcode = AVC_OPCODE_VENDOR;
1116
1117 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1118 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1119 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1120 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1121 c->operand[4] = 0; /* slot */
1122 c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
1123 c->operand[6] = 0; /* more/last */
1124 c->operand[7] = 0; /* length */
1125
1126 c->length = 12;
1127
1128 if (avc_write(fdtv, c, r) < 0)
1129 return -EIO;
1130
1131 return 0;
1132}
1133
1134int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1135{
1136 char buffer[sizeof(struct avc_command_frame)];
1137 struct avc_command_frame *c = (void *)buffer;
1138 struct avc_response_frame *r = (void *)buffer;
1139
1140 memset(c, 0, sizeof(*c));
1141
1142 c->ctype = AVC_CTYPE_STATUS;
1143 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1144 c->opcode = AVC_OPCODE_VENDOR;
1145
1146 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1147 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1148 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1149 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1150 c->operand[4] = 0; /* slot */
1151 c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
1152 c->operand[6] = 0; /* more/last */
1153 c->operand[7] = 0; /* length */
1154
1155 c->length = 12;
1156
1157 if (avc_write(fdtv, c, r) < 0)
1158 return -EIO;
1159
1160 /* FIXME: check response code and validate response data */
1161
1162 *len = get_ca_object_length(r);
1163 memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
1164
1165 return 0;
1166}
1167
1168#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
1169
1170static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
1171{
1172 int ret;
1173
1174 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1175 return -EINTR;
1176
1177 ret = fdtv->backend->read(fdtv, addr, buf, len);
1178 if (ret < 0)
1179 dev_err(fdtv->device, "CMP: read I/O error\n");
1180
1181 mutex_unlock(&fdtv->avc_mutex);
1182 return ret;
1183}
1184
1185static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg)
1186{
1187 int ret;
1188
1189 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1190 return -EINTR;
1191
1192 ret = fdtv->backend->lock(fdtv, addr, data, arg);
1193 if (ret < 0)
1194 dev_err(fdtv->device, "CMP: lock I/O error\n");
1195
1196 mutex_unlock(&fdtv->avc_mutex);
1197 return ret;
1198}
1199
1200static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
1201{
1202 return (be32_to_cpu(opcr) >> shift) & mask;
1203}
1204
1205static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
1206{
1207 *opcr &= ~cpu_to_be32(mask << shift);
1208 *opcr |= cpu_to_be32((value & mask) << shift);
1209}
1210
1211#define get_opcr_online(v) get_opcr((v), 0x1, 31)
1212#define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
1213#define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
1214
1215#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
1216#define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
1217#define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
1218#define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
1219
1220int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
1221{
1222 __be32 old_opcr, opcr;
1223 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1224 int attempts = 0;
1225 int ret;
1226
1227 ret = cmp_read(fdtv, &opcr, opcr_address, 4);
1228 if (ret < 0)
1229 return ret;
1230
1231repeat:
1232 if (!get_opcr_online(opcr)) {
1233 dev_err(fdtv->device, "CMP: output offline\n");
1234 return -EBUSY;
1235 }
1236
1237 old_opcr = opcr;
1238
1239 if (get_opcr_p2p_connections(opcr)) {
1240 if (get_opcr_channel(opcr) != channel) {
1241 dev_err(fdtv->device, "CMP: cannot change channel\n");
1242 return -EBUSY;
1243 }
1244 dev_info(fdtv->device, "CMP: overlaying connection\n");
1245
1246 /* We don't allocate isochronous resources. */
1247 } else {
1248 set_opcr_channel(&opcr, channel);
1249 set_opcr_data_rate(&opcr, 2); /* S400 */
1250
1251 /* FIXME: this is for the worst case - optimize */
1252 set_opcr_overhead_id(&opcr, 0);
1253
1254 /*
1255 * FIXME: allocate isochronous channel and bandwidth at IRM
1256 * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
1257 */
1258 }
1259
1260 set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
1261
1262 ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr);
1263 if (ret < 0)
1264 return ret;
1265
1266 if (old_opcr != opcr) {
1267 /*
1268 * FIXME: if old_opcr.P2P_Connections > 0,
1269 * deallocate isochronous channel and bandwidth at IRM
1270 * if (...)
1271 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1272 */
1273
1274 if (++attempts < 6) /* arbitrary limit */
1275 goto repeat;
1276 return -EBUSY;
1277 }
1278
1279 return 0;
1280}
1281
1282void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
1283{
1284 __be32 old_opcr, opcr;
1285 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1286 int attempts = 0;
1287
1288 if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
1289 return;
1290
1291repeat:
1292 if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
1293 get_opcr_channel(opcr) != channel) {
1294 dev_err(fdtv->device, "CMP: no connection to break\n");
1295 return;
1296 }
1297
1298 old_opcr = opcr;
1299 set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
1300
1301 if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0)
1302 return;
1303
1304 if (old_opcr != opcr) {
1305 /*
1306 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
1307 * owner, deallocate isochronous channel and bandwidth at IRM
1308 * if (...)
1309 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1310 */
1311
1312 if (++attempts < 6) /* arbitrary limit */
1313 goto repeat;
1314 }
1315}
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index 6d87926b8bfe..eeb80d0ea3ff 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -10,33 +10,37 @@
10 * the License, or (at your option) any later version. 10 * the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <linux/device.h>
13#include <linux/dvb/ca.h> 14#include <linux/dvb/ca.h>
14#include <linux/fs.h> 15#include <linux/fs.h>
15#include <linux/module.h> 16#include <linux/module.h>
16 17
17#include <dvbdev.h> 18#include <dvbdev.h>
18 19
19#include "avc.h"
20#include "firedtv.h" 20#include "firedtv.h"
21#include "firedtv-ci.h"
22 21
23static int fdtv_ca_ready(ANTENNA_INPUT_INFO *info) 22#define EN50221_TAG_APP_INFO_ENQUIRY 0x9f8020
23#define EN50221_TAG_CA_INFO_ENQUIRY 0x9f8030
24#define EN50221_TAG_CA_PMT 0x9f8032
25#define EN50221_TAG_ENTER_MENU 0x9f8022
26
27static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
24{ 28{
25 return info->CaInitializationStatus == 1 && 29 return stat->ca_initialization_status == 1 &&
26 info->CaErrorFlag == 0 && 30 stat->ca_error_flag == 0 &&
27 info->CaDvbFlag == 1 && 31 stat->ca_dvb_flag == 1 &&
28 info->CaModulePresentStatus == 1; 32 stat->ca_module_present_status == 1;
29} 33}
30 34
31static int fdtv_get_ca_flags(ANTENNA_INPUT_INFO *info) 35static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
32{ 36{
33 int flags = 0; 37 int flags = 0;
34 38
35 if (info->CaModulePresentStatus == 1) 39 if (stat->ca_module_present_status == 1)
36 flags |= CA_CI_MODULE_PRESENT; 40 flags |= CA_CI_MODULE_PRESENT;
37 if (info->CaInitializationStatus == 1 && 41 if (stat->ca_initialization_status == 1 &&
38 info->CaErrorFlag == 0 && 42 stat->ca_error_flag == 0 &&
39 info->CaDvbFlag == 1) 43 stat->ca_dvb_flag == 1)
40 flags |= CA_CI_MODULE_READY; 44 flags |= CA_CI_MODULE_READY;
41 return flags; 45 return flags;
42} 46}
@@ -59,17 +63,17 @@ static int fdtv_ca_get_caps(void *arg)
59 63
60static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg) 64static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
61{ 65{
62 ANTENNA_INPUT_INFO info; 66 struct firedtv_tuner_status stat;
63 struct ca_slot_info *slot = arg; 67 struct ca_slot_info *slot = arg;
64 68
65 if (avc_tuner_status(fdtv, &info)) 69 if (avc_tuner_status(fdtv, &stat))
66 return -EFAULT; 70 return -EFAULT;
67 71
68 if (slot->num != 0) 72 if (slot->num != 0)
69 return -EFAULT; 73 return -EFAULT;
70 74
71 slot->type = CA_CI; 75 slot->type = CA_CI;
72 slot->flags = fdtv_get_ca_flags(&info); 76 slot->flags = fdtv_get_ca_flags(&stat);
73 return 0; 77 return 0;
74} 78}
75 79
@@ -77,8 +81,7 @@ static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
77{ 81{
78 struct ca_msg *reply = arg; 82 struct ca_msg *reply = arg;
79 83
80 return 84 return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
81 avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
82} 85}
83 86
84static int fdtv_ca_info(struct firedtv *fdtv, void *arg) 87static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
@@ -92,30 +95,29 @@ static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
92{ 95{
93 struct ca_msg *reply = arg; 96 struct ca_msg *reply = arg;
94 97
95 return 98 return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
96 avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
97} 99}
98 100
99static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg) 101static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
100{ 102{
101 ANTENNA_INPUT_INFO info; 103 struct firedtv_tuner_status stat;
102 int err; 104 int err;
103 105
104 switch (fdtv->ca_last_command) { 106 switch (fdtv->ca_last_command) {
105 case TAG_APP_INFO_ENQUIRY: 107 case EN50221_TAG_APP_INFO_ENQUIRY:
106 err = fdtv_ca_app_info(fdtv, arg); 108 err = fdtv_ca_app_info(fdtv, arg);
107 break; 109 break;
108 case TAG_CA_INFO_ENQUIRY: 110 case EN50221_TAG_CA_INFO_ENQUIRY:
109 err = fdtv_ca_info(fdtv, arg); 111 err = fdtv_ca_info(fdtv, arg);
110 break; 112 break;
111 default: 113 default:
112 if (avc_tuner_status(fdtv, &info)) 114 if (avc_tuner_status(fdtv, &stat))
113 err = -EFAULT; 115 err = -EFAULT;
114 else if (info.CaMmi == 1) 116 else if (stat.ca_mmi == 1)
115 err = fdtv_ca_get_mmi(fdtv, arg); 117 err = fdtv_ca_get_mmi(fdtv, arg);
116 else { 118 else {
117 printk(KERN_INFO "%s: Unhandled message 0x%08X\n", 119 dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
118 __func__, fdtv->ca_last_command); 120 fdtv->ca_last_command);
119 err = -EFAULT; 121 err = -EFAULT;
120 } 122 }
121 } 123 }
@@ -133,14 +135,13 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
133 data_pos = 4; 135 data_pos = 4;
134 if (msg->msg[3] & 0x80) { 136 if (msg->msg[3] & 0x80) {
135 data_length = 0; 137 data_length = 0;
136 for (i = 0; i < (msg->msg[3] & 0x7F); i++) 138 for (i = 0; i < (msg->msg[3] & 0x7f); i++)
137 data_length = (data_length << 8) + msg->msg[data_pos++]; 139 data_length = (data_length << 8) + msg->msg[data_pos++];
138 } else { 140 } else {
139 data_length = msg->msg[3]; 141 data_length = msg->msg[3];
140 } 142 }
141 143
142 return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? 144 return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
143 -EFAULT : 0;
144} 145}
145 146
146static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg) 147static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
@@ -152,23 +153,23 @@ static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
152 fdtv->ca_last_command = 153 fdtv->ca_last_command =
153 (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2]; 154 (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
154 switch (fdtv->ca_last_command) { 155 switch (fdtv->ca_last_command) {
155 case TAG_CA_PMT: 156 case EN50221_TAG_CA_PMT:
156 err = fdtv_ca_pmt(fdtv, arg); 157 err = fdtv_ca_pmt(fdtv, arg);
157 break; 158 break;
158 case TAG_APP_INFO_ENQUIRY: 159 case EN50221_TAG_APP_INFO_ENQUIRY:
159 /* handled in ca_get_msg */ 160 /* handled in ca_get_msg */
160 err = 0; 161 err = 0;
161 break; 162 break;
162 case TAG_CA_INFO_ENQUIRY: 163 case EN50221_TAG_CA_INFO_ENQUIRY:
163 /* handled in ca_get_msg */ 164 /* handled in ca_get_msg */
164 err = 0; 165 err = 0;
165 break; 166 break;
166 case TAG_ENTER_MENU: 167 case EN50221_TAG_ENTER_MENU:
167 err = avc_ca_enter_menu(fdtv); 168 err = avc_ca_enter_menu(fdtv);
168 break; 169 break;
169 default: 170 default:
170 printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n", 171 dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
171 __func__, fdtv->ca_last_command); 172 fdtv->ca_last_command);
172 err = -EFAULT; 173 err = -EFAULT;
173 } 174 }
174 return err; 175 return err;
@@ -179,10 +180,10 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
179{ 180{
180 struct dvb_device *dvbdev = file->private_data; 181 struct dvb_device *dvbdev = file->private_data;
181 struct firedtv *fdtv = dvbdev->priv; 182 struct firedtv *fdtv = dvbdev->priv;
182 ANTENNA_INPUT_INFO info; 183 struct firedtv_tuner_status stat;
183 int err; 184 int err;
184 185
185 switch(cmd) { 186 switch (cmd) {
186 case CA_RESET: 187 case CA_RESET:
187 err = fdtv_ca_reset(fdtv); 188 err = fdtv_ca_reset(fdtv);
188 break; 189 break;
@@ -199,13 +200,12 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
199 err = fdtv_ca_send_msg(fdtv, arg); 200 err = fdtv_ca_send_msg(fdtv, arg);
200 break; 201 break;
201 default: 202 default:
202 printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__, 203 dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
203 cmd);
204 err = -EOPNOTSUPP; 204 err = -EOPNOTSUPP;
205 } 205 }
206 206
207 /* FIXME Is this necessary? */ 207 /* FIXME Is this necessary? */
208 avc_tuner_status(fdtv, &info); 208 avc_tuner_status(fdtv, &stat);
209 209
210 return err; 210 return err;
211} 211}
@@ -233,22 +233,21 @@ static struct dvb_device fdtv_ca = {
233 233
234int fdtv_ca_register(struct firedtv *fdtv) 234int fdtv_ca_register(struct firedtv *fdtv)
235{ 235{
236 ANTENNA_INPUT_INFO info; 236 struct firedtv_tuner_status stat;
237 int err; 237 int err;
238 238
239 if (avc_tuner_status(fdtv, &info)) 239 if (avc_tuner_status(fdtv, &stat))
240 return -EINVAL; 240 return -EINVAL;
241 241
242 if (!fdtv_ca_ready(&info)) 242 if (!fdtv_ca_ready(&stat))
243 return -EFAULT; 243 return -EFAULT;
244 244
245 err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, 245 err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
246 &fdtv_ca, fdtv, DVB_DEVICE_CA); 246 &fdtv_ca, fdtv, DVB_DEVICE_CA);
247 247
248 if (info.CaApplicationInfo == 0) 248 if (stat.ca_application_info == 0)
249 printk(KERN_ERR "%s: CaApplicationInfo is not set.\n", 249 dev_err(fdtv->device, "CaApplicationInfo is not set\n");
250 __func__); 250 if (stat.ca_date_time_request == 1)
251 if (info.CaDateTimeRequest == 1)
252 avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval); 251 avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
253 252
254 return err; 253 return err;
diff --git a/drivers/media/dvb/firewire/firedtv-ci.h b/drivers/media/dvb/firewire/firedtv-ci.h
deleted file mode 100644
index d6840f5dcbae..000000000000
--- a/drivers/media/dvb/firewire/firedtv-ci.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#ifndef _FIREDTV_CI_H
2#define _FIREDTV_CI_H
3
4struct firedtv;
5
6int fdtv_ca_register(struct firedtv *fdtv);
7void fdtv_ca_release(struct firedtv *fdtv);
8
9#endif /* _FIREDTV_CI_H */
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
index 1823058696f2..9d308dd32a5c 100644
--- a/drivers/media/dvb/firewire/firedtv-dvb.c
+++ b/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -10,75 +10,55 @@
10 * the License, or (at your option) any later version. 10 * the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <linux/bitops.h>
14#include <linux/device.h>
13#include <linux/errno.h> 15#include <linux/errno.h>
14#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/mod_devicetable.h>
18#include <linux/module.h>
15#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/slab.h>
21#include <linux/string.h>
16#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/wait.h>
24#include <linux/workqueue.h>
17 25
26#include <dmxdev.h>
18#include <dvb_demux.h> 27#include <dvb_demux.h>
19#include <dvb_frontend.h>
20#include <dvbdev.h> 28#include <dvbdev.h>
29#include <dvb_frontend.h>
21 30
22#include "avc.h"
23#include "firedtv.h" 31#include "firedtv.h"
24#include "firedtv-ci.h"
25
26DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
27 32
28static struct firedtv_channel *fdtv_channel_allocate(struct firedtv *fdtv) 33static int alloc_channel(struct firedtv *fdtv)
29{ 34{
30 struct firedtv_channel *c = NULL; 35 int i;
31 int k;
32 36
33 if (mutex_lock_interruptible(&fdtv->demux_mutex)) 37 for (i = 0; i < 16; i++)
34 return NULL; 38 if (!__test_and_set_bit(i, &fdtv->channel_active))
35
36 for (k = 0; k < 16; k++)
37 if (!fdtv->channel[k].active) {
38 fdtv->channel[k].active = true;
39 c = &fdtv->channel[k];
40 break; 39 break;
41 } 40 return i;
42
43 mutex_unlock(&fdtv->demux_mutex);
44 return c;
45} 41}
46 42
47static int fdtv_channel_collect(struct firedtv *fdtv, int *pidc, u16 pid[]) 43static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
48{ 44{
49 int k, l = 0; 45 int i, n;
50
51 if (mutex_lock_interruptible(&fdtv->demux_mutex))
52 return -EINTR;
53
54 for (k = 0; k < 16; k++)
55 if (fdtv->channel[k].active)
56 pid[l++] = fdtv->channel[k].pid;
57
58 mutex_unlock(&fdtv->demux_mutex);
59 46
60 *pidc = l; 47 for (i = 0, n = 0; i < 16; i++)
61 48 if (test_bit(i, &fdtv->channel_active))
62 return 0; 49 pid[n++] = fdtv->channel_pid[i];
50 *pidc = n;
63} 51}
64 52
65static int fdtv_channel_release(struct firedtv *fdtv, 53static inline void dealloc_channel(struct firedtv *fdtv, int i)
66 struct firedtv_channel *channel)
67{ 54{
68 if (mutex_lock_interruptible(&fdtv->demux_mutex)) 55 __clear_bit(i, &fdtv->channel_active);
69 return -EINTR;
70
71 channel->active = false;
72
73 mutex_unlock(&fdtv->demux_mutex);
74 return 0;
75} 56}
76 57
77int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed) 58int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
78{ 59{
79 struct firedtv *fdtv = (struct firedtv*)dvbdmxfeed->demux->priv; 60 struct firedtv *fdtv = dvbdmxfeed->demux->priv;
80 struct firedtv_channel *channel; 61 int pidc, c, ret;
81 int pidc,k;
82 u16 pids[16]; 62 u16 pids[16];
83 63
84 switch (dvbdmxfeed->type) { 64 switch (dvbdmxfeed->type) {
@@ -86,11 +66,14 @@ int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
86 case DMX_TYPE_SEC: 66 case DMX_TYPE_SEC:
87 break; 67 break;
88 default: 68 default:
89 printk(KERN_ERR "%s: invalid type %u\n", 69 dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
90 __func__, dvbdmxfeed->type); 70 dvbdmxfeed->type);
91 return -EINVAL; 71 return -EINVAL;
92 } 72 }
93 73
74 if (mutex_lock_interruptible(&fdtv->demux_mutex))
75 return -EINTR;
76
94 if (dvbdmxfeed->type == DMX_TYPE_TS) { 77 if (dvbdmxfeed->type == DMX_TYPE_TS) {
95 switch (dvbdmxfeed->pes_type) { 78 switch (dvbdmxfeed->pes_type) {
96 case DMX_TS_PES_VIDEO: 79 case DMX_TS_PES_VIDEO:
@@ -98,75 +81,64 @@ int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
98 case DMX_TS_PES_TELETEXT: 81 case DMX_TS_PES_TELETEXT:
99 case DMX_TS_PES_PCR: 82 case DMX_TS_PES_PCR:
100 case DMX_TS_PES_OTHER: 83 case DMX_TS_PES_OTHER:
101 //Dirty fix to keep fdtv->channel pid-list up to date 84 c = alloc_channel(fdtv);
102 for(k=0;k<16;k++){
103 if (!fdtv->channel[k].active)
104 fdtv->channel[k].pid =
105 dvbdmxfeed->pid;
106 break;
107 }
108 channel = fdtv_channel_allocate(fdtv);
109 break; 85 break;
110 default: 86 default:
111 printk(KERN_ERR "%s: invalid pes type %u\n", 87 dev_err(fdtv->device,
112 __func__, dvbdmxfeed->pes_type); 88 "can't start dmx feed: invalid pes type %u\n",
113 return -EINVAL; 89 dvbdmxfeed->pes_type);
90 ret = -EINVAL;
91 goto out;
114 } 92 }
115 } else { 93 } else {
116 channel = fdtv_channel_allocate(fdtv); 94 c = alloc_channel(fdtv);
117 } 95 }
118 96
119 if (!channel) { 97 if (c > 15) {
120 printk(KERN_ERR "%s: busy!\n", __func__); 98 dev_err(fdtv->device, "can't start dmx feed: busy\n");
121 return -EBUSY; 99 ret = -EBUSY;
100 goto out;
122 } 101 }
123 102
124 dvbdmxfeed->priv = channel; 103 dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
125 channel->pid = dvbdmxfeed->pid; 104 fdtv->channel_pid[c] = dvbdmxfeed->pid;
126 105 collect_channels(fdtv, &pidc, pids);
127 if (fdtv_channel_collect(fdtv, &pidc, pids)) {
128 fdtv_channel_release(fdtv, channel);
129 printk(KERN_ERR "%s: could not collect pids!\n", __func__);
130 return -EINTR;
131 }
132 106
133 if (dvbdmxfeed->pid == 8192) { 107 if (dvbdmxfeed->pid == 8192) {
134 k = avc_tuner_get_ts(fdtv); 108 ret = avc_tuner_get_ts(fdtv);
135 if (k) { 109 if (ret) {
136 fdtv_channel_release(fdtv, channel); 110 dealloc_channel(fdtv, c);
137 printk("%s: AVCTuner_GetTS failed with error %d\n", 111 dev_err(fdtv->device, "can't get TS\n");
138 __func__, k); 112 goto out;
139 return k;
140 } 113 }
141 } else { 114 } else {
142 k = avc_tuner_set_pids(fdtv, pidc, pids); 115 ret = avc_tuner_set_pids(fdtv, pidc, pids);
143 if (k) { 116 if (ret) {
144 fdtv_channel_release(fdtv, channel); 117 dealloc_channel(fdtv, c);
145 printk("%s: AVCTuner_SetPIDs failed with error %d\n", 118 dev_err(fdtv->device, "can't set PIDs\n");
146 __func__, k); 119 goto out;
147 return k;
148 } 120 }
149 } 121 }
122out:
123 mutex_unlock(&fdtv->demux_mutex);
150 124
151 return 0; 125 return ret;
152} 126}
153 127
154int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 128int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
155{ 129{
156 struct dvb_demux *demux = dvbdmxfeed->demux; 130 struct dvb_demux *demux = dvbdmxfeed->demux;
157 struct firedtv *fdtv = (struct firedtv*)demux->priv; 131 struct firedtv *fdtv = demux->priv;
158 struct firedtv_channel *c = dvbdmxfeed->priv; 132 int pidc, c, ret;
159 int k, l;
160 u16 pids[16]; 133 u16 pids[16];
161 134
162 if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) && 135 if (dvbdmxfeed->type == DMX_TYPE_TS &&
163 (demux->dmx.frontend->source != DMX_MEMORY_FE))) { 136 !((dvbdmxfeed->ts_type & TS_PACKET) &&
137 (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
164 138
165 if (dvbdmxfeed->ts_type & TS_DECODER) { 139 if (dvbdmxfeed->ts_type & TS_DECODER) {
166
167 if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER || 140 if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
168 !demux->pesfilter[dvbdmxfeed->pes_type]) 141 !demux->pesfilter[dvbdmxfeed->pes_type])
169
170 return -EINVAL; 142 return -EINVAL;
171 143
172 demux->pids[dvbdmxfeed->pes_type] |= 0x8000; 144 demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
@@ -174,38 +146,32 @@ int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
174 } 146 }
175 147
176 if (!(dvbdmxfeed->ts_type & TS_DECODER && 148 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
177 dvbdmxfeed->pes_type < DMX_TS_PES_OTHER)) 149 dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
178
179 return 0; 150 return 0;
180 } 151 }
181 152
182 if (mutex_lock_interruptible(&fdtv->demux_mutex)) 153 if (mutex_lock_interruptible(&fdtv->demux_mutex))
183 return -EINTR; 154 return -EINTR;
184 155
185 /* list except channel to be removed */ 156 c = (unsigned long)dvbdmxfeed->priv;
186 for (k = 0, l = 0; k < 16; k++) 157 dealloc_channel(fdtv, c);
187 if (fdtv->channel[k].active) { 158 collect_channels(fdtv, &pidc, pids);
188 if (&fdtv->channel[k] != c)
189 pids[l++] = fdtv->channel[k].pid;
190 else
191 fdtv->channel[k].active = false;
192 }
193 159
194 k = avc_tuner_set_pids(fdtv, l, pids); 160 ret = avc_tuner_set_pids(fdtv, pidc, pids);
195 if (!k)
196 c->active = false;
197 161
198 mutex_unlock(&fdtv->demux_mutex); 162 mutex_unlock(&fdtv->demux_mutex);
199 return k; 163
164 return ret;
200} 165}
201 166
202int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev) 167DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
168
169int fdtv_dvb_register(struct firedtv *fdtv)
203{ 170{
204 int err; 171 int err;
205 172
206 err = DVB_REGISTER_ADAPTER(&fdtv->adapter, 173 err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
207 fdtv_model_names[fdtv->type], 174 THIS_MODULE, fdtv->device, adapter_nr);
208 THIS_MODULE, dev, adapter_nr);
209 if (err < 0) 175 if (err < 0)
210 goto fail_log; 176 goto fail_log;
211 177
@@ -223,9 +189,9 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
223 if (err) 189 if (err)
224 goto fail_unreg_adapter; 190 goto fail_unreg_adapter;
225 191
226 fdtv->dmxdev.filternum = 16; 192 fdtv->dmxdev.filternum = 16;
227 fdtv->dmxdev.demux = &fdtv->demux.dmx; 193 fdtv->dmxdev.demux = &fdtv->demux.dmx;
228 fdtv->dmxdev.capabilities = 0; 194 fdtv->dmxdev.capabilities = 0;
229 195
230 err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter); 196 err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
231 if (err) 197 if (err)
@@ -233,13 +199,12 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
233 199
234 fdtv->frontend.source = DMX_FRONTEND_0; 200 fdtv->frontend.source = DMX_FRONTEND_0;
235 201
236 err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, 202 err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
237 &fdtv->frontend);
238 if (err) 203 if (err)
239 goto fail_dmxdev_release; 204 goto fail_dmxdev_release;
240 205
241 err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx, 206 err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
242 &fdtv->frontend); 207 &fdtv->frontend);
243 if (err) 208 if (err)
244 goto fail_rem_frontend; 209 goto fail_rem_frontend;
245 210
@@ -252,16 +217,15 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
252 217
253 err = fdtv_ca_register(fdtv); 218 err = fdtv_ca_register(fdtv);
254 if (err) 219 if (err)
255 dev_info(dev, "Conditional Access Module not enabled\n"); 220 dev_info(fdtv->device,
256 221 "Conditional Access Module not enabled\n");
257 return 0; 222 return 0;
258 223
259fail_net_release: 224fail_net_release:
260 dvb_net_release(&fdtv->dvbnet); 225 dvb_net_release(&fdtv->dvbnet);
261 fdtv->demux.dmx.close(&fdtv->demux.dmx); 226 fdtv->demux.dmx.close(&fdtv->demux.dmx);
262fail_rem_frontend: 227fail_rem_frontend:
263 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, 228 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
264 &fdtv->frontend);
265fail_dmxdev_release: 229fail_dmxdev_release:
266 dvb_dmxdev_release(&fdtv->dmxdev); 230 dvb_dmxdev_release(&fdtv->dmxdev);
267fail_dmx_release: 231fail_dmx_release:
@@ -269,8 +233,132 @@ fail_dmx_release:
269fail_unreg_adapter: 233fail_unreg_adapter:
270 dvb_unregister_adapter(&fdtv->adapter); 234 dvb_unregister_adapter(&fdtv->adapter);
271fail_log: 235fail_log:
272 dev_err(dev, "DVB initialization failed\n"); 236 dev_err(fdtv->device, "DVB initialization failed\n");
273 return err; 237 return err;
274} 238}
275 239
240void 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
252const 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
260struct 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
300static 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};
345MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
346
347static int __init fdtv_init(void)
348{
349 return fdtv_1394_init(fdtv_id_table);
350}
351
352static void __exit fdtv_exit(void)
353{
354 fdtv_1394_exit();
355}
356
357module_init(fdtv_init);
358module_exit(fdtv_exit);
276 359
360MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
361MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
362MODULE_DESCRIPTION("FireDTV DVB Driver");
363MODULE_LICENSE("GPL");
364MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c
index f8150f402bb6..9b9539c800f8 100644
--- a/drivers/media/dvb/firewire/firedtv-fe.c
+++ b/drivers/media/dvb/firewire/firedtv-fe.c
@@ -10,6 +10,7 @@
10 * the License, or (at your option) any later version. 10 * the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <linux/device.h>
13#include <linux/errno.h> 14#include <linux/errno.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/string.h> 16#include <linux/string.h>
@@ -17,8 +18,6 @@
17 18
18#include <dvb_frontend.h> 19#include <dvb_frontend.h>
19 20
20#include "avc.h"
21#include "cmp.h"
22#include "firedtv.h" 21#include "firedtv.h"
23 22
24static int fdtv_dvb_init(struct dvb_frontend *fe) 23static int fdtv_dvb_init(struct dvb_frontend *fe)
@@ -32,35 +31,37 @@ static int fdtv_dvb_init(struct dvb_frontend *fe)
32 err = cmp_establish_pp_connection(fdtv, fdtv->subunit, 31 err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
33 fdtv->isochannel); 32 fdtv->isochannel);
34 if (err) { 33 if (err) {
35 printk(KERN_ERR "Could not establish point to point " 34 dev_err(fdtv->device,
36 "connection.\n"); 35 "could not establish point to point connection\n");
37 return err; 36 return err;
38 } 37 }
39 38
40 return setup_iso_channel(fdtv); 39 return fdtv->backend->start_iso(fdtv);
41} 40}
42 41
43static int fdtv_sleep(struct dvb_frontend *fe) 42static int fdtv_sleep(struct dvb_frontend *fe)
44{ 43{
45 struct firedtv *fdtv = fe->sec_priv; 44 struct firedtv *fdtv = fe->sec_priv;
46 45
47 tear_down_iso_channel(fdtv); 46 fdtv->backend->stop_iso(fdtv);
48 cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel); 47 cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
49 fdtv->isochannel = -1; 48 fdtv->isochannel = -1;
50 return 0; 49 return 0;
51} 50}
52 51
52#define LNBCONTROL_DONTCARE 0xff
53
53static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe, 54static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
54 struct dvb_diseqc_master_cmd *cmd) 55 struct dvb_diseqc_master_cmd *cmd)
55{ 56{
56 struct firedtv *fdtv = fe->sec_priv; 57 struct firedtv *fdtv = fe->sec_priv;
57 58
58 return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, 59 return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
59 LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd); 60 LNBCONTROL_DONTCARE, 1, cmd);
60} 61}
61 62
62static int fdtv_diseqc_send_burst(struct dvb_frontend *fe, 63static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
63 fe_sec_mini_cmd_t minicmd) 64 fe_sec_mini_cmd_t minicmd)
64{ 65{
65 return 0; 66 return 0;
66} 67}
@@ -74,7 +75,7 @@ static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
74} 75}
75 76
76static int fdtv_set_voltage(struct dvb_frontend *fe, 77static int fdtv_set_voltage(struct dvb_frontend *fe,
77 fe_sec_voltage_t voltage) 78 fe_sec_voltage_t voltage)
78{ 79{
79 struct firedtv *fdtv = fe->sec_priv; 80 struct firedtv *fdtv = fe->sec_priv;
80 81
@@ -85,12 +86,12 @@ static int fdtv_set_voltage(struct dvb_frontend *fe,
85static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status) 86static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
86{ 87{
87 struct firedtv *fdtv = fe->sec_priv; 88 struct firedtv *fdtv = fe->sec_priv;
88 ANTENNA_INPUT_INFO info; 89 struct firedtv_tuner_status stat;
89 90
90 if (avc_tuner_status(fdtv, &info)) 91 if (avc_tuner_status(fdtv, &stat))
91 return -EINVAL; 92 return -EINVAL;
92 93
93 if (info.NoRF) 94 if (stat.no_rf)
94 *status = 0; 95 *status = 0;
95 else 96 else
96 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | 97 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
@@ -101,39 +102,37 @@ static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
101static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber) 102static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
102{ 103{
103 struct firedtv *fdtv = fe->sec_priv; 104 struct firedtv *fdtv = fe->sec_priv;
104 ANTENNA_INPUT_INFO info; 105 struct firedtv_tuner_status stat;
105 106
106 if (avc_tuner_status(fdtv, &info)) 107 if (avc_tuner_status(fdtv, &stat))
107 return -EINVAL; 108 return -EINVAL;
108 109
109 *ber = info.BER[0] << 24 | info.BER[1] << 16 | 110 *ber = stat.ber;
110 info.BER[2] << 8 | info.BER[3];
111 return 0; 111 return 0;
112} 112}
113 113
114static int fdtv_read_signal_strength (struct dvb_frontend *fe, u16 *strength) 114static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
115{ 115{
116 struct firedtv *fdtv = fe->sec_priv; 116 struct firedtv *fdtv = fe->sec_priv;
117 ANTENNA_INPUT_INFO info; 117 struct firedtv_tuner_status stat;
118 118
119 if (avc_tuner_status(fdtv, &info)) 119 if (avc_tuner_status(fdtv, &stat))
120 return -EINVAL; 120 return -EINVAL;
121 121
122 *strength = info.SignalStrength << 8; 122 *strength = stat.signal_strength << 8;
123 return 0; 123 return 0;
124} 124}
125 125
126static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr) 126static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
127{ 127{
128 struct firedtv *fdtv = fe->sec_priv; 128 struct firedtv *fdtv = fe->sec_priv;
129 ANTENNA_INPUT_INFO info; 129 struct firedtv_tuner_status stat;
130 130
131 if (avc_tuner_status(fdtv, &info)) 131 if (avc_tuner_status(fdtv, &stat))
132 return -EINVAL; 132 return -EINVAL;
133 133
134 /* C/N[dB] = -10 * log10(snr / 65535) */ 134 /* C/N[dB] = -10 * log10(snr / 65535) */
135 *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1]; 135 *snr = stat.carrier_noise_ratio * 257;
136 *snr *= 257;
137 return 0; 136 return 0;
138} 137}
139 138
@@ -142,8 +141,10 @@ static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
142 return -EOPNOTSUPP; 141 return -EOPNOTSUPP;
143} 142}
144 143
144#define ACCEPTED 0x9
145
145static int fdtv_set_frontend(struct dvb_frontend *fe, 146static int fdtv_set_frontend(struct dvb_frontend *fe,
146 struct dvb_frontend_parameters *params) 147 struct dvb_frontend_parameters *params)
147{ 148{
148 struct firedtv *fdtv = fe->sec_priv; 149 struct firedtv *fdtv = fe->sec_priv;
149 150
@@ -155,7 +156,7 @@ static int fdtv_set_frontend(struct dvb_frontend *fe,
155} 156}
156 157
157static int fdtv_get_frontend(struct dvb_frontend *fe, 158static int fdtv_get_frontend(struct dvb_frontend *fe,
158 struct dvb_frontend_parameters *params) 159 struct dvb_frontend_parameters *params)
159{ 160{
160 return -EOPNOTSUPP; 161 return -EOPNOTSUPP;
161} 162}
@@ -235,8 +236,8 @@ void fdtv_frontend_init(struct firedtv *fdtv)
235 break; 236 break;
236 237
237 default: 238 default:
238 printk(KERN_ERR "FireDTV: no frontend for model type %d\n", 239 dev_err(fdtv->device, "no frontend for model type %d\n",
239 fdtv->type); 240 fdtv->type);
240 } 241 }
241 strcpy(fi->name, fdtv_model_names[fdtv->type]); 242 strcpy(fi->name, fdtv_model_names[fdtv->type]);
242 243
diff --git a/drivers/media/dvb/firewire/firedtv-iso.c b/drivers/media/dvb/firewire/firedtv-iso.c
deleted file mode 100644
index a72df228e7de..000000000000
--- a/drivers/media/dvb/firewire/firedtv-iso.c
+++ /dev/null
@@ -1,111 +0,0 @@
1/*
2 * FireSAT DVB driver
3 *
4 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 */
11
12#include <linux/errno.h>
13#include <linux/kernel.h>
14#include <linux/list.h>
15#include <linux/spinlock.h>
16
17#include <dvb_demux.h>
18
19#include <dma.h>
20#include <iso.h>
21#include <nodemgr.h>
22
23#include "firedtv.h"
24
25static void rawiso_activity_cb(struct hpsb_iso *iso);
26
27void tear_down_iso_channel(struct firedtv *fdtv)
28{
29 if (fdtv->iso_handle != NULL) {
30 hpsb_iso_stop(fdtv->iso_handle);
31 hpsb_iso_shutdown(fdtv->iso_handle);
32 }
33 fdtv->iso_handle = NULL;
34}
35
36int setup_iso_channel(struct firedtv *fdtv)
37{
38 int result;
39 fdtv->iso_handle =
40 hpsb_iso_recv_init(fdtv->ud->ne->host,
41 256 * 200, //data_buf_size,
42 256, //buf_packets,
43 fdtv->isochannel,
44 HPSB_ISO_DMA_DEFAULT, //dma_mode,
45 -1, //stat.config.irq_interval,
46 rawiso_activity_cb);
47 if (fdtv->iso_handle == NULL) {
48 printk(KERN_ERR "Cannot initialize iso receive.\n");
49 return -EINVAL;
50 }
51 result = hpsb_iso_recv_start(fdtv->iso_handle, -1, -1, 0);
52 if (result != 0) {
53 printk(KERN_ERR "Cannot start iso receive.\n");
54 return -EINVAL;
55 }
56 return 0;
57}
58
59static void rawiso_activity_cb(struct hpsb_iso *iso)
60{
61 unsigned int num;
62 unsigned int i;
63 unsigned int packet;
64 unsigned long flags;
65 struct firedtv *fdtv = NULL;
66 struct firedtv *fdtv_iterator;
67
68 spin_lock_irqsave(&fdtv_list_lock, flags);
69 list_for_each_entry(fdtv_iterator, &fdtv_list, list) {
70 if(fdtv_iterator->iso_handle == iso) {
71 fdtv = fdtv_iterator;
72 break;
73 }
74 }
75 spin_unlock_irqrestore(&fdtv_list_lock, flags);
76
77 if (fdtv) {
78 packet = iso->first_packet;
79 num = hpsb_iso_n_ready(iso);
80 for (i = 0; i < num; i++,
81 packet = (packet + 1) % iso->buf_packets) {
82 unsigned char *buf =
83 dma_region_i(&iso->data_buf, unsigned char,
84 iso->infos[packet].offset +
85 sizeof(struct CIPHeader));
86 int count = (iso->infos[packet].len -
87 sizeof(struct CIPHeader)) /
88 (188 + sizeof(struct firewireheader));
89 if (iso->infos[packet].len <= sizeof(struct CIPHeader))
90 continue; // ignore empty packet
91
92 while (count --) {
93 if (buf[sizeof(struct firewireheader)] == 0x47)
94 dvb_dmx_swfilter_packets(&fdtv->demux,
95 &buf[sizeof(struct firewireheader)], 1);
96 else
97 printk("%s: invalid packet, skipping\n", __func__);
98 buf += 188 + sizeof(struct firewireheader);
99
100 }
101
102 }
103 hpsb_iso_recv_release_packets(iso, num);
104 }
105 else {
106 printk("%s: packets for unknown iso channel, skipping\n",
107 __func__);
108 hpsb_iso_recv_release_packets(iso, hpsb_iso_n_ready(iso));
109 }
110}
111
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c
index 436c0c69a13d..46a6324d7b73 100644
--- a/drivers/media/dvb/firewire/firedtv-rc.c
+++ b/drivers/media/dvb/firewire/firedtv-rc.c
@@ -15,7 +15,6 @@
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/types.h> 16#include <linux/types.h>
17 17
18#include "firedtv-rc.h"
19#include "firedtv.h" 18#include "firedtv.h"
20 19
21/* fixed table with older keycodes, geared towards MythTV */ 20/* fixed table with older keycodes, geared towards MythTV */
diff --git a/drivers/media/dvb/firewire/firedtv-rc.h b/drivers/media/dvb/firewire/firedtv-rc.h
deleted file mode 100644
index d3e14727d3dd..000000000000
--- a/drivers/media/dvb/firewire/firedtv-rc.h
+++ /dev/null
@@ -1,11 +0,0 @@
1#ifndef _FIREDTV_RC_H
2#define _FIREDTV_RC_H
3
4struct firedtv;
5struct device;
6
7int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
8void fdtv_unregister_rc(struct firedtv *fdtv);
9void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
10
11#endif /* _FIREDTV_RC_H */
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
index 2a34028ccbcd..d48530b81e61 100644
--- a/drivers/media/dvb/firewire/firedtv.h
+++ b/drivers/media/dvb/firewire/firedtv.h
@@ -29,95 +29,35 @@
29#include <dvb_net.h> 29#include <dvb_net.h>
30#include <dvbdev.h> 30#include <dvbdev.h>
31 31
32#include <linux/version.h> 32struct firedtv_tuner_status {
33#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) 33 unsigned active_system:8;
34#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w, v) 34 unsigned searching:1;
35#else 35 unsigned moving:1;
36#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w) 36 unsigned no_rf:1;
37#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(x) 37 unsigned input:1;
38#endif 38 unsigned selected_antenna:7;
39 39 unsigned ber:32;
40/***************************************************************** 40 unsigned signal_strength:8;
41 * CA message command constants from en50221_app_tags.h of libdvb 41 unsigned raster_frequency:2;
42 *****************************************************************/ 42 unsigned rf_frequency:22;
43/* Resource Manager */ 43 unsigned man_dep_info_length:8;
44#define TAG_PROFILE_ENQUIRY 0x9f8010 44 unsigned front_end_error:1;
45#define TAG_PROFILE 0x9f8011 45 unsigned antenna_error:1;
46#define TAG_PROFILE_CHANGE 0x9f8012 46 unsigned front_end_power_status:1;
47 47 unsigned power_supply:1;
48/* Application Info */ 48 unsigned carrier_noise_ratio:16;
49#define TAG_APP_INFO_ENQUIRY 0x9f8020 49 unsigned power_supply_voltage:8;
50#define TAG_APP_INFO 0x9f8021 50 unsigned antenna_voltage:8;
51#define TAG_ENTER_MENU 0x9f8022 51 unsigned firewire_bus_voltage:8;
52 52 unsigned ca_mmi:1;
53/* CA Support */ 53 unsigned ca_pmt_reply:1;
54#define TAG_CA_INFO_ENQUIRY 0x9f8030 54 unsigned ca_date_time_request:1;
55#define TAG_CA_INFO 0x9f8031 55 unsigned ca_application_info:1;
56#define TAG_CA_PMT 0x9f8032 56 unsigned ca_module_present_status:1;
57#define TAG_CA_PMT_REPLY 0x9f8033 57 unsigned ca_dvb_flag:1;
58 58 unsigned ca_error_flag:1;
59/* Host Control */ 59 unsigned ca_initialization_status:1;
60#define TAG_TUNE 0x9f8400 60};
61#define TAG_REPLACE 0x9f8401
62#define TAG_CLEAR_REPLACE 0x9f8402
63#define TAG_ASK_RELEASE 0x9f8403
64
65/* Date and Time */
66#define TAG_DATE_TIME_ENQUIRY 0x9f8440
67#define TAG_DATE_TIME 0x9f8441
68
69/* Man Machine Interface (MMI) */
70#define TAG_CLOSE_MMI 0x9f8800
71#define TAG_DISPLAY_CONTROL 0x9f8801
72#define TAG_DISPLAY_REPLY 0x9f8802
73#define TAG_TEXT_LAST 0x9f8803
74#define TAG_TEXT_MORE 0x9f8804
75#define TAG_KEYPAD_CONTROL 0x9f8805
76#define TAG_KEYPRESS 0x9f8806
77#define TAG_ENQUIRY 0x9f8807
78#define TAG_ANSWER 0x9f8808
79#define TAG_MENU_LAST 0x9f8809
80#define TAG_MENU_MORE 0x9f880a
81#define TAG_MENU_ANSWER 0x9f880b
82#define TAG_LIST_LAST 0x9f880c
83#define TAG_LIST_MORE 0x9f880d
84#define TAG_SUBTITLE_SEGMENT_LAST 0x9f880e
85#define TAG_SUBTITLE_SEGMENT_MORE 0x9f880f
86#define TAG_DISPLAY_MESSAGE 0x9f8810
87#define TAG_SCENE_END_MARK 0x9f8811
88#define TAG_SCENE_DONE 0x9f8812
89#define TAG_SCENE_CONTROL 0x9f8813
90#define TAG_SUBTITLE_DOWNLOAD_LAST 0x9f8814
91#define TAG_SUBTITLE_DOWNLOAD_MORE 0x9f8815
92#define TAG_FLUSH_DOWNLOAD 0x9f8816
93#define TAG_DOWNLOAD_REPLY 0x9f8817
94
95/* Low Speed Communications */
96#define TAG_COMMS_COMMAND 0x9f8c00
97#define TAG_CONNECTION_DESCRIPTOR 0x9f8c01
98#define TAG_COMMS_REPLY 0x9f8c02
99#define TAG_COMMS_SEND_LAST 0x9f8c03
100#define TAG_COMMS_SEND_MORE 0x9f8c04
101#define TAG_COMMS_RECV_LAST 0x9f8c05
102#define TAG_COMMS_RECV_MORE 0x9f8c06
103
104/* Authentication */
105#define TAG_AUTH_REQ 0x9f8200
106#define TAG_AUTH_RESP 0x9f8201
107
108/* Teletext */
109#define TAG_TELETEXT_EBU 0x9f9000
110
111/* Smartcard */
112#define TAG_SMARTCARD_COMMAND 0x9f8e00
113#define TAG_SMARTCARD_REPLY 0x9f8e01
114#define TAG_SMARTCARD_SEND 0x9f8e02
115#define TAG_SMARTCARD_RCV 0x9f8e03
116
117/* EPG */
118#define TAG_EPG_ENQUIRY 0x9f8f00
119#define TAG_EPG_REPLY 0x9f8f01
120
121 61
122enum model_type { 62enum model_type {
123 FIREDTV_UNKNOWN = 0, 63 FIREDTV_UNKNOWN = 0,
@@ -127,11 +67,22 @@ enum model_type {
127 FIREDTV_DVB_S2 = 4, 67 FIREDTV_DVB_S2 = 4,
128}; 68};
129 69
70struct device;
130struct input_dev; 71struct input_dev;
131struct hpsb_iso; 72struct firedtv;
132struct unit_directory; 73
74struct firedtv_backend {
75 int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
76 int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
77 int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
78 int (*start_iso)(struct firedtv *fdtv);
79 void (*stop_iso)(struct firedtv *fdtv);
80};
133 81
134struct firedtv { 82struct firedtv {
83 struct device *device;
84 struct list_head list;
85
135 struct dvb_adapter adapter; 86 struct dvb_adapter adapter;
136 struct dmxdev dmxdev; 87 struct dmxdev dmxdev;
137 struct dvb_demux demux; 88 struct dvb_demux demux;
@@ -149,79 +100,83 @@ struct firedtv {
149 struct work_struct remote_ctrl_work; 100 struct work_struct remote_ctrl_work;
150 struct input_dev *remote_ctrl_dev; 101 struct input_dev *remote_ctrl_dev;
151 102
152 struct firedtv_channel { 103 enum model_type type;
153 bool active; 104 char subunit;
154 int pid; 105 char isochannel;
155 } channel[16]; 106 fe_sec_voltage_t voltage;
156 struct mutex demux_mutex; 107 fe_sec_tone_mode_t tone;
157 108
158 struct unit_directory *ud; 109 const struct firedtv_backend *backend;
110 void *backend_data;
159 111
160 enum model_type type; 112 struct mutex demux_mutex;
161 char subunit; 113 unsigned long channel_active;
162 fe_sec_voltage_t voltage; 114 u16 channel_pid[16];
163 fe_sec_tone_mode_t tone;
164
165 int isochannel;
166 struct hpsb_iso *iso_handle;
167
168 struct list_head list;
169 115
170 /* needed by avc_api */ 116 size_t response_length;
171 int resp_length; 117 u8 response[512];
172 u8 respfrm[512];
173}; 118};
174 119
175struct firewireheader { 120/* firedtv-1394.c */
176 union { 121#ifdef CONFIG_DVB_FIREDTV_IEEE1394
177 struct { 122int fdtv_1394_init(struct ieee1394_device_id id_table[]);
178 __u8 tcode:4; 123void fdtv_1394_exit(void);
179 __u8 sy:4; 124#else
180 __u8 tag:2; 125static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
181 __u8 channel:6; 126static inline void fdtv_1394_exit(void) {}
182 127#endif
183 __u8 length_l;
184 __u8 length_h;
185 } hdr;
186 __u32 val;
187 };
188};
189
190struct CIPHeader {
191 union {
192 struct {
193 __u8 syncbits:2;
194 __u8 sid:6;
195 __u8 dbs;
196 __u8 fn:2;
197 __u8 qpc:3;
198 __u8 sph:1;
199 __u8 rsv:2;
200 __u8 dbc;
201 __u8 syncbits2:2;
202 __u8 fmt:6;
203 __u32 fdf:24;
204 } cip;
205 __u64 val;
206 };
207};
208
209extern const char *fdtv_model_names[];
210extern struct list_head fdtv_list;
211extern spinlock_t fdtv_list_lock;
212 128
213struct device; 129/* firedtv-avc.c */
130int avc_recv(struct firedtv *fdtv, void *data, size_t length);
131int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
132struct dvb_frontend_parameters;
133int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
134int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
135int avc_tuner_get_ts(struct firedtv *fdtv);
136int avc_identify_subunit(struct firedtv *fdtv);
137struct dvb_diseqc_master_cmd;
138int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
139 char conttone, char nrdiseq,
140 struct dvb_diseqc_master_cmd *diseqcmd);
141void avc_remote_ctrl_work(struct work_struct *work);
142int avc_register_remote_control(struct firedtv *fdtv);
143int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
144int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
145int avc_ca_reset(struct firedtv *fdtv);
146int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
147int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
148int avc_ca_enter_menu(struct firedtv *fdtv);
149int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
150int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
151void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
152
153/* firedtv-ci.c */
154int fdtv_ca_register(struct firedtv *fdtv);
155void fdtv_ca_release(struct firedtv *fdtv);
214 156
215/* firedtv-dvb.c */ 157/* firedtv-dvb.c */
216int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed); 158int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
217int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed); 159int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
218int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev); 160int fdtv_dvb_register(struct firedtv *fdtv);
161void fdtv_dvb_unregister(struct firedtv *fdtv);
162struct firedtv *fdtv_alloc(struct device *dev,
163 const struct firedtv_backend *backend,
164 const char *name, size_t name_len);
165extern const char *fdtv_model_names[];
219 166
220/* firedtv-fe.c */ 167/* firedtv-fe.c */
221void fdtv_frontend_init(struct firedtv *fdtv); 168void fdtv_frontend_init(struct firedtv *fdtv);
222 169
223/* firedtv-iso.c */ 170/* firedtv-rc.c */
224int setup_iso_channel(struct firedtv *fdtv); 171#ifdef CONFIG_DVB_FIREDTV_INPUT
225void tear_down_iso_channel(struct firedtv *fdtv); 172int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
173void fdtv_unregister_rc(struct firedtv *fdtv);
174void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
175#else
176static inline int fdtv_register_rc(struct firedtv *fdtv,
177 struct device *dev) { return 0; }
178static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
179static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
180#endif
226 181
227#endif /* _FIREDTV_H */ 182#endif /* _FIREDTV_H */