blob: d70795623fb9d645e1ccabe610b304e96bfacf35 [file] [log] [blame]
Greg Kroah-Hartmanc81c8b62008-03-06 21:30:23 -08001/*
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
25static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal);
26
27/* Frees an allocated packet */
28static 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 */
38static 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
50static 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
99int 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
110static void do_schedule_remotecontrol(unsigned long ignored);
111DECLARE_TASKLET(schedule_remotecontrol, do_schedule_remotecontrol, 0);
112
113static 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
135int 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)
185static 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 CmdFrm->length = 16;
244}
245
246int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, BYTE *status) {
247 AVCCmdFrm CmdFrm;
248 AVCRspFrm RspFrm;
249 M_VALID_FLAGS flags;
250 int k;
251
252// printk(KERN_INFO "%s\n", __func__);
253
254 if(firesat->type == FireSAT_DVB_S)
255 AVCTuner_tuneQPSK(firesat, params, &CmdFrm);
256 else {
257 if(firesat->type == FireSAT_DVB_T) {
258 flags.Bits_T.GuardInterval = (params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO);
259 flags.Bits_T.CodeRateLPStream = (params->u.ofdm.code_rate_LP != FEC_AUTO);
260 flags.Bits_T.CodeRateHPStream = (params->u.ofdm.code_rate_HP != FEC_AUTO);
261 flags.Bits_T.HierarchyInfo = (params->u.ofdm.hierarchy_information != HIERARCHY_AUTO);
262 flags.Bits_T.Constellation = (params->u.ofdm.constellation != QAM_AUTO);
263 flags.Bits_T.Bandwidth = (params->u.ofdm.bandwidth != BANDWIDTH_AUTO);
264 flags.Bits_T.CenterFrequency = 1;
265 flags.Bits_T.reserved1 = 0;
266 flags.Bits_T.reserved2 = 0;
267 flags.Bits_T.OtherFrequencyFlag = 0;
268 flags.Bits_T.TransmissionMode = (params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO);
269 flags.Bits_T.NetworkId = 0;
270 } else {
271 flags.Bits.Modulation = 0;
272 if(firesat->type == FireSAT_DVB_S) {
273 flags.Bits.FEC_inner = 1;
274 } else if(firesat->type == FireSAT_DVB_C) {
275 flags.Bits.FEC_inner = 0;
276 }
277 flags.Bits.FEC_outer = 0;
278 flags.Bits.Symbol_Rate = 1;
279 flags.Bits.Frequency = 1;
280 flags.Bits.Orbital_Pos = 0;
281 if(firesat->type == FireSAT_DVB_S) {
282 flags.Bits.Polarisation = 1;
283 } else if(firesat->type == FireSAT_DVB_C) {
284 flags.Bits.Polarisation = 0;
285 }
286 flags.Bits.reserved_fields = 0;
287 flags.Bits.reserved1 = 0;
288 flags.Bits.Network_ID = 0;
289 }
290
291 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
292
293 CmdFrm.cts = AVC;
294 CmdFrm.ctype = CONTROL;
295 CmdFrm.sutyp = 0x5;
296 CmdFrm.suid = firesat->subunit;
297 CmdFrm.opcode = DSD;
298
299 CmdFrm.operand[0] = 0; // source plug
300 CmdFrm.operand[1] = 0xD2; // subfunction replace
301 CmdFrm.operand[2] = 0x20; // system id = DVB
302 CmdFrm.operand[3] = 0x00; // antenna number
303 CmdFrm.operand[4] = (firesat->type == FireSAT_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
304 CmdFrm.operand[5] = flags.Valid_Word.ByteHi; // valid_flags [0]
305 CmdFrm.operand[6] = flags.Valid_Word.ByteLo; // valid_flags [1]
306
307 if(firesat->type == FireSAT_DVB_T) {
308 CmdFrm.operand[7] = 0x0;
309 CmdFrm.operand[8] = (params->frequency/10) >> 24;
310 CmdFrm.operand[9] = ((params->frequency/10) >> 16) & 0xFF;
311 CmdFrm.operand[10] = ((params->frequency/10) >> 8) & 0xFF;
312 CmdFrm.operand[11] = (params->frequency/10) & 0xFF;
313 switch(params->u.ofdm.bandwidth) {
314 case BANDWIDTH_7_MHZ:
315 CmdFrm.operand[12] = 0x20;
316 break;
317 case BANDWIDTH_8_MHZ:
318 case BANDWIDTH_6_MHZ: // not defined by AVC spec
319 case BANDWIDTH_AUTO:
320 default:
321 CmdFrm.operand[12] = 0x00;
322 }
323 switch(params->u.ofdm.constellation) {
324 case QAM_16:
325 CmdFrm.operand[13] = 1 << 6;
326 break;
327 case QAM_64:
328 CmdFrm.operand[13] = 2 << 6;
329 break;
330 case QPSK:
331 default:
332 CmdFrm.operand[13] = 0x00;
333 }
334 switch(params->u.ofdm.hierarchy_information) {
335 case HIERARCHY_1:
336 CmdFrm.operand[13] |= 1 << 3;
337 break;
338 case HIERARCHY_2:
339 CmdFrm.operand[13] |= 2 << 3;
340 break;
341 case HIERARCHY_4:
342 CmdFrm.operand[13] |= 3 << 3;
343 break;
344 case HIERARCHY_AUTO:
345 case HIERARCHY_NONE:
346 default:
347 break;
348 }
349 switch(params->u.ofdm.code_rate_HP) {
350 case FEC_2_3:
351 CmdFrm.operand[13] |= 1;
352 break;
353 case FEC_3_4:
354 CmdFrm.operand[13] |= 2;
355 break;
356 case FEC_5_6:
357 CmdFrm.operand[13] |= 3;
358 break;
359 case FEC_7_8:
360 CmdFrm.operand[13] |= 4;
361 break;
362 case FEC_1_2:
363 default:
364 break;
365 }
366 switch(params->u.ofdm.code_rate_LP) {
367 case FEC_2_3:
368 CmdFrm.operand[14] = 1 << 5;
369 break;
370 case FEC_3_4:
371 CmdFrm.operand[14] = 2 << 5;
372 break;
373 case FEC_5_6:
374 CmdFrm.operand[14] = 3 << 5;
375 break;
376 case FEC_7_8:
377 CmdFrm.operand[14] = 4 << 5;
378 break;
379 case FEC_1_2:
380 default:
381 CmdFrm.operand[14] = 0x00;
382 break;
383 }
384 switch(params->u.ofdm.guard_interval) {
385 case GUARD_INTERVAL_1_16:
386 CmdFrm.operand[14] |= 1 << 3;
387 break;
388 case GUARD_INTERVAL_1_8:
389 CmdFrm.operand[14] |= 2 << 3;
390 break;
391 case GUARD_INTERVAL_1_4:
392 CmdFrm.operand[14] |= 3 << 3;
393 break;
394 case GUARD_INTERVAL_1_32:
395 case GUARD_INTERVAL_AUTO:
396 default:
397 break;
398 }
399 switch(params->u.ofdm.transmission_mode) {
400 case TRANSMISSION_MODE_8K:
401 CmdFrm.operand[14] |= 1 << 1;
402 break;
403 case TRANSMISSION_MODE_2K:
404 case TRANSMISSION_MODE_AUTO:
405 default:
406 break;
407 }
408
409 CmdFrm.operand[15] = 0x00; // network_ID[0]
410 CmdFrm.operand[16] = 0x00; // network_ID[1]
411 CmdFrm.operand[17] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
412
413 CmdFrm.length = 20;
414 } else {
415 CmdFrm.operand[7] = 0x00;
416 CmdFrm.operand[8] = (((firesat->voltage==SEC_VOLTAGE_18)?0:1)<<6); /* 0 = H, 1 = V */
417 CmdFrm.operand[9] = 0x00;
418 CmdFrm.operand[10] = 0x00;
419
420 if(firesat->type == FireSAT_DVB_S) {
421 /* ### relative frequency -> absolute frequency */
422 CmdFrm.operand[11] = (((params->frequency/4) >> 16) & 0xFF) | (2 << 6);
423 CmdFrm.operand[12] = ((params->frequency/4) >> 8) & 0xFF;
424 CmdFrm.operand[13] = (params->frequency/4) & 0xFF;
425 } else if(firesat->type == FireSAT_DVB_C) {
426 CmdFrm.operand[11] = (((params->frequency/4000) >> 16) & 0xFF) | (2 << 6);
427 CmdFrm.operand[12] = ((params->frequency/4000) >> 8) & 0xFF;
428 CmdFrm.operand[13] = (params->frequency/4000) & 0xFF;
429 }
430
431 CmdFrm.operand[14] = ((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF;
432 CmdFrm.operand[15] = ((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF;
433 CmdFrm.operand[16] = ((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0;
434
435 CmdFrm.operand[17] = 0x00;
436 switch(params->u.qpsk.fec_inner) {
437 case FEC_1_2:
438 CmdFrm.operand[18] = 0x1;
439 break;
440 case FEC_2_3:
441 CmdFrm.operand[18] = 0x2;
442 break;
443 case FEC_3_4:
444 CmdFrm.operand[18] = 0x3;
445 break;
446 case FEC_5_6:
447 CmdFrm.operand[18] = 0x4;
448 break;
449 case FEC_7_8:
450 CmdFrm.operand[18] = 0x5;
451 break;
452 case FEC_4_5:
453 case FEC_8_9:
454 case FEC_AUTO:
455 default:
456 CmdFrm.operand[18] = 0x0;
457 }
458 if(firesat->type == FireSAT_DVB_S) {
459 CmdFrm.operand[19] = 0x08; // modulation
460 } else if(firesat->type == FireSAT_DVB_C) {
461 switch(params->u.qam.modulation) {
462 case QAM_16:
463 CmdFrm.operand[19] = 0x08; // modulation
464 break;
465 case QAM_32:
466 CmdFrm.operand[19] = 0x10; // modulation
467 break;
468 case QAM_64:
469 CmdFrm.operand[19] = 0x18; // modulation
470 break;
471 case QAM_128:
472 CmdFrm.operand[19] = 0x20; // modulation
473 break;
474 case QAM_256:
475 CmdFrm.operand[19] = 0x28; // modulation
476 break;
477 case QAM_AUTO:
478 default:
479 CmdFrm.operand[19] = 0x00; // modulation
480 }
481 }
482 CmdFrm.operand[20] = 0x00;
483 CmdFrm.operand[21] = 0x00;
484 CmdFrm.operand[22] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
485
486 CmdFrm.length=28;
487 }
488 } // AVCTuner_DSD_direct
489
490 if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
491 return k;
492
493// msleep(250);
494 mdelay(500);
495
496 if(status)
497 *status=RspFrm.operand[2];
498 return 0;
499}
500
501int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) {
502 AVCCmdFrm CmdFrm;
503 AVCRspFrm RspFrm;
504 int pos,k;
505
506 printk(KERN_INFO "%s\n", __func__);
507
508 if(pidc > 16 && pidc != 0xFF)
509 return -EINVAL;
510
511 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
512
513 CmdFrm.cts = AVC;
514 CmdFrm.ctype = CONTROL;
515 CmdFrm.sutyp = 0x5;
516 CmdFrm.suid = firesat->subunit;
517 CmdFrm.opcode = DSD;
518
519 CmdFrm.operand[0] = 0; // source plug
520 CmdFrm.operand[1] = 0xD2; // subfunction replace
521 CmdFrm.operand[2] = 0x20; // system id = DVB
522 CmdFrm.operand[3] = 0x00; // antenna number
523 CmdFrm.operand[4] = 0x11; // system_specific_multiplex selection_length
524 CmdFrm.operand[5] = 0x00; // valid_flags [0]
525 CmdFrm.operand[6] = 0x00; // valid_flags [1]
526
527 if(firesat->type == FireSAT_DVB_T) {
528/* CmdFrm.operand[7] = 0x00;
529 CmdFrm.operand[8] = 0x00;//(params->frequency/10) >> 24;
530 CmdFrm.operand[9] = 0x00;//((params->frequency/10) >> 16) & 0xFF;
531 CmdFrm.operand[10] = 0x00;//((params->frequency/10) >> 8) & 0xFF;
532 CmdFrm.operand[11] = 0x00;//(params->frequency/10) & 0xFF;
533 CmdFrm.operand[12] = 0x00;
534 CmdFrm.operand[13] = 0x00;
535 CmdFrm.operand[14] = 0x00;
536
537 CmdFrm.operand[15] = 0x00; // network_ID[0]
538 CmdFrm.operand[16] = 0x00; // network_ID[1]
539*/ CmdFrm.operand[17] = pidc; // Nr_of_dsd_sel_specs
540
541 pos=18;
542 } else {
543/* CmdFrm.operand[7] = 0x00;
544 CmdFrm.operand[8] = 0x00;
545 CmdFrm.operand[9] = 0x00;
546 CmdFrm.operand[10] = 0x00;
547
548 CmdFrm.operand[11] = 0x00;//(((params->frequency/4) >> 16) & 0xFF) | (2 << 6);
549 CmdFrm.operand[12] = 0x00;//((params->frequency/4) >> 8) & 0xFF;
550 CmdFrm.operand[13] = 0x00;//(params->frequency/4) & 0xFF;
551
552 CmdFrm.operand[14] = 0x00;//((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF;
553 CmdFrm.operand[15] = 0x00;//((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF;
554 CmdFrm.operand[16] = 0x00;//((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0;
555
556 CmdFrm.operand[17] = 0x00;
557 CmdFrm.operand[18] = 0x00;
558 CmdFrm.operand[19] = 0x00; // modulation
559 CmdFrm.operand[20] = 0x00;
560 CmdFrm.operand[21] = 0x00;*/
561 CmdFrm.operand[22] = pidc; // Nr_of_dsd_sel_specs
562
563 pos=23;
564 }
565 if(pidc != 0xFF)
566 for(k=0;k<pidc;k++) {
567 CmdFrm.operand[pos++] = 0x13; // flowfunction relay
568 CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
569 CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
570 CmdFrm.operand[pos++] = pid[k] & 0xFF;
571 CmdFrm.operand[pos++] = 0x00; // tableID
572 CmdFrm.operand[pos++] = 0x00; // filter_length
573 }
574
575 CmdFrm.length = pos+3;
576
577 if((pos+3)%4)
578 CmdFrm.length += 4 - ((pos+3)%4);
579
580 if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
581 return k;
582
583 mdelay(250);
584
585 return 0;
586}
587
588int AVCTuner_GetTS(struct firesat *firesat){
589 AVCCmdFrm CmdFrm;
590 AVCRspFrm RspFrm;
591 int k;
592
593 printk(KERN_INFO "%s\n", __func__);
594
595 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
596
597 CmdFrm.cts = AVC;
598 CmdFrm.ctype = CONTROL;
599 CmdFrm.sutyp = 0x5;
600 CmdFrm.suid = firesat->subunit;
601 CmdFrm.opcode = DSIT;
602
603 CmdFrm.operand[0] = 0; // source plug
604 CmdFrm.operand[1] = 0xD2; // subfunction replace
605 CmdFrm.operand[2] = 0xFF; //status
606 CmdFrm.operand[3] = 0x20; // system id = DVB
607 CmdFrm.operand[4] = 0x00; // antenna number
608 CmdFrm.operand[5] = 0x0; // system_specific_search_flags
609 CmdFrm.operand[6] = 0x11; // system_specific_multiplex selection_length
610 CmdFrm.operand[7] = 0x00; // valid_flags [0]
611 CmdFrm.operand[8] = 0x00; // valid_flags [1]
612 CmdFrm.operand[24] = 0x00; // nr_of_dsit_sel_specs (always 0)
613
614 CmdFrm.length = 28;
615
616 if((k=AVCWrite(firesat, &CmdFrm, &RspFrm))) return k;
617
618 mdelay(250);
619 return 0;
620}
621
622int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *transport, int *has_ci) {
623 AVCCmdFrm CmdFrm;
624 AVCRspFrm RspFrm;
625
626 memset(&CmdFrm,0,sizeof(AVCCmdFrm));
627
628 CmdFrm.cts = AVC;
629 CmdFrm.ctype = CONTROL;
630 CmdFrm.sutyp = 0x5; // tuner
631 CmdFrm.suid = firesat->subunit;
632 CmdFrm.opcode = READ_DESCRIPTOR;
633
634 CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
635 CmdFrm.operand[1]=0xff;
636 CmdFrm.operand[2]=0x00;
637 CmdFrm.operand[3]=0x00; // length highbyte
638 CmdFrm.operand[4]=0x08; // length lowbyte
639 CmdFrm.operand[5]=0x00; // offset highbyte
640 CmdFrm.operand[6]=0x0d; // offset lowbyte
641
642 CmdFrm.length=12;
643
644 if(AVCWrite(firesat,&CmdFrm,&RspFrm)<0)
645 return -EIO;
646
647 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
648 printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp);
649 return -EINVAL;
650 }
651 if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) {
652 printk("%s: Invalid response length\n",__func__);
653 return -EINVAL;
654 }
655 if(systemId)
656 *systemId = RspFrm.operand[7];
657 if(transport)
658 *transport = RspFrm.operand[14] & 0x7;
659 switch(RspFrm.operand[14] & 0x7) {
660 case 1:
661 printk(KERN_INFO "%s: found DVB/S\n",__func__);
662 break;
663 case 2:
664 printk(KERN_INFO "%s: found DVB/C\n",__func__);
665 break;
666 case 3:
667 printk(KERN_INFO "%s: found DVB/T\n",__func__);
668 break;
669 default:
670 printk(KERN_INFO "%s: found unknown tuner id %u\n",__func__,RspFrm.operand[14] & 0x7);
671 }
672 if(has_ci)
673 *has_ci = (RspFrm.operand[14] >> 4) & 0x1;
674 return 0;
675}
676
677int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info) {
678 AVCCmdFrm CmdFrm;
679 AVCRspFrm RspFrm;
680 int length;
681
682 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
683
684 CmdFrm.cts=AVC;
685 CmdFrm.ctype=CONTROL;
686 CmdFrm.sutyp=0x05; // tuner
687 CmdFrm.suid=firesat->subunit;
688 CmdFrm.opcode=READ_DESCRIPTOR;
689
690 CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
691 CmdFrm.operand[1]=0xff;
692 CmdFrm.operand[2]=0x00;
693 CmdFrm.operand[3]=sizeof(ANTENNA_INPUT_INFO) >> 8;
694 CmdFrm.operand[4]=sizeof(ANTENNA_INPUT_INFO) & 0xFF;
695 CmdFrm.operand[5]=0x00;
696 CmdFrm.operand[6]=0x03;
697 CmdFrm.length=12;
698 //Absenden des AVC request und warten auf response
699 if (AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
700 return -EIO;
701
702 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
703 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
704 return -EINVAL;
705 }
706
707 length = (RspFrm.operand[3] << 8) + RspFrm.operand[4];
708 if(length == sizeof(ANTENNA_INPUT_INFO))
709 {
710 memcpy(antenna_input_info,&RspFrm.operand[7],length);
711 return 0;
712 }
713 printk("%s: invalid info returned from AVC\n",__func__);
714 return -EINVAL;
715}
716
717int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
718 char conttone, char nrdiseq,
719 struct dvb_diseqc_master_cmd *diseqcmd)
720{
721 AVCCmdFrm CmdFrm;
722 AVCRspFrm RspFrm;
723 int i,j;
724
725 printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone);
726
727 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
728
729 CmdFrm.cts=AVC;
730 CmdFrm.ctype=CONTROL;
731 CmdFrm.sutyp=0x05;
732 CmdFrm.suid=firesat->subunit;
733 CmdFrm.opcode=VENDOR;
734
735 CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
736 CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
737 CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
738 CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
739
740 CmdFrm.operand[4]=voltage;
741 CmdFrm.operand[5]=nrdiseq;
742
743 i=6;
744
745 for(j=0;j<nrdiseq;j++) {
746 int k;
747 printk(KERN_INFO "%s: diseq %d len %x\n",__func__,j,diseqcmd[j].msg_len);
748 CmdFrm.operand[i++]=diseqcmd[j].msg_len;
749
750 for(k=0;k<diseqcmd[j].msg_len;k++) {
751 printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",__func__,j,k,diseqcmd[j].msg[k]);
752 CmdFrm.operand[i++]=diseqcmd[j].msg[k];
753 }
754 }
755
756 CmdFrm.operand[i++]=burst;
757 CmdFrm.operand[i++]=conttone;
758
759 CmdFrm.length=i+3;
760 if((i+3)%4)
761 CmdFrm.length += 4 - ((i+3)%4);
762
763/* for(j=0;j<CmdFrm.length;j++)
764 printk(KERN_INFO "%s: CmdFrm.operand[%d]=0x%x\n",__func__,j,CmdFrm.operand[j]);
765
766 printk(KERN_INFO "%s: cmdfrm.length = %u\n",__func__,CmdFrm.length);
767 */
768 if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
769 return -EIO;
770
771 if(RspFrm.resp != ACCEPTED) {
772 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
773 return -EINVAL;
774 }
775
776 return 0;
777}
778
779int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount)
780{
781 AVCCmdFrm CmdFrm;
782 AVCRspFrm RspFrm;
783
784 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
785
786 CmdFrm.cts = AVC;
787 CmdFrm.ctype = STATUS;
788 CmdFrm.sutyp = 0x1f;
789 CmdFrm.suid = 0x7;
790 CmdFrm.opcode = SUBUNIT_Info;
791
792 CmdFrm.operand[0] = 0x07;
793 CmdFrm.operand[1] = 0xff;
794 CmdFrm.operand[2] = 0xff;
795 CmdFrm.operand[3] = 0xff;
796 CmdFrm.operand[4] = 0xff;
797
798 CmdFrm.length = 8;
799
800 if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
801 return -EIO;
802
803 if(RspFrm.resp != STABLE) {
804 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
805 return -EINVAL;
806 }
807
808 if(subunitcount)
809 *subunitcount = (RspFrm.operand[1] & 0x7) + 1;
810
811 return 0;
812}
813
814static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal)
815{
816 AVCCmdFrm CmdFrm;
817
818// printk(KERN_INFO "%s\n",__func__);
819
820 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
821
822 CmdFrm.cts = AVC;
823 CmdFrm.ctype = NOTIFY;
824 CmdFrm.sutyp = 0x1f;
825 CmdFrm.suid = 0x7;
826 CmdFrm.opcode = VENDOR;
827
828 CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
829 CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
830 CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
831 CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
832
833 CmdFrm.length = 8;
834
835 if(internal) {
836 if(__AVCWrite(firesat,&CmdFrm,NULL) < 0)
837 return -EIO;
838 } else
839 if(AVCWrite(firesat,&CmdFrm,NULL) < 0)
840 return -EIO;
841
842 return 0;
843}
844
845int AVCRegisterRemoteControl(struct firesat*firesat)
846{
847 return __AVCRegisterRemoteControl(firesat, 0);
848}