firesat: add DVB-S support for DVB-S2 devices
[linux-2.6-block.git] / drivers / media / dvb / firesat / avc_api.c
1 /*
2  * FireSAT AVC driver
3  *
4  * Copyright (c) 2004 Andreas Monitzer <andy@monitzer.com>
5  * Copyright (c) 2008 Ben Backx <ben@bbackx.com>
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 "firesat.h"
14 #include <ieee1394_transactions.h>
15 #include <nodemgr.h>
16 #include <asm/byteorder.h>
17 #include <linux/delay.h>
18 #include "avc_api.h"
19 #include "firesat-rc.h"
20
21 #define RESPONSE_REGISTER                               0xFFFFF0000D00ULL
22 #define COMMAND_REGISTER                                0xFFFFF0000B00ULL
23 #define PCR_BASE_ADDRESS                                0xFFFFF0000900ULL
24
25 static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal);
26
27 /* Frees an allocated packet */
28 static void avc_free_packet(struct hpsb_packet *packet)
29 {
30         hpsb_free_tlabel(packet);
31         hpsb_free_packet(packet);
32 }
33
34 /*
35  * Goofy routine that basically does a down_timeout function.
36  * Stolen from sbp2.c
37  */
38 static int avc_down_timeout(atomic_t *done, int timeout)
39 {
40         int i;
41
42         for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
43                 set_current_state(TASK_INTERRUPTIBLE);
44                 if (schedule_timeout(HZ/10))    /* 100ms */
45                         return(1);
46         }
47         return ((i > 0) ? 0:1);
48 }
49
50 static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) {
51         struct hpsb_packet *packet;
52         struct node_entry *ne;
53
54         ne = firesat->nodeentry;
55         if(!ne) {
56                 printk("%s: lost node!\n",__func__);
57                 return -EIO;
58         }
59
60         /* need all input data */
61         if(!firesat || !ne || !CmdFrm)
62                 return -EINVAL;
63
64 //      printk(KERN_INFO "AVCWrite command %x\n",CmdFrm->opcode);
65
66 //      for(k=0;k<CmdFrm->length;k++)
67 //              printk(KERN_INFO "CmdFrm[%d] = %08x\n", k, ((quadlet_t*)CmdFrm)[k]);
68
69         packet=hpsb_make_writepacket(ne->host, ne->nodeid, COMMAND_REGISTER,
70                         (quadlet_t*)CmdFrm, CmdFrm->length);
71
72         hpsb_set_packet_complete_task(packet, (void (*)(void*))avc_free_packet,
73                                   packet);
74
75         hpsb_node_fill_packet(ne, packet);
76
77         if(RspFrm)
78                 atomic_set(&firesat->avc_reply_received, 0);
79
80         if (hpsb_send_packet(packet) < 0) {
81                 avc_free_packet(packet);
82                 atomic_set(&firesat->avc_reply_received, 1);
83                 return -EIO;
84         }
85
86         if(RspFrm) {
87                 if(avc_down_timeout(&firesat->avc_reply_received,HZ/2)) {
88                 printk("%s: timeout waiting for avc response\n",__func__);
89                         atomic_set(&firesat->avc_reply_received, 1);
90                 return -ETIMEDOUT;
91         }
92
93                 memcpy(RspFrm,firesat->respfrm,firesat->resp_length);
94         }
95
96         return 0;
97 }
98
99 int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) {
100         int ret;
101         if(down_interruptible(&firesat->avc_sem))
102                 return -EINTR;
103
104         ret = __AVCWrite(firesat, CmdFrm, RspFrm);
105
106         up(&firesat->avc_sem);
107         return ret;
108 }
109
110 static void do_schedule_remotecontrol(unsigned long ignored);
111 DECLARE_TASKLET(schedule_remotecontrol, do_schedule_remotecontrol, 0);
112
113 static void do_schedule_remotecontrol(unsigned long ignored) {
114         struct firesat *firesat;
115         unsigned long flags;
116
117         spin_lock_irqsave(&firesat_list_lock, flags);
118         list_for_each_entry(firesat,&firesat_list,list) {
119                 if(atomic_read(&firesat->reschedule_remotecontrol) == 1) {
120                         if(down_trylock(&firesat->avc_sem))
121                                 tasklet_schedule(&schedule_remotecontrol);
122                         else {
123                                 if(__AVCRegisterRemoteControl(firesat, 1) == 0)
124                                         atomic_set(&firesat->reschedule_remotecontrol, 0);
125                                 else
126                                         tasklet_schedule(&schedule_remotecontrol);
127
128                                 up(&firesat->avc_sem);
129                         }
130                 }
131         }
132         spin_unlock_irqrestore(&firesat_list_lock, flags);
133 }
134
135 int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
136 //      printk(KERN_INFO "%s\n",__func__);
137
138         // remote control handling
139
140         AVCRspFrm *RspFrm = (AVCRspFrm*)data;
141
142         if(/*RspFrm->length >= 8 && ###*/
143                         ((RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
144                         RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
145                         RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2)) &&
146                         RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
147                 if(RspFrm->resp == CHANGED) {
148 //                      printk(KERN_INFO "%s: code = %02x %02x\n",__func__,RspFrm->operand[4],RspFrm->operand[5]);
149                         firesat_got_remotecontrolcode((((u16)RspFrm->operand[4]) << 8) | ((u16)RspFrm->operand[5]));
150
151                         // schedule
152                         atomic_set(&firesat->reschedule_remotecontrol, 1);
153                         tasklet_schedule(&schedule_remotecontrol);
154                 } else if(RspFrm->resp != INTERIM)
155                         printk(KERN_INFO "%s: remote control result = %d\n",__func__, RspFrm->resp);
156                 return 0;
157         }
158
159         if(atomic_read(&firesat->avc_reply_received) == 1) {
160                 printk("%s: received out-of-order AVC response, ignored\n",__func__);
161                 return -EINVAL;
162         }
163 //      AVCRspFrm *resp=(AVCRspFrm *)data;
164 //      int k;
165 /*
166         printk(KERN_INFO "resp=0x%x\n",resp->resp);
167         printk(KERN_INFO "cts=0x%x\n",resp->cts);
168         printk(KERN_INFO "suid=0x%x\n",resp->suid);
169         printk(KERN_INFO "sutyp=0x%x\n",resp->sutyp);
170         printk(KERN_INFO "opcode=0x%x\n",resp->opcode);
171         printk(KERN_INFO "length=%d\n",resp->length);
172 */
173 //      for(k=0;k<2;k++)
174 //              printk(KERN_INFO "operand[%d]=%02x\n",k,resp->operand[k]);
175
176         memcpy(firesat->respfrm,data,length);
177         firesat->resp_length=length;
178
179         atomic_set(&firesat->avc_reply_received, 1);
180
181         return 0;
182 }
183
184 // tuning command for setting the relative LNB frequency (not supported by the AVC standard)
185 static void AVCTuner_tuneQPSK(struct firesat *firesat, struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm) {
186         memset(CmdFrm, 0, sizeof(AVCCmdFrm));
187
188         CmdFrm->cts = AVC;
189         CmdFrm->ctype = CONTROL;
190         CmdFrm->sutyp = 0x5;
191         CmdFrm->suid = firesat->subunit;
192         CmdFrm->opcode = VENDOR;
193
194         CmdFrm->operand[0]=SFE_VENDOR_DE_COMPANYID_0;
195         CmdFrm->operand[1]=SFE_VENDOR_DE_COMPANYID_1;
196         CmdFrm->operand[2]=SFE_VENDOR_DE_COMPANYID_2;
197         CmdFrm->operand[3]=SFE_VENDOR_OPCODE_TUNE_QPSK;
198
199         printk(KERN_INFO "%s: tuning to frequency %u\n",__func__,params->frequency);
200
201         CmdFrm->operand[4] = (params->frequency >> 24) & 0xFF;
202         CmdFrm->operand[5] = (params->frequency >> 16) & 0xFF;
203         CmdFrm->operand[6] = (params->frequency >> 8) & 0xFF;
204         CmdFrm->operand[7] = params->frequency & 0xFF;
205
206         printk(KERN_INFO "%s: symbol rate = %uBd\n",__func__,params->u.qpsk.symbol_rate);
207
208         CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate/1000) >> 8) & 0xFF;
209         CmdFrm->operand[9] = (params->u.qpsk.symbol_rate/1000) & 0xFF;
210
211         switch(params->u.qpsk.fec_inner) {
212         case FEC_1_2:
213                 CmdFrm->operand[10] = 0x1;
214                 break;
215         case FEC_2_3:
216                 CmdFrm->operand[10] = 0x2;
217                 break;
218         case FEC_3_4:
219                 CmdFrm->operand[10] = 0x3;
220                 break;
221         case FEC_5_6:
222                 CmdFrm->operand[10] = 0x4;
223                 break;
224         case FEC_7_8:
225                 CmdFrm->operand[10] = 0x5;
226                 break;
227         case FEC_4_5:
228         case FEC_8_9:
229         case FEC_AUTO:
230         default:
231                 CmdFrm->operand[10] = 0x0;
232         }
233
234         if(firesat->voltage == 0xff)
235                 CmdFrm->operand[11] = 0xff;
236         else
237                 CmdFrm->operand[11] = (firesat->voltage==SEC_VOLTAGE_18)?0:1; // polarisation
238         if(firesat->tone == 0xff)
239                 CmdFrm->operand[12] = 0xff;
240         else
241                 CmdFrm->operand[12] = (firesat->tone==SEC_TONE_ON)?1:0; // band
242
243         if (firesat->type == FireSAT_DVB_S2) {
244                 CmdFrm->operand[13] = 0x1;
245                 CmdFrm->operand[14] = 0xFF;
246                 CmdFrm->operand[15] = 0xFF;
247         }
248
249         CmdFrm->length = 16;
250 }
251
252 int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, BYTE *status) {
253         AVCCmdFrm CmdFrm;
254         AVCRspFrm RspFrm;
255         M_VALID_FLAGS flags;
256         int k;
257
258 //      printk(KERN_INFO "%s\n", __func__);
259
260         if (firesat->type == FireSAT_DVB_S || firesat->type == FireSAT_DVB_S2)
261                 AVCTuner_tuneQPSK(firesat, params, &CmdFrm);
262         else {
263                 if(firesat->type == FireSAT_DVB_T) {
264                         flags.Bits_T.GuardInterval = (params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO);
265                         flags.Bits_T.CodeRateLPStream = (params->u.ofdm.code_rate_LP != FEC_AUTO);
266                         flags.Bits_T.CodeRateHPStream = (params->u.ofdm.code_rate_HP != FEC_AUTO);
267                         flags.Bits_T.HierarchyInfo = (params->u.ofdm.hierarchy_information != HIERARCHY_AUTO);
268                         flags.Bits_T.Constellation = (params->u.ofdm.constellation != QAM_AUTO);
269                         flags.Bits_T.Bandwidth = (params->u.ofdm.bandwidth != BANDWIDTH_AUTO);
270                         flags.Bits_T.CenterFrequency = 1;
271                         flags.Bits_T.reserved1 = 0;
272                         flags.Bits_T.reserved2 = 0;
273                         flags.Bits_T.OtherFrequencyFlag = 0;
274                         flags.Bits_T.TransmissionMode = (params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO);
275                         flags.Bits_T.NetworkId = 0;
276                 } else {
277                         flags.Bits.Modulation = 0;
278                         if(firesat->type == FireSAT_DVB_S) {
279                                 flags.Bits.FEC_inner = 1;
280                         } else if(firesat->type == FireSAT_DVB_C) {
281                                 flags.Bits.FEC_inner = 0;
282                         }
283                         flags.Bits.FEC_outer = 0;
284                         flags.Bits.Symbol_Rate = 1;
285                         flags.Bits.Frequency = 1;
286                         flags.Bits.Orbital_Pos = 0;
287                         if(firesat->type == FireSAT_DVB_S) {
288                                 flags.Bits.Polarisation = 1;
289                         } else if(firesat->type == FireSAT_DVB_C) {
290                                 flags.Bits.Polarisation = 0;
291                         }
292                         flags.Bits.reserved_fields = 0;
293                         flags.Bits.reserved1 = 0;
294                         flags.Bits.Network_ID = 0;
295                 }
296
297                 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
298
299                 CmdFrm.cts      = AVC;
300                 CmdFrm.ctype    = CONTROL;
301                 CmdFrm.sutyp    = 0x5;
302                 CmdFrm.suid     = firesat->subunit;
303                 CmdFrm.opcode   = DSD;
304
305                 CmdFrm.operand[0]  = 0; // source plug
306                 CmdFrm.operand[1]  = 0xD2; // subfunction replace
307                 CmdFrm.operand[2]  = 0x20; // system id = DVB
308                 CmdFrm.operand[3]  = 0x00; // antenna number
309                 CmdFrm.operand[4]  = (firesat->type == FireSAT_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
310                 CmdFrm.operand[5]  = flags.Valid_Word.ByteHi; // valid_flags [0]
311                 CmdFrm.operand[6]  = flags.Valid_Word.ByteLo; // valid_flags [1]
312
313                 if(firesat->type == FireSAT_DVB_T) {
314                         CmdFrm.operand[7]  = 0x0;
315                         CmdFrm.operand[8]  = (params->frequency/10) >> 24;
316                         CmdFrm.operand[9]  = ((params->frequency/10) >> 16) & 0xFF;
317                         CmdFrm.operand[10] = ((params->frequency/10) >>  8) & 0xFF;
318                         CmdFrm.operand[11] = (params->frequency/10) & 0xFF;
319                         switch(params->u.ofdm.bandwidth) {
320                         case BANDWIDTH_7_MHZ:
321                                 CmdFrm.operand[12] = 0x20;
322                                 break;
323                         case BANDWIDTH_8_MHZ:
324                         case BANDWIDTH_6_MHZ: // not defined by AVC spec
325                         case BANDWIDTH_AUTO:
326                         default:
327                                 CmdFrm.operand[12] = 0x00;
328                         }
329                         switch(params->u.ofdm.constellation) {
330                         case QAM_16:
331                                 CmdFrm.operand[13] = 1 << 6;
332                                 break;
333                         case QAM_64:
334                                 CmdFrm.operand[13] = 2 << 6;
335                                 break;
336                         case QPSK:
337                         default:
338                                 CmdFrm.operand[13] = 0x00;
339                         }
340                         switch(params->u.ofdm.hierarchy_information) {
341                         case HIERARCHY_1:
342                                 CmdFrm.operand[13] |= 1 << 3;
343                                 break;
344                         case HIERARCHY_2:
345                                 CmdFrm.operand[13] |= 2 << 3;
346                                 break;
347                         case HIERARCHY_4:
348                                 CmdFrm.operand[13] |= 3 << 3;
349                                 break;
350                         case HIERARCHY_AUTO:
351                         case HIERARCHY_NONE:
352                         default:
353                                 break;
354                         }
355                         switch(params->u.ofdm.code_rate_HP) {
356                         case FEC_2_3:
357                                 CmdFrm.operand[13] |= 1;
358                                 break;
359                         case FEC_3_4:
360                                 CmdFrm.operand[13] |= 2;
361                                 break;
362                         case FEC_5_6:
363                                 CmdFrm.operand[13] |= 3;
364                                 break;
365                         case FEC_7_8:
366                                 CmdFrm.operand[13] |= 4;
367                                 break;
368                         case FEC_1_2:
369                         default:
370                                 break;
371                         }
372                         switch(params->u.ofdm.code_rate_LP) {
373                         case FEC_2_3:
374                                 CmdFrm.operand[14] = 1 << 5;
375                                 break;
376                         case FEC_3_4:
377                                 CmdFrm.operand[14] = 2 << 5;
378                                 break;
379                         case FEC_5_6:
380                                 CmdFrm.operand[14] = 3 << 5;
381                                 break;
382                         case FEC_7_8:
383                                 CmdFrm.operand[14] = 4 << 5;
384                                 break;
385                         case FEC_1_2:
386                         default:
387                                 CmdFrm.operand[14] = 0x00;
388                                 break;
389                         }
390                         switch(params->u.ofdm.guard_interval) {
391                         case GUARD_INTERVAL_1_16:
392                                 CmdFrm.operand[14] |= 1 << 3;
393                                 break;
394                         case GUARD_INTERVAL_1_8:
395                                 CmdFrm.operand[14] |= 2 << 3;
396                                 break;
397                         case GUARD_INTERVAL_1_4:
398                                 CmdFrm.operand[14] |= 3 << 3;
399                                 break;
400                         case GUARD_INTERVAL_1_32:
401                         case GUARD_INTERVAL_AUTO:
402                         default:
403                                 break;
404                         }
405                         switch(params->u.ofdm.transmission_mode) {
406                         case TRANSMISSION_MODE_8K:
407                                 CmdFrm.operand[14] |= 1 << 1;
408                                 break;
409                         case TRANSMISSION_MODE_2K:
410                         case TRANSMISSION_MODE_AUTO:
411                         default:
412                                 break;
413                         }
414
415                         CmdFrm.operand[15] = 0x00; // network_ID[0]
416                         CmdFrm.operand[16] = 0x00; // network_ID[1]
417                         CmdFrm.operand[17] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
418
419                         CmdFrm.length = 20;
420                 } else {
421                         CmdFrm.operand[7]  = 0x00;
422                         CmdFrm.operand[8]  = (((firesat->voltage==SEC_VOLTAGE_18)?0:1)<<6); /* 0 = H, 1 = V */
423                         CmdFrm.operand[9]  = 0x00;
424                         CmdFrm.operand[10] = 0x00;
425
426                         if(firesat->type == FireSAT_DVB_S) {
427                                 /* ### relative frequency -> absolute frequency */
428                                 CmdFrm.operand[11] = (((params->frequency/4) >> 16) & 0xFF) | (2 << 6);
429                                 CmdFrm.operand[12] = ((params->frequency/4) >> 8) & 0xFF;
430                                 CmdFrm.operand[13] = (params->frequency/4) & 0xFF;
431                         } else if(firesat->type == FireSAT_DVB_C) {
432                                 CmdFrm.operand[11] = (((params->frequency/4000) >> 16) & 0xFF) | (2 << 6);
433                                 CmdFrm.operand[12] = ((params->frequency/4000) >> 8) & 0xFF;
434                                 CmdFrm.operand[13] = (params->frequency/4000) & 0xFF;
435                         }
436
437                         CmdFrm.operand[14] = ((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF;
438                         CmdFrm.operand[15] = ((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF;
439                         CmdFrm.operand[16] = ((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0;
440
441                         CmdFrm.operand[17] = 0x00;
442                         switch(params->u.qpsk.fec_inner) {
443                         case FEC_1_2:
444                                 CmdFrm.operand[18] = 0x1;
445                                 break;
446                         case FEC_2_3:
447                                 CmdFrm.operand[18] = 0x2;
448                                 break;
449                         case FEC_3_4:
450                                 CmdFrm.operand[18] = 0x3;
451                                 break;
452                         case FEC_5_6:
453                                 CmdFrm.operand[18] = 0x4;
454                                 break;
455                         case FEC_7_8:
456                                 CmdFrm.operand[18] = 0x5;
457                                 break;
458                         case FEC_4_5:
459                         case FEC_8_9:
460                         case FEC_AUTO:
461                         default:
462                                 CmdFrm.operand[18] = 0x0;
463                         }
464                         if(firesat->type == FireSAT_DVB_S) {
465                                 CmdFrm.operand[19] = 0x08; // modulation
466                         } else if(firesat->type == FireSAT_DVB_C) {
467                                 switch(params->u.qam.modulation) {
468                                 case QAM_16:
469                                         CmdFrm.operand[19] = 0x08; // modulation
470                                         break;
471                                 case QAM_32:
472                                         CmdFrm.operand[19] = 0x10; // modulation
473                                         break;
474                                 case QAM_64:
475                                         CmdFrm.operand[19] = 0x18; // modulation
476                                         break;
477                                 case QAM_128:
478                                         CmdFrm.operand[19] = 0x20; // modulation
479                                         break;
480                                 case QAM_256:
481                                         CmdFrm.operand[19] = 0x28; // modulation
482                                         break;
483                                 case QAM_AUTO:
484                                 default:
485                                         CmdFrm.operand[19] = 0x00; // modulation
486                                 }
487                         }
488                         CmdFrm.operand[20] = 0x00;
489                         CmdFrm.operand[21] = 0x00;
490                         CmdFrm.operand[22] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
491
492                         CmdFrm.length=28;
493                 }
494         } // AVCTuner_DSD_direct
495
496         if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
497                 return k;
498
499 //      msleep(250);
500         mdelay(500);
501
502         if(status)
503                 *status=RspFrm.operand[2];
504         return 0;
505 }
506
507 int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) {
508         AVCCmdFrm CmdFrm;
509         AVCRspFrm RspFrm;
510         int pos,k;
511
512         printk(KERN_INFO "%s\n", __func__);
513
514         if(pidc > 16 && pidc != 0xFF)
515                 return -EINVAL;
516
517         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
518
519         CmdFrm.cts      = AVC;
520         CmdFrm.ctype    = CONTROL;
521         CmdFrm.sutyp    = 0x5;
522         CmdFrm.suid     = firesat->subunit;
523         CmdFrm.opcode   = DSD;
524
525         CmdFrm.operand[0]  = 0; // source plug
526         CmdFrm.operand[1]  = 0xD2; // subfunction replace
527         CmdFrm.operand[2]  = 0x20; // system id = DVB
528         CmdFrm.operand[3]  = 0x00; // antenna number
529         CmdFrm.operand[4]  = 0x11; // system_specific_multiplex selection_length
530         CmdFrm.operand[5]  = 0x00; // valid_flags [0]
531         CmdFrm.operand[6]  = 0x00; // valid_flags [1]
532
533         if(firesat->type == FireSAT_DVB_T) {
534 /*              CmdFrm.operand[7]  = 0x00;
535                 CmdFrm.operand[8]  = 0x00;//(params->frequency/10) >> 24;
536                 CmdFrm.operand[9]  = 0x00;//((params->frequency/10) >> 16) & 0xFF;
537                 CmdFrm.operand[10] = 0x00;//((params->frequency/10) >>  8) & 0xFF;
538                 CmdFrm.operand[11] = 0x00;//(params->frequency/10) & 0xFF;
539                 CmdFrm.operand[12] = 0x00;
540                 CmdFrm.operand[13] = 0x00;
541                 CmdFrm.operand[14] = 0x00;
542
543                 CmdFrm.operand[15] = 0x00; // network_ID[0]
544                 CmdFrm.operand[16] = 0x00; // network_ID[1]
545 */              CmdFrm.operand[17] = pidc; // Nr_of_dsd_sel_specs
546
547                 pos=18;
548         } else {
549 /*              CmdFrm.operand[7]  = 0x00;
550                 CmdFrm.operand[8]  = 0x00;
551                 CmdFrm.operand[9]  = 0x00;
552                 CmdFrm.operand[10] = 0x00;
553
554                 CmdFrm.operand[11] = 0x00;//(((params->frequency/4) >> 16) & 0xFF) | (2 << 6);
555                 CmdFrm.operand[12] = 0x00;//((params->frequency/4) >> 8) & 0xFF;
556                 CmdFrm.operand[13] = 0x00;//(params->frequency/4) & 0xFF;
557
558                 CmdFrm.operand[14] = 0x00;//((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF;
559                 CmdFrm.operand[15] = 0x00;//((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF;
560                 CmdFrm.operand[16] = 0x00;//((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0;
561
562                 CmdFrm.operand[17] = 0x00;
563                 CmdFrm.operand[18] = 0x00;
564                 CmdFrm.operand[19] = 0x00; // modulation
565                 CmdFrm.operand[20] = 0x00;
566                 CmdFrm.operand[21] = 0x00;*/
567                 CmdFrm.operand[22] = pidc; // Nr_of_dsd_sel_specs
568
569                 pos=23;
570         }
571         if(pidc != 0xFF)
572                 for(k=0;k<pidc;k++) {
573                         CmdFrm.operand[pos++] = 0x13; // flowfunction relay
574                         CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
575                         CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
576                         CmdFrm.operand[pos++] = pid[k] & 0xFF;
577                         CmdFrm.operand[pos++] = 0x00; // tableID
578                         CmdFrm.operand[pos++] = 0x00; // filter_length
579                 }
580
581         CmdFrm.length = pos+3;
582
583         if((pos+3)%4)
584                 CmdFrm.length += 4 - ((pos+3)%4);
585
586         if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
587                 return k;
588
589         mdelay(250);
590
591         return 0;
592 }
593
594 int AVCTuner_GetTS(struct firesat *firesat){
595         AVCCmdFrm CmdFrm;
596         AVCRspFrm RspFrm;
597         int k;
598
599         printk(KERN_INFO "%s\n", __func__);
600
601         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
602
603         CmdFrm.cts              = AVC;
604         CmdFrm.ctype    = CONTROL;
605         CmdFrm.sutyp    = 0x5;
606         CmdFrm.suid             = firesat->subunit;
607         CmdFrm.opcode   = DSIT;
608
609         CmdFrm.operand[0]  = 0; // source plug
610         CmdFrm.operand[1]  = 0xD2; // subfunction replace
611         CmdFrm.operand[2]  = 0xFF; //status
612         CmdFrm.operand[3]  = 0x20; // system id = DVB
613         CmdFrm.operand[4]  = 0x00; // antenna number
614         CmdFrm.operand[5]  = 0x0;  // system_specific_search_flags
615         CmdFrm.operand[6]  = 0x11; // system_specific_multiplex selection_length
616         CmdFrm.operand[7]  = 0x00; // valid_flags [0]
617         CmdFrm.operand[8]  = 0x00; // valid_flags [1]
618         CmdFrm.operand[24] = 0x00; // nr_of_dsit_sel_specs (always 0)
619
620         CmdFrm.length = 28;
621
622         if((k=AVCWrite(firesat, &CmdFrm, &RspFrm))) return k;
623
624         mdelay(250);
625         return 0;
626 }
627
628 int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *transport, int *has_ci) {
629         AVCCmdFrm CmdFrm;
630         AVCRspFrm RspFrm;
631
632         memset(&CmdFrm,0,sizeof(AVCCmdFrm));
633
634         CmdFrm.cts = AVC;
635         CmdFrm.ctype = CONTROL;
636         CmdFrm.sutyp = 0x5; // tuner
637         CmdFrm.suid = firesat->subunit;
638         CmdFrm.opcode = READ_DESCRIPTOR;
639
640         CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
641         CmdFrm.operand[1]=0xff;
642         CmdFrm.operand[2]=0x00;
643         CmdFrm.operand[3]=0x00; // length highbyte
644         CmdFrm.operand[4]=0x08; // length lowbyte
645         CmdFrm.operand[5]=0x00; // offset highbyte
646         CmdFrm.operand[6]=0x0d; // offset lowbyte
647
648         CmdFrm.length=12;
649
650         if(AVCWrite(firesat,&CmdFrm,&RspFrm)<0)
651                 return -EIO;
652
653         if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
654                 printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp);
655                 return -EINVAL;
656         }
657         if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) {
658                 printk("%s: Invalid response length\n",__func__);
659                 return -EINVAL;
660         }
661         if(systemId)
662                 *systemId = RspFrm.operand[7];
663         if(has_ci)
664                 *has_ci = (RspFrm.operand[14] >> 4) & 0x1;
665         return 0;
666 }
667
668 int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info) {
669         AVCCmdFrm CmdFrm;
670         AVCRspFrm RspFrm;
671         int length;
672
673         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
674
675         CmdFrm.cts=AVC;
676         CmdFrm.ctype=CONTROL;
677         CmdFrm.sutyp=0x05; // tuner
678         CmdFrm.suid=firesat->subunit;
679         CmdFrm.opcode=READ_DESCRIPTOR;
680
681         CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
682         CmdFrm.operand[1]=0xff;
683         CmdFrm.operand[2]=0x00;
684         CmdFrm.operand[3]=sizeof(ANTENNA_INPUT_INFO) >> 8;
685         CmdFrm.operand[4]=sizeof(ANTENNA_INPUT_INFO) & 0xFF;
686         CmdFrm.operand[5]=0x00;
687         CmdFrm.operand[6]=0x03;
688         CmdFrm.length=12;
689         //Absenden des AVC request und warten auf response
690         if (AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
691                 return -EIO;
692
693         if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
694                 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
695                 return -EINVAL;
696         }
697
698         length = (RspFrm.operand[3] << 8) + RspFrm.operand[4];
699         if(length == sizeof(ANTENNA_INPUT_INFO))
700         {
701                 memcpy(antenna_input_info,&RspFrm.operand[7],length);
702                 return 0;
703         }
704         printk("%s: invalid info returned from AVC\n",__func__);
705         return -EINVAL;
706 }
707
708 int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
709                   char conttone, char nrdiseq,
710                   struct dvb_diseqc_master_cmd *diseqcmd)
711 {
712         AVCCmdFrm CmdFrm;
713         AVCRspFrm RspFrm;
714         int i,j;
715
716         printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone);
717
718         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
719
720         CmdFrm.cts=AVC;
721         CmdFrm.ctype=CONTROL;
722         CmdFrm.sutyp=0x05;
723         CmdFrm.suid=firesat->subunit;
724         CmdFrm.opcode=VENDOR;
725
726         CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
727         CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
728         CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
729         CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
730
731         CmdFrm.operand[4]=voltage;
732         CmdFrm.operand[5]=nrdiseq;
733
734         i=6;
735
736         for(j=0;j<nrdiseq;j++) {
737                 int k;
738                 printk(KERN_INFO "%s: diseq %d len %x\n",__func__,j,diseqcmd[j].msg_len);
739                 CmdFrm.operand[i++]=diseqcmd[j].msg_len;
740
741                 for(k=0;k<diseqcmd[j].msg_len;k++) {
742                         printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",__func__,j,k,diseqcmd[j].msg[k]);
743                         CmdFrm.operand[i++]=diseqcmd[j].msg[k];
744                 }
745         }
746
747         CmdFrm.operand[i++]=burst;
748         CmdFrm.operand[i++]=conttone;
749
750         CmdFrm.length=i+3;
751         if((i+3)%4)
752                 CmdFrm.length += 4 - ((i+3)%4);
753
754 /*      for(j=0;j<CmdFrm.length;j++)
755                 printk(KERN_INFO "%s: CmdFrm.operand[%d]=0x%x\n",__func__,j,CmdFrm.operand[j]);
756
757         printk(KERN_INFO "%s: cmdfrm.length = %u\n",__func__,CmdFrm.length);
758         */
759         if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
760                 return -EIO;
761
762         if(RspFrm.resp != ACCEPTED) {
763                 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
764                 return -EINVAL;
765         }
766
767         return 0;
768 }
769
770 int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount)
771 {
772         AVCCmdFrm CmdFrm;
773         AVCRspFrm RspFrm;
774
775         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
776
777         CmdFrm.cts = AVC;
778         CmdFrm.ctype = STATUS;
779         CmdFrm.sutyp = 0x1f;
780         CmdFrm.suid = 0x7;
781         CmdFrm.opcode = SUBUNIT_Info;
782
783         CmdFrm.operand[0] = 0x07;
784         CmdFrm.operand[1] = 0xff;
785         CmdFrm.operand[2] = 0xff;
786         CmdFrm.operand[3] = 0xff;
787         CmdFrm.operand[4] = 0xff;
788
789         CmdFrm.length = 8;
790
791         if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
792                 return -EIO;
793
794         if(RspFrm.resp != STABLE) {
795                 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
796                 return -EINVAL;
797         }
798
799         if(subunitcount)
800                 *subunitcount = (RspFrm.operand[1] & 0x7) + 1;
801
802         return 0;
803 }
804
805 static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal)
806 {
807         AVCCmdFrm CmdFrm;
808
809 //      printk(KERN_INFO "%s\n",__func__);
810
811         memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
812
813         CmdFrm.cts = AVC;
814         CmdFrm.ctype = NOTIFY;
815         CmdFrm.sutyp = 0x1f;
816         CmdFrm.suid = 0x7;
817         CmdFrm.opcode = VENDOR;
818
819         CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
820         CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
821         CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
822         CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
823
824         CmdFrm.length = 8;
825
826         if(internal) {
827                 if(__AVCWrite(firesat,&CmdFrm,NULL) < 0)
828                         return -EIO;
829         } else
830                 if(AVCWrite(firesat,&CmdFrm,NULL) < 0)
831                         return -EIO;
832
833         return 0;
834 }
835
836 int AVCRegisterRemoteControl(struct firesat*firesat)
837 {
838         return __AVCRegisterRemoteControl(firesat, 0);
839 }