DVB: add firesat driver
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / dvb / firesat / avc_api.c
blobd70795623fb9d645e1ccabe610b304e96bfacf35
1 /*
2 * FireSAT AVC driver
4 * Copyright (c) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (c) 2008 Ben Backx <ben@bbackx.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
13 #include "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"
21 #define RESPONSE_REGISTER 0xFFFFF0000D00ULL
22 #define COMMAND_REGISTER 0xFFFFF0000B00ULL
23 #define PCR_BASE_ADDRESS 0xFFFFF0000900ULL
25 static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal);
27 /* Frees an allocated packet */
28 static void avc_free_packet(struct hpsb_packet *packet)
30 hpsb_free_tlabel(packet);
31 hpsb_free_packet(packet);
35 * Goofy routine that basically does a down_timeout function.
36 * Stolen from sbp2.c
38 static int avc_down_timeout(atomic_t *done, int timeout)
40 int i;
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);
47 return ((i > 0) ? 0:1);
50 static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) {
51 struct hpsb_packet *packet;
52 struct node_entry *ne;
54 ne = firesat->nodeentry;
55 if(!ne) {
56 printk("%s: lost node!\n",__func__);
57 return -EIO;
60 /* need all input data */
61 if(!firesat || !ne || !CmdFrm)
62 return -EINVAL;
64 // printk(KERN_INFO "AVCWrite command %x\n",CmdFrm->opcode);
66 // for(k=0;k<CmdFrm->length;k++)
67 // printk(KERN_INFO "CmdFrm[%d] = %08x\n", k, ((quadlet_t*)CmdFrm)[k]);
69 packet=hpsb_make_writepacket(ne->host, ne->nodeid, COMMAND_REGISTER,
70 (quadlet_t*)CmdFrm, CmdFrm->length);
72 hpsb_set_packet_complete_task(packet, (void (*)(void*))avc_free_packet,
73 packet);
75 hpsb_node_fill_packet(ne, packet);
77 if(RspFrm)
78 atomic_set(&firesat->avc_reply_received, 0);
80 if (hpsb_send_packet(packet) < 0) {
81 avc_free_packet(packet);
82 atomic_set(&firesat->avc_reply_received, 1);
83 return -EIO;
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;
93 memcpy(RspFrm,firesat->respfrm,firesat->resp_length);
96 return 0;
99 int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) {
100 int ret;
101 if(down_interruptible(&firesat->avc_sem))
102 return -EINTR;
104 ret = __AVCWrite(firesat, CmdFrm, RspFrm);
106 up(&firesat->avc_sem);
107 return ret;
110 static void do_schedule_remotecontrol(unsigned long ignored);
111 DECLARE_TASKLET(schedule_remotecontrol, do_schedule_remotecontrol, 0);
113 static void do_schedule_remotecontrol(unsigned long ignored) {
114 struct firesat *firesat;
115 unsigned long flags;
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);
128 up(&firesat->avc_sem);
132 spin_unlock_irqrestore(&firesat_list_lock, flags);
135 int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
136 // printk(KERN_INFO "%s\n",__func__);
138 // remote control handling
140 AVCRspFrm *RspFrm = (AVCRspFrm*)data;
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]));
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;
159 if(atomic_read(&firesat->avc_reply_received) == 1) {
160 printk("%s: received out-of-order AVC response, ignored\n",__func__);
161 return -EINVAL;
163 // AVCRspFrm *resp=(AVCRspFrm *)data;
164 // int k;
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);
173 // for(k=0;k<2;k++)
174 // printk(KERN_INFO "operand[%d]=%02x\n",k,resp->operand[k]);
176 memcpy(firesat->respfrm,data,length);
177 firesat->resp_length=length;
179 atomic_set(&firesat->avc_reply_received, 1);
181 return 0;
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));
188 CmdFrm->cts = AVC;
189 CmdFrm->ctype = CONTROL;
190 CmdFrm->sutyp = 0x5;
191 CmdFrm->suid = firesat->subunit;
192 CmdFrm->opcode = VENDOR;
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;
199 printk(KERN_INFO "%s: tuning to frequency %u\n",__func__,params->frequency);
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;
206 printk(KERN_INFO "%s: symbol rate = %uBd\n",__func__,params->u.qpsk.symbol_rate);
208 CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate/1000) >> 8) & 0xFF;
209 CmdFrm->operand[9] = (params->u.qpsk.symbol_rate/1000) & 0xFF;
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;
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
243 CmdFrm->length = 16;
246 int 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;
252 // printk(KERN_INFO "%s\n", __func__);
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;
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;
286 flags.Bits.reserved_fields = 0;
287 flags.Bits.reserved1 = 0;
288 flags.Bits.Network_ID = 0;
291 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
293 CmdFrm.cts = AVC;
294 CmdFrm.ctype = CONTROL;
295 CmdFrm.sutyp = 0x5;
296 CmdFrm.suid = firesat->subunit;
297 CmdFrm.opcode = DSD;
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]
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;
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;
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;
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;
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;
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;
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;
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
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;
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;
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;
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;
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
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
486 CmdFrm.length=28;
488 } // AVCTuner_DSD_direct
490 if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
491 return k;
493 // msleep(250);
494 mdelay(500);
496 if(status)
497 *status=RspFrm.operand[2];
498 return 0;
501 int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) {
502 AVCCmdFrm CmdFrm;
503 AVCRspFrm RspFrm;
504 int pos,k;
506 printk(KERN_INFO "%s\n", __func__);
508 if(pidc > 16 && pidc != 0xFF)
509 return -EINVAL;
511 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
513 CmdFrm.cts = AVC;
514 CmdFrm.ctype = CONTROL;
515 CmdFrm.sutyp = 0x5;
516 CmdFrm.suid = firesat->subunit;
517 CmdFrm.opcode = DSD;
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]
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;
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
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;
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;
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;
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
563 pos=23;
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
575 CmdFrm.length = pos+3;
577 if((pos+3)%4)
578 CmdFrm.length += 4 - ((pos+3)%4);
580 if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
581 return k;
583 mdelay(250);
585 return 0;
588 int AVCTuner_GetTS(struct firesat *firesat){
589 AVCCmdFrm CmdFrm;
590 AVCRspFrm RspFrm;
591 int k;
593 printk(KERN_INFO "%s\n", __func__);
595 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
597 CmdFrm.cts = AVC;
598 CmdFrm.ctype = CONTROL;
599 CmdFrm.sutyp = 0x5;
600 CmdFrm.suid = firesat->subunit;
601 CmdFrm.opcode = DSIT;
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)
614 CmdFrm.length = 28;
616 if((k=AVCWrite(firesat, &CmdFrm, &RspFrm))) return k;
618 mdelay(250);
619 return 0;
622 int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *transport, int *has_ci) {
623 AVCCmdFrm CmdFrm;
624 AVCRspFrm RspFrm;
626 memset(&CmdFrm,0,sizeof(AVCCmdFrm));
628 CmdFrm.cts = AVC;
629 CmdFrm.ctype = CONTROL;
630 CmdFrm.sutyp = 0x5; // tuner
631 CmdFrm.suid = firesat->subunit;
632 CmdFrm.opcode = READ_DESCRIPTOR;
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
642 CmdFrm.length=12;
644 if(AVCWrite(firesat,&CmdFrm,&RspFrm)<0)
645 return -EIO;
647 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
648 printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp);
649 return -EINVAL;
651 if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) {
652 printk("%s: Invalid response length\n",__func__);
653 return -EINVAL;
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);
672 if(has_ci)
673 *has_ci = (RspFrm.operand[14] >> 4) & 0x1;
674 return 0;
677 int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info) {
678 AVCCmdFrm CmdFrm;
679 AVCRspFrm RspFrm;
680 int length;
682 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
684 CmdFrm.cts=AVC;
685 CmdFrm.ctype=CONTROL;
686 CmdFrm.sutyp=0x05; // tuner
687 CmdFrm.suid=firesat->subunit;
688 CmdFrm.opcode=READ_DESCRIPTOR;
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;
702 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
703 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
704 return -EINVAL;
707 length = (RspFrm.operand[3] << 8) + RspFrm.operand[4];
708 if(length == sizeof(ANTENNA_INPUT_INFO))
710 memcpy(antenna_input_info,&RspFrm.operand[7],length);
711 return 0;
713 printk("%s: invalid info returned from AVC\n",__func__);
714 return -EINVAL;
717 int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
718 char conttone, char nrdiseq,
719 struct dvb_diseqc_master_cmd *diseqcmd)
721 AVCCmdFrm CmdFrm;
722 AVCRspFrm RspFrm;
723 int i,j;
725 printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone);
727 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
729 CmdFrm.cts=AVC;
730 CmdFrm.ctype=CONTROL;
731 CmdFrm.sutyp=0x05;
732 CmdFrm.suid=firesat->subunit;
733 CmdFrm.opcode=VENDOR;
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;
740 CmdFrm.operand[4]=voltage;
741 CmdFrm.operand[5]=nrdiseq;
743 i=6;
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;
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];
756 CmdFrm.operand[i++]=burst;
757 CmdFrm.operand[i++]=conttone;
759 CmdFrm.length=i+3;
760 if((i+3)%4)
761 CmdFrm.length += 4 - ((i+3)%4);
763 /* for(j=0;j<CmdFrm.length;j++)
764 printk(KERN_INFO "%s: CmdFrm.operand[%d]=0x%x\n",__func__,j,CmdFrm.operand[j]);
766 printk(KERN_INFO "%s: cmdfrm.length = %u\n",__func__,CmdFrm.length);
768 if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
769 return -EIO;
771 if(RspFrm.resp != ACCEPTED) {
772 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
773 return -EINVAL;
776 return 0;
779 int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount)
781 AVCCmdFrm CmdFrm;
782 AVCRspFrm RspFrm;
784 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
786 CmdFrm.cts = AVC;
787 CmdFrm.ctype = STATUS;
788 CmdFrm.sutyp = 0x1f;
789 CmdFrm.suid = 0x7;
790 CmdFrm.opcode = SUBUNIT_Info;
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;
798 CmdFrm.length = 8;
800 if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
801 return -EIO;
803 if(RspFrm.resp != STABLE) {
804 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp);
805 return -EINVAL;
808 if(subunitcount)
809 *subunitcount = (RspFrm.operand[1] & 0x7) + 1;
811 return 0;
814 static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal)
816 AVCCmdFrm CmdFrm;
818 // printk(KERN_INFO "%s\n",__func__);
820 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
822 CmdFrm.cts = AVC;
823 CmdFrm.ctype = NOTIFY;
824 CmdFrm.sutyp = 0x1f;
825 CmdFrm.suid = 0x7;
826 CmdFrm.opcode = VENDOR;
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;
833 CmdFrm.length = 8;
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;
842 return 0;
845 int AVCRegisterRemoteControl(struct firesat*firesat)
847 return __AVCRegisterRemoteControl(firesat, 0);