firedtv: Use DEFINE_SPINLOCK
[pandora-kernel.git] / drivers / media / dvb / firewire / avc.c
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
34 static 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
72 static 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
86 int 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  */
125 static 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
185 static 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
271 static 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
397 int 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
435 int 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
479 int 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
512 int 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
547 int 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
589 int 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
638 int 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
660 void 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 */
670 int 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
699 static 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
709 static 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
724 int 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
762 int 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
798 int 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
827 int 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
960 int 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
992 int 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
1020 int 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 }