The VP-1020, Twinhan, VVmer satellite reciever card. 1. Introduction. 2. bttv driver. 3. i2c level 4. The kernel module. 5. The packets to the asic. 6. Tuner Packets 6.1 ci tuner packet 6.2 fta tuner packet 6.3 other packets 7. DMA operations. 8. I2C timing and error recovery. 9. Circuit description. 10. Changes to this document. 1. Introduction. The card is marketed under different labels, mine is a VVmer TV@Sat card, but I believe it to be the same as a VisionPlus VP-1020 and a Twinhan. The BTTV card list has it as: DST Card/DST-IP (bt878, twinhan asic) VP-1020 Sold as: KWorld DVBS Satellite TV-Card Powercolor DSTV Satellite Tuner Card Prolink Pixelview DTV2000 Provideo PV-911 Digital Satellite TV Tuner Card With Common Interface ? DST-CI Card (DVB Satellite) VP-1030 DCT Card (DVB cable) The card consists of a BT848 (or connexant equiv), an alps tuner and an asic. In respect of it's use of the CX/BT chip it is similar to the Pinnacle PCTVSAT 2. bttv driver. The normal bttv driver hangs and the whole system locks up on detecting the bt848 chip. Most unLinuxy :( The PCI id is all zeroes. On tracking down where the hangs occur, it is in most areas to do with video capture initialisation. The BT chip is not used for video capture on this card. In order to prevent lockups, I changed my version of the bttv driver to have the unknown device have zero video inputs, and changed the core driver not to do any capture / video initialisation if video inputs count is zero. I'm not sure what the right solution is here, because so little of the bttv driver is actually used. 3. i2c level The i2c is also slightly different in that gpio pin 0 has to be driven low for i2c signals to go out. After I2c transfer, this pin is left not output enabled. I2c is not done to the tuner but to the asic at address 0x55. Data is sent in small packets, comprising part of the tuner frequency and part qpsk code, and part bits for 13/18 V and 22Khz tone. At this stage I presume the asic sends this data out to relevant parts of the board. 4. The kernel module. This module is a fairly transparent elf module. The kernel module allows very low level commands to be sent to the card. The interface is not like the current dvb drivers. 5. The packets to the asic. The card is determined to be ci based or fta. The packet 0 | 6 | 0 | 0 | 0 | 0 | 0 | 0xfa is sent to the asic (0x55). If it was sent OK, and the reply is "DST-CI", then the card is CI. On my card, the response is DST-020. For fta devices, packets seem to be fixed length. For ci devices, the first byte appears to be a length indicator then following bytes the same as fta. The method works by sending the packet to 0x55, (actually in the code the address is put in the first byte of the buffer and handled as an address by the sending routine. The sending is done not by bit banging, so 0xaa is put into byte 0 for send, 0xab for recieve) Then the asic is read a single byte as response. There may also be an 8820 device. It is reset in certain conditions by pulling GPIO bit 2 low, waiting, then releasing back to high. 6. Tuner Packets 6.1 ci tuner packet example values lnb1=5150,lnb2=10750; h_v=0; freq=4000; symrate=28125; symbol rate div 1000, e.g symrate=28125 freq / 1000 (e.g. 4000) freq_diff = freq below lnb_lo or freq above lnb_hi tuner packet sent to 0x55 byte 0: len = 9 1: 0 2: (freq_diff & 0x7f ) >> 8 3: freq_diff low byte 4: 1 (could be any reference division ratio) 5: (sym >> 16) & 0x7f; 6: sym >> 8; 7: sym; 8: 0x80 (i_Q) 0x40 (h_v) 0x20 (symbol rate > 8000) 0x10 0 8 = 0 4 set if freq_diff <= 1530 2 = 0 1 = 1 for 22K 9: checksum (~bytesum(buf[0..8]) + 1) 6.2 fta tuner packet typical values: lnb1=5150,lnb2=10750; h_v=0; freq=4000; symrate=28125; symbol rate div 1000, e.g symrate=28125 freq / 1000 (e.g. 4000) freq_diff = freq below lnb_lo or freq above lnb_hi symcalc = ((long long)symbolrate << 20) / 88000 tuner packet sent to 0x55 0: (freq_diff & 0x7f ) >> 8 1: freq_diff low byte 2: 1 (could be any reference division ratio) 3: symcalc ( 13..20) 4: symcalc ( 4 .. 12) 5: symcalc ( 0 .. 3) in high nibble 6: 0x80 (i_Q) 0x40 (h_v 13/18V) 0x20 (symbol rate > 8000) 0x10 0 8 = 0 4 set if freq_diff <= 1530 2 = 0 1 = 1 for 22K 7: checksum (~bytesum(buf[0..6]) + 1) 6.3 Other packets. line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 7. DMA operations. DMA is setup for capture as audio data. It is 4092 bytes wide per line, 255 lines per field. The sample driver uses 10 fields. The sample driver uses the following risc program: ===================================================================== The following are repeated NF=10 times, representing frames | | OP_SYNC | 1 << 15 (disable FDSR errs) | BKTR_FM1 | 0 | | The following are repeated NL=255 times, representing lines | | OP_WRITE | OP_SOL | OP_EOL | byte count = 4092 | | address, advancing 4092 bytes each line | | OP_SYNC | BKTR_VRO # wait for VR0 | 0 OP_JUMP start address of risc buffer ===================================================================== The dma ctl register is set to 0x2204f0c 7654 3210 9876 5432 1098 7654 3210 0010 0010 0000 0100 1111 0000 1100 A_SEL (3<<24) 10 = SML (MIC/line audio input) DA_MLB (1<<21) 1 = LSB first for Sony format DA_SBR (1<<14) 1 = Rounded 8-bit samples DA_SDR (0xf<<8) DDF first stage and decimation rate PKTP (3<<2) 32 DWORDS After setup, int_mask |= SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI; and gpio_dma_ctl |= DA_APP | ACAP_EN | RISC_EN | FIFO_EN; /* 0x33 */ To stop capture, gpio_dma_ctl &= ~(RISC_EN | FIFO_EN); 8. I2C timing and error recovery. The I2C mechanism is described here in more detail. The driver uses interrupts for i2c comms. It is possible that using poll driven i2c may not be compatible. The fusion I2C interface has the following bits defined #define I2CMODE 0x80 /* 0 = software, 1 = hardware */ #define I2CRATE 0x40 /* I2C timing frequency. 0 = 99.2 kHz mode 1 = 396.8 kHz mode */ #define I2CNOSTOP 0x20 /* I2C stop mode. 0 = xmit stop, 1 = doesn't */ #define I2CNOSTART 0x10 /* I2C start mode. 0 = xmit START or repeated START transactions. The R/W status from bit 24 is saved for any future 1 byte transactions 1 = Enables 1 byte read or write without START */ #define I2CSYNC 4 /* I2C synchronization */ #define I2CW3BRA 2 /* Number of bytes sent and master/slave acknowledge. This bit has no meaning when I2CNOSTART (bit 4) is high during a write transaction. 0 = Writes transaction of 2 bytes I2CDB(0-1). During a 1-byte read transaction (I2CNOSTART is high), master sends a NACK to end the reads from the slave. 1 = Writes transaction of 3 bytes I2CDB(0-2). During a 1-byte read transaction (I2CNOSTART is high), master sends an ACK after reading the data byte. */ Communication to the asic takes place as follows: pulldownGPIO(pin0); schedule_timeout(10); writei2cpacket: byte 0 address (=0xaa) and byte 1 are sent in first command. byte[0] << 24 | byte[1] << 16 | SCL | SDA | I2CMODE | I2CNOSTOP for byte[j=2 .. n-1]: byte[j] << 24 | SCL | SDA | I2CMODE | I2CNOSTOP | I2CNOSTART byte[n] << 24 | SCL | SDA | I2CMODE | I2CNOSTART schedule_timeout(3); i2cReadVerify: (address (=0xab) << 24) | SCL | SDA | I2CMODE read the single byte reply >> 8, should be FF releaseGPIO(pin 0) wait 8000 schedule_timeout(1)'s for GPIO pin 0 to go low pulldownGPIO(pin 0) schedule_timeout(3) readasic: /* in the driver, this is the code executed. It is in fact wrong ============================================================ for (j = 0; j < no bytes reqd; j++ ) { bits = address (=0xab) << 24 | SCL | SDA | I2CMODE if (j != no bytes reqd - 1) bits |= I2CNOSTOP | I2CW3BRA write schedule_timeout(10); read single byte reply from i2c port } to read from I2C the following should be done: ==============================================*/ for (j = 0; j < no bytes reqd; j++ ) { bits = address (=0xab) << 24 | SCL | SDA | I2CMODE | I2CNOSTOP if (j != no bytes reqd - 1) bits |= I2CW3BRA if (j) bits |= NOSTART write bits to control reg read single byte reply from i2c port } /* end corrected code ====================== */ releaseGPIO ( pin 0) checksum for tuner data save tuner data If at any stage there is an error, then the procedure is releaseGPIO(pin 0) schedule_timeout(10); pulldownGPIO(pin0); schedule_timeout(10); try again. 9. Circuit description. The gpio pins 15:8 go to data pins on the tuner, which means its collecting 8 bit data as Y values. I think it is using async data collection, using the ALRCK pin. This goes to the output of a flipflop which is driven in some way by pin 18 of the tuner, described as bclck-out. The i2c goes first to an asic DTV20023. This then drives the i2c of the tuner as a slave. Only three pins on the asic beyond the i2c seem to be used. 878A: GPIO 15:8 --> Tuner 27:20 GPIO 19 -> tuner 31 GPIO 18 -> 30 GPIO 17 -> 29 GPIO 16 -> 19 GPIO 0 -> Asic pin 5 Other tracks seem to be to do with LNB power etc. ALRCK circuit is: 74f74d device (I don't see how this clocks....) ~RD0 -> H CP0 -> tuner 18 ~SD0 -> H Q0 -> 878a ALRCK Other tuner connections: 16 -> diode D7 14 -> R23 -> Q6 12 -> base Q4 Others to do with power and LNB DTV20023 (44 pin asic) 2 -> tuner 17 (i2c) 3 -> tuner 15 (i2c) 4 -> base Q2 5 -> GPIO 0 -> R11 -> +ve? 7,8 -> 878A i2c 38 -> R32 -> pin 2 -> R33 -> pin 3 -> R12 -> +ve ? -> relay pin (thus the output of 38 allows i2c to go to tuner or is simply vdd ?) 41 -> D8 -> R29 -> analog LNB circuitry Tuner pins PIN NAME PIN No. PIN DESCRIPTION LNB POWER B 1 LNB voltage supply. To put 1000Pf of ceramic capacitor into ground. LNB POWER A 2 LNB voltage supply. To put 1000Pf of ceramic capacitor into ground. A-GND 3, 6 GND. Please don't let any Digital Noise enter through ground. B1 4 5V Supply for RF Amp TR B2 5 5V Supply for ZERO-IF chip B3 7 5V supply for PLL chip. A/s 8 I2C Bus Address selection input(Do not connect it to anywhere) T/M 9 Tuning voltage monitor(Do not connect it to anywhere) TUNING(+30V) 10 PLL Channel select voltage supply (+30V) B4 11 5V supply for AGC pull-up. NRES 12 Reset, active at low level AUX_CLK 13 Programmable Output Port or Programmable Output Clock F22/DiSEqC 14 DiSEqC modulation (22 kHz Tone), SCL SDA 15 17 I2C Bus N.C 16 Do not connect it to anywhere BCLK OUT 18 Output Byte Clock; or Bit Clock in Serial Mode. N.C 19 Do not connect it to anywhere DO, ... , D7 20 ~ 27 Output Data; D7 is DATA_OUT in Serial Mode. N.C 28 Do not connect it to anywhere D/P 29 Data/Parity Signal. ERROR 30 Output Error Signal. Set in case of uncorrectable packet. STR OUT 31 Output 1st byte Signal (synchro byte clock) VDD 32 +3.3V Supply for LINK IC 10. Changes to this document. 18 Sep 2003. Circuit description. Added other packets. Fixed read from asic 15 Sep 2003. The verify byte means the tuner has locked. There are more commands, yet to be decoded. 10 Sep 2003. Got correct Fusion 878a document! I2C more correctly described. DMA is from audio. 9 Sep 2003. DMA loop corrected. New / old terminolgy wrong, should be fta / ci. 8 Sep 2003. Tidied, added I2c details and DMA details. Fixes to symbol rate for ci, more sensible LNB value.