initial commit from dddvb-0.9.19c

This commit is contained in:
mvoelkel 2015-08-05 17:22:42 +02:00
commit 9e2128c4fb
121 changed files with 90381 additions and 0 deletions

189
CHANGELOG Normal file
View File

@ -0,0 +1,189 @@
0.9.19c 2015.07.20
- MAX S8:
do not turn on diseqc and tuners on init
of to save power
turn off tuners when not used
- support new Octopus CI in flashprog
0.9.19b 2015.06.15
- fix version number
- option "old_quattro=1" for old MAX S8 input numbering
new is "VL VH HL HH", old is "VL HL VH HH"
- set drive strength in mxl5xx to 1 to fix problems with
8th demod
0.9.19 2015.06.14
- lock flash access
- support serial numbers for newer cards
0.9.18 2015.05.05
- support GT links
- fixes for mxl5xx tuning
(prevent simultaneous tuning inside 100ms)
- allow dynamic fmode change
0.9.18 (beta) 2015.01.24
- initial support of GT links
- fixes for mxl5xx tuning
0.9.17 2015.01.10
- support input modes for MAX S8 4/8
ddbridge parameter fmode:
fmode = 0 : demod 0 & 4 on input 0, demod 1 & 5 on input 1, etc.
input for each frontend can be changed with ioctl DTV_INPUT
fmode = 1 : connect all lines to QUAD LNB
fmode = 2 : connect to QUATTRO LNB: input 0=V,L, 1=H,L, 2=V,H, 3=H,H
fmode = 3 : all demods on input 0
send JESS or SCR commands from application
- preparations for support of GT links
0.9.16 2014.12.19
- support MAX S8 4/8 production card
0.9.15a 2014.07.29
- last minute fixes
0.9.15 2014.06.24
- support MAX S8 4/8 prototype
0.9.14b 2014.04.24
- fix fe read lockup in cxd2843
0.9.14a 2014.04.23
- fix Cine S2 V7 PCIe ID
0.9.14 2014.04.20
- support for CineCT V7 with C2
- initial support for STV0910/STV6111/LNBH25
- more coding style cleanups
- API changes for modulator
0.9.13 2014.03.25
- support for CineCT V7
0.9.12 2014.02.17
- support for SNR in XO2 and LED connected to XO2
0.9.11 2014.02.04
- kernel style cleanups
- attr alloc fixes for modulator card
0.9.10 2013.10.09
- Bugfixes CXD2843
support slice id
0.9.9 2013.08.14
- support for CXD2843 DVB-C/T/C2/T2 demod
0.9.7 2013.04.15
- Octopus Net complete
- changes for 3.8 kernels
0.9.6 2012.09.26
- basic Octopus Net support
0.9.5 2012.08.05
- cleanup
0.9.4 2012.07.11
- support for new modulator bitstream 1.1
0.9.3 2012.06.13
- add hwid, remap attributes
0.9.2 2012.06.08
- fix cxd2099 address writing optmization
- add setting of TS output gap size through sysfs
gap_size = (gap_value*2)+4
bit rate = 72 Mbps * 188 / gap_size
0.9.1 2012.05.01
- support for reworked DVB-C modulator
- support for multiple channels
- move some funktions from tasklets back into
interrupt in those cases where it is more efficient
0.9.0 2012.03.05
- initial support of DVB-C modulator card
- rework of redirect mechanism to support modulator
0.8.5 2012.01.30
- init DMA_BUFFER_CONTROL before starting input/output
in case it was not stopped properly before reboot
(can only happen on cards on PCIe extensions without reset line)
0.8.4 2012.01.04
- support for reading bridge serial number
- test code for proper start/stop of redirected streams
0.8.3 2011.12.18
- add support for EEProms on 0x50
- make flashprog safer to use for end users
- lost of kernel coding style adjustments
0.8.2 2011.10.14
- added some documentation in docs/
0.8.1 2011.10.13
- signal strength and SNR for STV0367/TDA18212 combo
- serial number support via sysfs
0.8 2011.07.30
- Support for DVB-C/T cards with stv0367 demod and TDA18212 tuner
- loopback TS for testing
- support of octopus cards with fan, led and temperature sensors
via attributes.
- redirect of TS to CI and back
0.7 2011.06.14
- Add IDs for new cards in ddbridge driver
- Change dvb adapter allocation for ddbridge driver
Configurable with module parameter adapter_alloc:
0 = one adapter per io (old behavior)
1 = one per tab with io present (tab connected to something)
2 = one per tab regardless of something connected or not
3 = one adapter for all devices of one card

7
Kbuild Normal file
View File

@ -0,0 +1,7 @@
#
# Makefile for the kernel multimedia device drivers.
#
obj-y := dvb-core/ \
ddbridge/ \
frontends/

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules
$(MAKE) -C apps
dep:
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
install: all
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
clean:
rm -rf */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*

19
apps/Makefile Normal file
View File

@ -0,0 +1,19 @@
all: cit citin flashprog modt ddtest setmod ddflash
cit: cit.c
gcc -o cit cit.c -lpthread
modt: modt.c
gcc -o modt modt.c -lpthread
setmod: setmod.c
gcc -o setmod setmod.c -I../include/
flashprog: flashprog.c
gcc -o flashprog flashprog.c
ddtest: ddtest.c
gcc -o ddtest ddtest.c
ddflash: ddflash.c
gcc -o ddflash ddflash.c

138
apps/cit.c Normal file
View File

@ -0,0 +1,138 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
void proc_buf(uint8_t *buf, uint32_t *d)
{
uint32_t c;
static uint32_t tc=0;
if (buf[1]==0x1f && buf[2]==0xff) {
//printf("fill\n");
return;
}
if (buf[1]==0x9f && buf[2]==0xff) {
//printf("fill\n");
return;
}
if (buf[1]==0x1a && buf[2]==0xbb) {
tc++;
if (!(tc&0xfff))
printf("T %d\n", tc);
return;
}
//printf("%02x %02x %02x %02x\n", buf[0], buf[1], buf [2], buf[3]);
if (buf[1]!=0x0a || buf[2]!=0xaa)
return;
c=(buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
if (c!=*d) {
printf("CONT ERROR: got %08x expected %08x\n", c, *d);
*d=c;
} else {
if (memcmp(ts+8, buf+8, 180))
printf("error\n");
if (!(c&0xffff))
printf("R %08x\n", c);
}
(*d)++;
}
void *get_ts(void *a)
{
uint8_t buf[188*1024];
int len, off;
int fdi=open("/dev/dvb/adapter2/ci0", O_RDONLY);
uint32_t d=0;
while (1) {
len=read(fdi, buf, 188*1024);
if (len<0)
continue;
if (buf[0]!=0x47) {
read(fdi, buf, 1);
continue;
}
for (off=0; off<len; off+=188) {
proc_buf(buf+off, &d);
}
}
}
#define SNUM 233
//671
void send(void)
{
uint8_t buf[188*SNUM], *cts;
int i;
uint32_t c=0;
int fdo;
fdo=open("/dev/dvb/adapter2/ci0", O_WRONLY);
while (1) {
for (i=0; i<SNUM; i++) {
cts=buf+i*188;
memcpy(cts, ts, 188);
cts[4]=(c>>24);
cts[5]=(c>>16);
cts[6]=(c>>8);
cts[7]=c;
//write(fdo, fill, 188);
//printf("S %d\n", c);
c++;
//usleep(100000+0xffff&rand());
//usleep(1000);
}
write(fdo, buf, 188*SNUM);
}
}
int main()
{
pthread_t th;
memset(ts+8, 180, 0x5a);
pthread_create(&th, NULL, get_ts, NULL);
usleep(10000);
send();
}

61
apps/citin.c Normal file
View File

@ -0,0 +1,61 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
void proc_ts(int i, uint8_t *buf)
{
uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
if (buf[3]&0xc0) /* only descrambled packets */
return;
/* only ORF */
if (pid==160 || pid==161 || pid==1001||pid==13001 || pid==0)
write(1, buf, 188);
}
#define TSBUFSIZE (100*188)
void citest()
{
uint8_t *buf;
uint8_t id;
int i, nts;
int len;
int ts=open("/dev/dvb/adapter4/ci0", O_RDONLY);
buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) {
len=read(ts, buf, TSBUFSIZE);
if (len<0) {
continue;
}
if (buf[0]!=0x47) {
read(ts, buf, 1);
continue;
}
if (len%188) { /* should not happen */
printf("blah\n");
continue;
}
nts=len/188;
for (i=0; i<nts; i++)
proc_ts(i, buf+i*188);
}
}
int main()
{
citest();
}

55
apps/citout.c Normal file
View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
#define TSBUFSIZE (100*188)
void citest()
{
uint8_t *buf;
uint8_t id;
int i, nts;
int len;
int ts0=open("/dev/dvb/adapter0/dvr0", O_RDONLY);
int ts1=open("/dev/dvb/adapter4/sec0", O_WRONLY);
int demux0=open("/dev/dvb/adapter0/demux0", O_RDWR);
struct dmx_pes_filter_params pesFilterParams;
pesFilterParams.input = DMX_IN_FRONTEND;
pesFilterParams.output = DMX_OUT_TS_TAP;
pesFilterParams.pes_type = DMX_PES_OTHER;
pesFilterParams.flags = DMX_IMMEDIATE_START;
pesFilterParams.pid = 8192;
if (ioctl(demux0, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
printf("Could not set PES filter\n");
return;
}
buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) {
len=read(ts0, buf, TSBUFSIZE);
if (len<=0)
break;
if (buf[0]!=0x47)
printf("oops\n");
write(ts1, buf, len);
}
}
int main()
{
citest();
}

1
apps/ddflash.c Symbolic link
View File

@ -0,0 +1 @@
octonet/ddflash.c

1
apps/ddtest.c Symbolic link
View File

@ -0,0 +1 @@
octonet/ddtest.c

1
apps/flash.h Symbolic link
View File

@ -0,0 +1 @@
./octonet/flash.h

722
apps/flashprog.c Normal file
View File

@ -0,0 +1,722 @@
/*
/* flashprog - Programmer for flash on Digital Devices Octopus
*
* Copyright (C) 2010-2011 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#define DDB_MAGIC 'd'
static uint32_t linknr = 0;
struct ddb_id {
__u16 vendor;
__u16 device;
__u16 subvendor;
__u16 subdevice;
__u32 hw;
__u32 regmap;
};
struct ddb_flashio {
__u8 *write_buf;
__u32 write_len;
__u8 *read_buf;
__u32 read_len;
__u32 link;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
int flashio(int ddb, uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen)
{
struct ddb_flashio fio = {
.write_buf=wbuf,
.write_len=wlen,
.read_buf=rbuf,
.read_len=rlen,
.link=linknr,
};
return ioctl(ddb, IOCTL_DDB_FLASHIO, &fio);
}
enum {
UNKNOWN_FLASH = 0,
ATMEL_AT45DB642D = 1,
SSTI_SST25VF016B = 2,
SSTI_SST25VF032B = 3,
SSTI_SST25VF064C = 4,
SPANSION_S25FL116K = 5,
};
int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
{
uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff};
return flashio(ddb, cmd, 4, buf, len);
}
int flashdump(int ddb, uint32_t addr, uint32_t len)
{
int i, j;
uint8_t buf[32];
int bl = sizeof(buf);
for (j=0; j<len; j+=bl, addr+=bl) {
flashread(ddb, buf, addr, bl);
for (i=0; i<bl; i++) {
printf("%02x ", buf[i]);
}
printf("\n");
}
}
int FlashDetect(int dev)
{
uint8_t Cmd = 0x9F;
uint8_t Id[3];
int r = flashio(dev, &Cmd,1,Id,3);
if (r < 0)
return r;
if (Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x41 )
r = SSTI_SST25VF016B;
else if( Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x4A )
r = SSTI_SST25VF032B;
else if( Id[0] == 0x1F && Id[1] == 0x28 )
r = ATMEL_AT45DB642D;
else if( Id[0] == 0xBF && Id[1] == 0x25 && Id[2] == 0x4B )
r = SSTI_SST25VF064C;
else if( Id[0] == 0x01 && Id[1] == 0x40 && Id[2] == 0x15 )
r = SPANSION_S25FL116K;
else
r = UNKNOWN_FLASH;
switch(r) {
case UNKNOWN_FLASH:
printf("Unknown Flash Flash ID = %02x %02x %02x\n",Id[0],Id[1],Id[2]);
break;
case ATMEL_AT45DB642D:
printf("Flash: Atmel AT45DB642D 64 MBit\n");
break;
case SSTI_SST25VF016B:
printf("Flash: SSTI SST25VF016B 16 MBit\n");
break;
case SSTI_SST25VF032B:
printf("Flash: SSTI SST25VF032B 32 MBit\n"); break;
case SSTI_SST25VF064C:
printf("Flash: SSTI SST25VF064C 64 MBit\n"); break;
case SPANSION_S25FL116K:
printf("Flash: SPANSION S25FL116K 16 MBit\n"); break;
}
return r;
}
int FlashWriteAtmel(int dev,uint32_t FlashOffset, uint8_t *Buffer,int BufferSize)
{
int err = 0;
int BlockErase = BufferSize >= 8192;
int i;
if (BlockErase) {
for(i = 0; i < BufferSize; i += 8192 ) {
uint8_t Cmd[4];
if( (i & 0xFFFF) == 0 )
printf(" Erase %08x\n",FlashOffset + i);
Cmd[0] = 0x50; // Block Erase
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
Cmd[3] = 0x00;
err = flashio(dev,Cmd,4,NULL,0);
if( err < 0 ) break;
while( 1 )
{
Cmd[0] = 0xD7; // Read Status register
err = flashio(dev,Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x80) == 0x80 ) break;
}
}
}
for(i = 0; i < BufferSize; i += 1024 )
{
uint8_t Cmd[4 + 1024];
if( (i & 0xFFFF) == 0 )
{
printf(" Program %08x\n",FlashOffset + i);
}
Cmd[0] = 0x84; // Buffer 1
Cmd[1] = 0x00;
Cmd[2] = 0x00;
Cmd[3] = 0x00;
memcpy(&Cmd[4],&Buffer[i],1024);
err = flashio(dev,Cmd,4 + 1024,NULL,0);
if( err < 0 ) break;
Cmd[0] = BlockErase ? 0x88 : 0x83; // Buffer to Main Memory (with Erase)
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
Cmd[3] = 0x00;
err = flashio(dev,Cmd,4,NULL,0);
if( err < 0 ) break;
while( 1 )
{
Cmd[0] = 0xD7; // Read Status register
err = flashio(dev,Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x80) == 0x80 ) break;
}
if( err < 0 ) break;
}
return err;
}
int FlashWritePageMode(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize, uint8_t LockBits)
{
int err = 0, i, j;
uint8_t Cmd[260];
if( (BufferSize % 4096) != 0 )
return -1; // Must be multiple of sector size
do {
Cmd[0] = 0x50; // EWSR
err = flashio(dev, Cmd,1,NULL,0);
if( err < 0 ) break;
Cmd[0] = 0x01; // WRSR
Cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(dev, Cmd,2,NULL,0);
if( err < 0 ) break;
for(i = 0; i < BufferSize; i += 4096 ) {
if( (i & 0xFFFF) == 0 ) {
printf(" Erase %08x\n",FlashOffset + i);
}
Cmd[0] = 0x06; // WREN
err = flashio(dev, Cmd,1,NULL,0);
if( err < 0 ) break;
Cmd[0] = 0x20; // Sector erase ( 4Kb)
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
Cmd[3] = 0x00;
err = flashio(dev, Cmd,4,NULL,0);
if( err < 0 ) break;
while(1)
{
Cmd[0] = 0x05; // RDRS
err = flashio(dev, Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x01) == 0 ) break;
}
if( err < 0 ) break;
}
if( err < 0 ) break;
for (j = BufferSize - 256; j >= 0; j -= 256 )
{
if( (j & 0xFFFF) == 0 )
{
printf(" Programm %08x\n",FlashOffset + j);
}
Cmd[0] = 0x06; // WREN
err = flashio(dev, Cmd,1,NULL,0);
if( err < 0 ) break;
Cmd[0] = 0x02; // PP
Cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
Cmd[3] = 0x00;
memcpy(&Cmd[4],&Buffer[j],256);
err = flashio(dev, Cmd,260,NULL,0);
if( err < 0 ) break;
while(1)
{
Cmd[0] = 0x05; // RDRS
err = flashio(dev, Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x01) == 0 ) break;
}
if( err < 0 ) break;
}
if( err < 0 ) break;
Cmd[0] = 0x50; // EWSR
err = flashio(dev, Cmd,1,NULL,0);
if( err < 0 ) break;
Cmd[0] = 0x01; // WRSR
Cmd[1] = LockBits; // BPx = 0, Lock all blocks
err = flashio(dev, Cmd,2,NULL,0);
} while(0);
return err;
}
int FlashWriteSSTI_B(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize)
{
int err = 0;
uint8_t Cmd[6];
int i, j;
// Must be multiple of sector size
if( (BufferSize % 4096) != 0 )
return -1;
do {
Cmd[0] = 0x50; // EWSR
err = flashio(dev,Cmd,1,NULL,0);
if( err < 0 )
break;
Cmd[0] = 0x01; // WRSR
Cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(dev,Cmd,2,NULL,0);
if( err < 0 )
break;
for(i = 0; i < BufferSize; i += 4096 ) {
if( (i & 0xFFFF) == 0 )
printf(" Erase %08x\n",FlashOffset + i);
Cmd[0] = 0x06; // WREN
err = flashio(dev,Cmd,1,NULL,0);
if( err < 0 )
break;
Cmd[0] = 0x20; // Sector erase ( 4Kb)
Cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
Cmd[3] = 0x00;
err = flashio(dev,Cmd,4,NULL,0);
if( err < 0 )
break;
while(1) {
Cmd[0] = 0x05; // RDRS
err = flashio(dev,Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x01) == 0 ) break;
}
if( err < 0 ) break;
}
if( err < 0 )
break;
for(j = BufferSize - 4096; j >= 0; j -= 4096 ) {
if( (j & 0xFFFF) == 0 )
printf(" Program %08x\n",FlashOffset + j);
for(i = 0; i < 4096; i += 2 ) {
if( i == 0 ) {
Cmd[0] = 0x06; // WREN
err = flashio(dev,Cmd,1,NULL,0);
if( err < 0 )
break;
Cmd[0] = 0xAD; // AAI
Cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
Cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
Cmd[3] = 0x00;
Cmd[4] = Buffer[j+i];
Cmd[5] = Buffer[j+i+1];
err = flashio(dev,Cmd,6,NULL,0);
} else {
Cmd[0] = 0xAD; // AAI
Cmd[1] = Buffer[j+i];
Cmd[2] = Buffer[j+i+1];
err = flashio(dev,Cmd,3,NULL,0);
}
if( err < 0 )
break;
while(1) {
Cmd[0] = 0x05; // RDRS
err = flashio(dev,Cmd,1,&Cmd[0],1);
if( err < 0 ) break;
if( (Cmd[0] & 0x01) == 0 ) break;
}
if( err < 0 ) break;
}
if( err < 0 ) break;
Cmd[0] = 0x04; // WDIS
err = flashio(dev,Cmd,1,NULL,0);
if( err < 0 ) break;
}
if( err < 0 ) break;
Cmd[0] = 0x50; // EWSR
err = flashio(dev,Cmd,1,NULL,0);
if( err < 0 ) break;
Cmd[0] = 0x01; // WRSR
Cmd[1] = 0x1C; // BPx = 0, Lock all blocks
err = flashio(dev,Cmd,2,NULL,0);
} while(0);
return err;
}
void get_id(int ddb, struct ddb_id *ddbid) {
uint8_t id[4];
if (ioctl(ddb, IOCTL_DDB_ID, ddbid)>=0)
return;
memset(ddbid, 0, sizeof(*ddbid));
flashread(ddb, id, 0, 4);
printf("%02x %02x %02x %02x\n",
id[0], id[1], id[2], id[3]);
ddbid->subvendor=(id[0] << 8) | id[1];
ddbid->subdevice=(id[2] << 8) | id[3];
}
int sure()
{
char c;
printf("\n\nWARNING! Flashing a new FPGA image might make your card unusable!\n");
printf("\n\nWARNUNG! Das Flashen eines neuen FPGA-Images kann Ihre Karte unbrauchbar machen.\n");
printf("\n\nAre you sure? y/n?");
printf("\n\nSind Sie sicher? y/n?");
fflush(0);
c = getchar();
if (c!='y') {
printf("\nFlashing aborted.\n\n");
return -1;
}
printf("\nStarting to flash\n\n");
return 0;
}
int main(int argc, char **argv)
{
char ddbname[80];
int type = 0;
struct ddb_id ddbid;
uint8_t *buffer;
int BufferSize = 0;
int BlockErase = 0;
uint32_t FlashOffset = 0x10000;
int ddb;
int i, err;
int SectorSize=0;
int FlashSize=0;
int Flash;
uint32_t svid=0, jump=0, dump=0;
int bin;
int ddbnum = 0;
int force = 0;
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"svid", required_argument, NULL, 's'},
{"help", no_argument , NULL, 'h'},
{"force", no_argument , NULL, 'f'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"d:n:s:o:l:dfhj",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'd':
dump = strtoul(optarg, NULL, 16);
break;
case 's':
svid = strtoul(optarg, NULL, 16);
break;
case 'o':
FlashOffset = strtoul(optarg, NULL, 16);
break;
case 'n':
ddbnum = strtol(optarg, NULL, 0);
break;
case 'l':
linknr = strtol(optarg, NULL, 0);
break;
case 'f':
force = 1;
break;
case 'j':
jump = 1;
break;
case 'h':
default:
break;
}
}
if (optind<argc) {
printf("Warning: unused arguments\n");
}
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
ddb=open(ddbname, O_RDWR);
if (ddb < 0) {
printf("Could not open device\n");
return -1;
}
Flash=FlashDetect(ddb);
switch(Flash) {
case ATMEL_AT45DB642D:
SectorSize = 1024;
FlashSize = 0x800000;
break;
case SSTI_SST25VF016B:
SectorSize = 4096;
FlashSize = 0x200000;
break;
case SSTI_SST25VF032B:
SectorSize = 4096;
FlashSize = 0x400000;
break;
case SSTI_SST25VF064C:
SectorSize = 4096;
FlashSize = 0x800000;
break;
case SPANSION_S25FL116K:
SectorSize = 4096;
FlashSize = 0x200000;
break;
default:
return 0;
}
get_id(ddb, &ddbid);
#if 1
printf("%04x %04x %04x %04x %08x %08x\n",
ddbid.vendor, ddbid.device,
ddbid.subvendor, ddbid.subdevice,
ddbid.hw, ddbid.regmap);
#endif
if (dump) {
flashdump(ddb, dump, 128);
return 0;
}
if (ddbid.device == 0x0011)
type = 1;
if (ddbid.device == 0x0201)
type = 2;
if (ddbid.device == 0x02)
type = 3;
if (ddbid.device == 0x03)
type = 0;
if (ddbid.device == 0x07)
type = 4;
if (ddbid.device == 0x320)
type = 5;
if (ddbid.device == 0x13)
type = 6;
if (ddbid.device == 0x12)
type = 7;
if (!SectorSize)
return 0;
if (jump) {
uint32_t Jump = 0x200000;
BufferSize = SectorSize;
FlashOffset = FlashSize - SectorSize;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
memset(&buffer[BufferSize - 256 + 0x10], 0x00, 16);
buffer[BufferSize - 256 + 0x10] = 0xbd;
buffer[BufferSize - 256 + 0x11] = 0xb3;
buffer[BufferSize - 256 + 0x12] = 0xc4;
buffer[BufferSize - 256 + 0x1a] = 0xfe;
buffer[BufferSize - 256 + 0x1e] = 0x03;
buffer[BufferSize - 256 + 0x1f] = ( ( Jump >> 16 ) & 0xFF );
buffer[BufferSize - 256 + 0x20] = ( ( Jump >> 8 ) & 0xFF );
buffer[BufferSize - 256 + 0x21] = ( ( Jump ) & 0xFF );
} else if (svid) {
BufferSize = SectorSize;
FlashOffset = 0;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer,0xFF,BufferSize);
buffer[0] = ((svid >> 24 ) & 0xFF);
buffer[1] = ((svid >> 16 ) & 0xFF);
buffer[2] = ((svid >> 8 ) & 0xFF);
buffer[3] = ((svid ) & 0xFF);
} else {
int fh, i;
int fsize;
char *fname;
switch (type) {
case 0:
fname="DVBBridgeV1B_DVBBridgeV1B.bit";
printf("Octopus\n");
break;
case 1:
fname="CIBridgeV1B_CIBridgeV1B.bit";
printf("Octopus CI\n");
break;
case 2:
fname="DVBModulatorV1B_DVBModulatorV1B.bit";
printf("Modulator\n");
break;
case 3:
fname="DVBBridgeV1A_DVBBridgeV1A.bit";
printf("Octopus 35\n");
break;
case 4:
fname="DVBBridgeV2A_DD01_0007_MXL.bit";
printf("Octopus 4/8\n");
break;
case 6:
fname="DVBBridgeV2B_DD01_0013_PRO.fpga";
printf("Octopus PRO\n");
break;
case 7:
fname="DVBBridgeV2B_DD01_0012_STD.fpga";
printf("Octopus CI\n");
break;
default:
printf("UNKNOWN\n");
break;
}
fh = open(fname, O_RDONLY);
if (fh < 0 ) {
printf("File not found \n");
return 0;
}
printf("Using bitstream %s\n", fname);
fsize = lseek(fh,0,SEEK_END);
if( fsize > 4000000 || fsize < SectorSize )
{
close(fh);
printf("Invalid File Size \n");
return 0;
}
if( Flash == ATMEL_AT45DB642D ) {
BlockErase = fsize >= 8192;
if( BlockErase )
BufferSize = (fsize + 8191) & ~8191;
else
BufferSize = (fsize + 1023) & ~1023;
} else {
BufferSize = (fsize + SectorSize - 1 ) & ~(SectorSize - 1);
}
printf(" Size %08x, target %08x\n", BufferSize, FlashOffset);
buffer = malloc(BufferSize);
if( buffer == NULL ) {
close(fh);
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
lseek(fh, 0, SEEK_SET);
read(fh, buffer, fsize);
close(fh);
if (BufferSize >= 0x10000) {
for(i = 0; i < 0x200; i += 1 ) {
if ( *(uint16_t *) (&buffer[i]) == 0xFFFF )
break;
buffer[i] = 0xFF;
}
}
}
if (!force && sure()<0)
return 0;
switch(Flash) {
case ATMEL_AT45DB642D:
err = FlashWriteAtmel(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF016B:
case SSTI_SST25VF032B:
err = FlashWriteSSTI_B(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF064C:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x3C);
break;
case SPANSION_S25FL116K:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
break;
}
if (err < 0)
printf("Programming Error\n");
else
printf("Programming Done\n");
free(buffer);
return 0;
}

36
apps/modt.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#define SNUM 1000
//671
void send(void)
{
uint8_t buf[188*SNUM], *cts;
int i;
uint32_t c=0;
int fdo;
fdo=open("/dev/dvb/adapter0/mod0", O_WRONLY);
while (1) {
read(0, buf, sizeof(buf));
write(fdo, buf, 188*SNUM);
}
}
int main()
{
send();
}

19
apps/octonet/Makefile Normal file
View File

@ -0,0 +1,19 @@
all: ddtest octonet octokey ddflash
install: all
install -m 0755 ddtest $(DESTDIR)/usr/bin
install -m 0755 octonet $(DESTDIR)/usr/bin
install -m 0755 octokey $(DESTDIR)/usr/bin
install -m 0755 ddflash $(DESTDIR)/usr/bin
ddflash: ddflash.c
$(CC) -o ddflash ddflash.c
ddtest: ddtest.c
$(CC) -o ddtest ddtest.c
octonet: octonet.c
$(CC) -o octonet octonet.c
octokey: octokey.c
$(CC) -o octokey octokey.c

791
apps/octonet/ddflash.c Normal file
View File

@ -0,0 +1,791 @@
/*
/* ddflash - Programmer for flash on Digital Devices devices
*
* Copyright (C) 2013 Digital Devices GmbH
* Ralph Metzler <rmetzler@digitaldevices.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include "flash.h"
static int reboot(uint32_t off)
{
FILE *f;
uint32_t time;
if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL)
return -1;
fscanf(f, "%u", &time);
fclose(f);
if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL)
return -1;
fprintf(f, "%u", time + off);
fclose(f);
system("/sbin/poweroff");
return 0;
}
struct ddflash {
int fd;
struct ddb_id id;
uint32_t type;
uint32_t version;
uint32_t sector_size;
uint32_t size;
uint32_t bufsize;
uint32_t block_erase;
uint8_t * buffer;
};
int flashio(int ddb, uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen)
{
struct ddb_flashio fio = {
.write_buf=wbuf,
.write_len=wlen,
.read_buf=rbuf,
.read_len=rlen,
.link=0,
};
return ioctl(ddb, IOCTL_DDB_FLASHIO, &fio);
}
enum {
UNKNOWN_FLASH = 0,
ATMEL_AT45DB642D = 1,
SSTI_SST25VF016B = 2,
SSTI_SST25VF032B = 3,
};
static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
{
uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff};
return flashio(ddb, cmd, 4, buf, len);
}
static int flashdump(struct ddflash *ddf, uint32_t addr, uint32_t len)
{
int i, j;
uint8_t buf[32];
int bl = sizeof(buf);
for (j = 0; j < len; j += bl, addr += bl) {
flashread(ddf->fd, buf, addr, bl);
for (i = 0; i < bl; i++) {
printf("%02x ", buf[i]);
}
printf("\n");
}
}
void dump(const uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf(" | ");
for (i = 0; i < 16; i++)
if (i + j < l)
putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.');
printf("\n");
}
}
static int flashwrite_SSTI(struct ddflash *ddf, int fs, uint32_t FlashOffset, uint32_t maxlen, uint32_t fw_off)
{
int err = 0;
uint8_t cmd[6];
int i, j;
uint32_t flen, blen;
blen = flen = lseek(fs, 0, SEEK_END) - fw_off;
if (blen % 0xfff)
blen = (blen + 0xfff) & 0xfffff000;
printf("blen = %u, flen = %u\n", blen, flen);
do {
#if 1
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(ddf->fd, cmd, 2, NULL, 0);
if (err < 0 )
break;
for (i = 0; i < flen; i += 4096) {
if ((i & 0xFFFF) == 0 )
printf("Erase %08x\n", FlashOffset + i);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0 )
break;
cmd[0] = 0x20; // Sector erase ( 4Kb)
cmd[1] = (((FlashOffset + i ) >> 16) & 0xFF);
cmd[2] = (((FlashOffset + i ) >> 8) & 0xFF);
cmd[3] = 0x00;
err = flashio(ddf->fd,cmd,4,NULL,0);
if (err < 0 )
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(ddf->fd,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x01) == 0 ) break;
}
if (err < 0 ) break;
}
if (err < 0 )
break;
#endif
for (j = blen - 4096; j >= 0; j -= 4096 ) {
uint32_t len = 4096;
ssize_t rlen;
if (lseek(fs, j + fw_off, SEEK_SET) < 0) {
printf("seek error\n");
return -1;
}
if (flen - j < 4096) {
len = flen - j;
memset(ddf->buffer, 0xff, 4096);
}
rlen = read(fs, ddf->buffer, len);
if (rlen < 0 || rlen != len) {
printf("file read error %d,%d at %u\n", rlen, errno, j);
return -1;
}
printf ("write %u bytes at %08x\n", len, j);
if ((j & 0xFFFF) == 0 )
printf(" Program %08x\n",FlashOffset + j);
#if 1
for (i = 0; i < 4096; i += 2) {
if (i == 0) {
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0 )
break;
cmd[0] = 0xAD; // AAI
cmd[1] = ((( FlashOffset + j ) >> 16) & 0xFF );
cmd[2] = ((( FlashOffset + j ) >> 8) & 0xFF );
cmd[3] = 0x00;
cmd[4] = ddf->buffer[i];
cmd[5] = ddf->buffer[i + 1];
err = flashio(ddf->fd,cmd,6,NULL,0);
} else {
cmd[0] = 0xAD; // AAI
cmd[1] = ddf->buffer[i];
cmd[2] = ddf->buffer[i + 1];
err = flashio(ddf->fd,cmd,3,NULL,0);
}
if (err < 0 )
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(ddf->fd,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x01) == 0 ) break;
}
if (err < 0 )
break;
}
if (err < 0)
break;
cmd[0] = 0x04; // WDIS
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0 )
break;
#endif
}
if (err < 0 ) break;
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd,cmd,1,NULL,0);
if (err < 0 ) break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x1C; // BPx = 0, Lock all blocks
err = flashio(ddf->fd,cmd,2,NULL,0);
} while(0);
return err;
}
static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
{
flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off);
}
static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
{
off_t off;
uint32_t len;
int i, j, rlen;
uint8_t buf[256], buf2[256];
int bl = sizeof(buf);
off = lseek(fs, 0, SEEK_END);
if (off < 0)
return -1;
len = off - fw_off;
lseek(fs, fw_off, SEEK_SET);
if (len > maxlen) {
printf("file too big\n");
return -1;
}
printf("flash file len %u, compare to %08x in flash\n", len, addr);
for (j = 0; j < len; j += bl, addr += bl) {
if (len - j < bl)
bl = len - j;
flashread(ddf->fd, buf, addr, bl);
rlen = read(fs, buf2, bl);
if (rlen < 0 || rlen != bl) {
printf("read error\n");
return -1;
}
if (memcmp(buf, buf2, bl)) {
printf("flash differs at %08x (offset %u)\n", addr, j);
dump(buf, 32);
dump(buf2, 32);
return addr;
}
}
printf("flash same as file\n");
return -2;
}
static int flash_detect(struct ddflash *ddf)
{
uint8_t cmd = 0x9F;
uint8_t id[3];
int r = flashio(ddf->fd, &cmd, 1, id, 3);
if (r < 0)
return r;
if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x41) {
r = SSTI_SST25VF016B;
//printf("Flash: SSTI SST25VF016B 16 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x200000;
} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4A) {
r = SSTI_SST25VF032B;
//printf("Flash: SSTI SST25VF032B 32 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x400000;
} else if (id[0] == 0x1F && id[1] == 0x28) {
r = ATMEL_AT45DB642D;
//printf("Flash: Atmel AT45DB642D 64 MBit\n");
ddf->sector_size = 1024;
ddf->size = 0x800000;
} else {
r = UNKNOWN_FLASH;
//printf("Unknown Flash Flash ID = %02x %02x %02x\n", id[0], id[1], id[2]);
}
if (ddf->sector_size) {
ddf->buffer = malloc(ddf->sector_size);
//printf("allocated buffer %08x@%08x\n", ddf->sector_size, (uint32_t) ddf->buffer);
}
return r;
}
int FlashWriteAtmel(int dev,uint32_t FlashOffset, uint8_t *Buffer,int BufferSize)
{
int err = 0;
int BlockErase = BufferSize >= 8192;
int i;
if (BlockErase) {
for (i = 0; i < BufferSize; i += 8192 ) {
uint8_t cmd[4];
if ((i & 0xFFFF) == 0 )
printf(" Erase %08x\n",FlashOffset + i);
cmd[0] = 0x50; // Block Erase
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
err = flashio(dev,cmd,4,NULL,0);
if (err < 0 ) break;
while( 1 )
{
cmd[0] = 0xD7; // Read Status register
err = flashio(dev,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x80) == 0x80 ) break;
}
}
}
for (i = 0; i < BufferSize; i += 1024) {
uint8_t cmd[4 + 1024];
if ((i & 0xFFFF) == 0 )
{
printf(" Program %08x\n",FlashOffset + i);
}
cmd[0] = 0x84; // Buffer 1
cmd[1] = 0x00;
cmd[2] = 0x00;
cmd[3] = 0x00;
memcpy(&cmd[4],&Buffer[i],1024);
err = flashio(dev,cmd,4 + 1024,NULL,0);
if (err < 0 ) break;
cmd[0] = BlockErase ? 0x88 : 0x83; // Buffer to Main Memory (with Erase)
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
err = flashio(dev,cmd,4,NULL,0);
if (err < 0 ) break;
while( 1 )
{
cmd[0] = 0xD7; // Read Status register
err = flashio(dev,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x80) == 0x80 ) break;
}
if (err < 0 ) break;
}
return err;
}
int FlashWriteSSTI(int dev, uint32_t FlashOffset, uint8_t *Buffer, int BufferSize)
{
int err = 0;
uint8_t cmd[6];
int i, j;
// Must be multiple of sector size
if ((BufferSize % 4096) != 0 )
return -1;
do {
cmd[0] = 0x50; // EWSR
err = flashio(dev,cmd,1,NULL,0);
if (err < 0 )
break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(dev,cmd,2,NULL,0);
if (err < 0 )
break;
for (i = 0; i < BufferSize; i += 4096 ) {
if ((i & 0xFFFF) == 0 )
printf(" Erase %08x\n",FlashOffset + i);
cmd[0] = 0x06; // WREN
err = flashio(dev,cmd,1,NULL,0);
if (err < 0 )
break;
cmd[0] = 0x20; // Sector erase ( 4Kb)
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
err = flashio(dev,cmd,4,NULL,0);
if (err < 0 )
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(dev,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x01) == 0 ) break;
}
if (err < 0 ) break;
}
if (err < 0 )
break;
for (j = BufferSize - 4096; j >= 0; j -= 4096 ) {
if ((j & 0xFFFF) == 0 )
printf(" Program %08x\n",FlashOffset + j);
for (i = 0; i < 4096; i += 2 ) {
if (i == 0 ) {
cmd[0] = 0x06; // WREN
err = flashio(dev,cmd,1,NULL,0);
if (err < 0 )
break;
cmd[0] = 0xAD; // AAI
cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
cmd[3] = 0x00;
cmd[4] = Buffer[j+i];
cmd[5] = Buffer[j+i+1];
err = flashio(dev,cmd,6,NULL,0);
} else {
cmd[0] = 0xAD; // AAI
cmd[1] = Buffer[j+i];
cmd[2] = Buffer[j+i+1];
err = flashio(dev,cmd,3,NULL,0);
}
if (err < 0 )
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(dev,cmd,1,&cmd[0],1);
if (err < 0 ) break;
if ((cmd[0] & 0x01) == 0 ) break;
}
if (err < 0 ) break;
}
if (err < 0 ) break;
cmd[0] = 0x04; // WDIS
err = flashio(dev,cmd,1,NULL,0);
if (err < 0 ) break;
}
if (err < 0 ) break;
cmd[0] = 0x50; // EWSR
err = flashio(dev,cmd,1,NULL,0);
if (err < 0 ) break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x1C; // BPx = 0, Lock all blocks
err = flashio(dev,cmd,2,NULL,0);
} while(0);
return err;
}
static int get_id(struct ddflash *ddf) {
uint8_t id[4];
if (ioctl(ddf->fd, IOCTL_DDB_ID, &ddf->id) < 0)
return -1;
#if 1
printf("%04x %04x %04x %04x %08x %08x\n",
ddf->id.vendor, ddf->id.device,
ddf->id.subvendor, ddf->id.subdevice,
ddf->id.hw, ddf->id.regmap);
#endif
if (ddf->id.device == 0x0011)
ddf->type = 1;
if (ddf->id.device == 0x0201)
ddf->type = 2;
if (ddf->id.device == 0x02)
ddf->type = 3;
if (ddf->id.device == 0x03)
ddf->type = 0;
if (ddf->id.device == 0x0300)
ddf->type = 4;
if (ddf->id.device == 0x0320)
ddf->type = 5;
return 0;
}
static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
{
int fd, fsize, ret = 0;
off_t off;
uint32_t p, i;
uint8_t *buf;
uint8_t hdr[256];
unsigned int devid, version, length;
unsigned int cid[8];
int cids = 0;
uint32_t maxlen = 1024 * 1024;
fd = open(fn, O_RDONLY);
if (fd < 0) {
printf("%s: not found\n", fn);
return -1;
}
off = lseek(fd, 0, SEEK_END);
if (off < 0)
return -1;
fsize = off;
if (fsize > maxlen) {
close(fd);
return -1;
}
lseek(fd, 0, SEEK_SET);
buf = malloc(fsize);
if (!buf)
return -1;
read(fd, buf, fsize);
close(fd);
for (p = 0; p < fsize && buf[p]; p++) {
char *key = &buf[p], *val = NULL;
for (; p < fsize && buf[p] != 0x0a; p++) {
if (buf[p] == ':') {
buf[p] = 0;
val = &buf[p + 1];
}
}
if (val == NULL || p == fsize)
break;
buf[p] = 0;
//printf("%-20s:%s\n", key, val);
if (!strcasecmp(key, "Devid")) {
sscanf(val, "%x", &devid);
} else if (!strcasecmp(key, "Compat")) {
cids = sscanf(val, "%x,%x,%x,%x,%x,%x,%x,%x",
&cid[0], &cid[1], &cid[2], &cid[3],
&cid[4], &cid[5], &cid[6], &cid[7]);
if (cids < 1)
break;
for (i = 0; i < cids; i++)
if (cid[i] == ddf->id.device)
break;
if (i == cids) {
printf("%s: no compatible id\n", fn);
ret = -2; /* no compatible ID */
goto out;
}
} else if (!strcasecmp(key, "Version")) {
sscanf(val, "%x", &version);
} else if (!strcasecmp(key, "Length")) {
sscanf(val, "%u", &length);
}
}
p++;
*fw_off = p;
printf("devid = %04x\n", devid);
printf("version = %08x %08x\n", version, ddf->id.hw);
printf("length = %u\n", length);
printf("fsize = %u, p = %u, f-p = %u\n", fsize, p, fsize - p);
if (devid == ddf->id.device) {
if (version <= (ddf->id.hw & 0xffffff)) {
printf("%s: old version\n", fn);
ret = -3; /* same id but no newer version */
}
} else
ret = 1;
out:
free(buf);
printf("check_fw = %d\n", ret);
return ret;
}
static int update_image(struct ddflash *ddf, char *fn,
uint32_t adr, uint32_t len,
int has_header, int no_change)
{
int fs, res = 0;
uint32_t fw_off = 0;
printf("Check %s\n", fn);
if (has_header) {
int ck;
ck = check_fw(ddf, fn, &fw_off);
if (ck < 0)
return ck;
if (ck == 1 && no_change)
return 0;
}
fs = open(fn, O_RDONLY);
if (fs < 0 ) {
printf("File %s not found \n", fn);
return -1;
}
res = flashcmp(ddf, fs, adr, len, fw_off);
if (res == -2) {
printf("%s: same as flash\n", fn);
}
if (res < 0)
goto out;
res = flashwrite(ddf, fs, adr, len, fw_off);
if (res == 0)
res = 1;
out:
close(fs);
return res;
}
static int fexists(char *fn)
{
struct stat b;
return (!stat(fn, &b));
}
static int update_flash(struct ddflash *ddf)
{
char *fname;
int res, stat = 0;
switch (ddf->id.device) {
case 0x300:
case 0x301:
case 0x302:
case 0x307:
if ((res = update_image(ddf, "/boot/bs.img", 0x4000, 0x1000, 0, 0)) == 1)
stat |= 4;
if ((res = update_image(ddf, "/boot/uboot.img", 0xb0000, 0xb0000, 0, 0)) == 1)
stat |= 2;
if (fexists("/config/gtl.enabled")) {
if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
stat |= 1;
if (res == -1)
if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
stat |= 1;
} else if (fexists("/config/gtl.disabled")) {
if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
stat |= 1;
if (res == -1)
if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
stat |= 1;
} else {
if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
stat |= 1;
if (res == -1)
if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
stat |= 1;
if (res == -1)
if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
stat |= 1;
if (res == -1)
if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
stat |= 1;
}
break;
case 0x320:
//fname="/boot/DVBNetV1A_DD01_0300.bit";
fname="/boot/fpga.img";
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
stat |= 1;
return stat;
break;
default:
return 0;
}
return stat;
}
int main(int argc, char **argv)
{
struct ddflash ddf;
char ddbname[80];
uint8_t *buffer = 0;
uint32_t FlashOffset = 0x10000;
int i, err, res;
int ddbnum = 0;
uint32_t svid, jump, flash;
memset(&ddf, 0, sizeof(ddf));
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"svid", required_argument, NULL, 's'},
{"help", no_argument , NULL, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"d:n:s:o:l:dfhj",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 's':
svid = strtoul(optarg, NULL, 16);
break;
case 'o':
FlashOffset = strtoul(optarg, NULL, 16);
break;
case 'n':
ddbnum = strtol(optarg, NULL, 0);
break;
case 'j':
jump = 1;
break;
case 'h':
default:
break;
}
}
if (optind < argc) {
printf("Warning: unused arguments\n");
}
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
while ((ddf.fd = open(ddbname, O_RDWR)) < 0) {
if (errno == EBUSY)
usleep(100000);
else {
printf("Could not open device\n");
return -1;
}
}
flash = flash_detect(&ddf);
get_id(&ddf);
res = update_flash(&ddf);
if (ddf.buffer)
free(ddf.buffer);
if (res < 0)
return res;
if (res & 1)
reboot(40);
return res;
}

1528
apps/octonet/ddtest.c Normal file

File diff suppressed because it is too large Load Diff

63
apps/octonet/flash.h Normal file
View File

@ -0,0 +1,63 @@
#define DDB_MAGIC 'd'
struct ddb_flashio {
__u8 *write_buf;
__u32 write_len;
__u8 *read_buf;
__u32 read_len;
__u32 link;
};
struct ddb_gpio {
__u32 mask;
__u32 data;
};
struct ddb_id {
__u16 vendor;
__u16 device;
__u16 subvendor;
__u16 subdevice;
__u32 hw;
__u32 regmap;
};
struct ddb_reg {
__u32 reg;
__u32 val;
};
struct ddb_mem {
__u32 off;
__u8 *buf;
__u32 len;
};
struct ddb_mdio {
__u8 adr;
__u8 reg;
__u16 val;
};
struct ddb_i2c_msg {
__u8 bus;
__u8 adr;
__u8 *hdr;
__u32 hlen;
__u8 *msg;
__u32 mlen;
};
#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id)
#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)

68
apps/octonet/ns.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef _UAPI_DVBNS_H_
#define _UAPI_DVBNS_H_
#include <linux/types.h>
struct dvb_ns_params {
__u8 smac[6];
__u8 dmac[6];
__u8 sip[16];
__u8 dip[16];
__u16 sport;
__u16 dport;
__u16 sport2;
__u16 dport2;
__u8 ssrc[8];
__u8 flags;
__u8 qos;
__u16 vlan;
__u8 ttl;
};
#define DVB_NS_IPV6 1
#define DVB_NS_RTP 2
#define DVB_NS_RTCP 4
#define DVB_NS_RTP_TO 8
struct dvb_ns_rtcp {
__u8 *msg;
__u16 len;
};
struct dvb_ns_packet {
__u8 *buf;
__u8 count;
};
struct dvb_nsd_ts {
__u16 pid;
__u16 num;
__u16 input;
__u16 timeout;
__u16 len;
__u8 *ts;
__u8 mode;
__u8 table;
__u8 filter_mask;
__u8 section;
__u16 section_id;
};
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
#define NS_START _IO('o', 193)
#define NS_STOP _IO('o', 194)
#define NS_SET_PID _IOW('o', 195, __u16)
#define NS_SET_PIDS _IOW('o', 196, __u8 *)
#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp)
#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts)
#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts)
#define NSD_CANCEL_GET_TS _IO('o', 200)
#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts)
#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet)
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
#define NS_SET_CI _IOW('o', 204, __u8)
#endif /*_UAPI_DVBNS_H_*/

37
apps/octonet/octokey.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
int fd, len;
struct input_event ev;
uint32_t time;
fd = open("/dev/input/event0", O_RDONLY);
if (fd < 0)
return -1;
while (1) {
if ((len = read(fd, &ev, sizeof(ev)) < sizeof(struct input_event)))
return -1;
printf("%u.%06u %u %u %u\n", ev.time.tv_sec, ev.time.tv_usec, ev.type, ev.code, ev.value);
}
}

83
apps/octonet/octonet.c Normal file
View File

@ -0,0 +1,83 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include "ns.h"
struct dvb_ns_params nsp = {
.dmac = { 0x00, 0x01, 0x2e, 0x3a, 0x66,0xfc },
.smac = { 0x00, 0x12, 0x34, 0x56, 0x78,0x90 },
.sip = { 192, 168, 2, 80 },
.dip = { 192, 168, 2, 58 },
.sport = 1234,
.dport = 6670,
.ssrc = { 0x91, 0x82, 0x73, 0x64 },
};
static int set(int fd)
{
uint16_t pid = 0xa000;
ioctl(fd, NS_SET_NET, &nsp);
ioctl(fd, NS_START);
ioctl(fd, NS_SET_PID, &pid);
while(1);
ioctl(fd, NS_STOP);
return 0;
}
int main(int argc, char **argv)
{
int ddbnum;
int force;
int ddb;
char ddbname[80];
while (1) {
int oi = 0;
int c;
static struct option lopts[] = {
{"help", no_argument , NULL, 'h'},
{"force", no_argument , NULL, 'f'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"n:l:fh",
lopts, &oi);
if (c == -1)
break;
switch (c) {
case 'm':
break;
case 'n':
ddbnum = strtol(optarg, NULL, 0);
break;
case 'f':
force = 1;
break;
case 'h':
default:
break;
}
}
if (optind < argc) {
printf("Warning: unused arguments\n");
}
sprintf(ddbname, "/dev/dvb/adapter0/ns%d", ddbnum);
ddb=open(ddbname, O_RDWR);
if (ddb < 0) {
printf("Could not open device\n");
return -1;
}
}

33
apps/setmod.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/dvb/mod.h>
int main()
{
int fd;
struct dvb_mod_params mp;
struct dvb_mod_channel_params mc;
fd = open("/dev/dvb/adapter1/mod0", O_RDONLY);
mp.base_frequency = 722000000;
mp.attenuator = 0;
ioctl(fd, DVB_MOD_SET, &mp);
mc.modulation = QAM_256;
mc.input_bitrate = 40000000ULL << 32;
mc.pcr_correction = 0;
ioctl(fd, DVB_MOD_CHANNEL_SET, &mc);
close(fd);
}

8
ddbridge/Kbuild Normal file
View File

@ -0,0 +1,8 @@
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
EXTRA_CFLAGS += -Idrivers/media/common/tuners
NOSTDINC_FLAGS += -I$(SUBDIRS)/frontends -I$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core

19
ddbridge/Makefile Normal file
View File

@ -0,0 +1,19 @@
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
MODDEFS := CONFIG_DVB_DDBRIDGE=m
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules
$(MAKE) -C apps
dep:
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
install: all
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
clean:
rm -rf */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*

4641
ddbridge/ddbridge-core.c Normal file

File diff suppressed because it is too large Load Diff

275
ddbridge/ddbridge-i2c.c Normal file
View File

@ -0,0 +1,275 @@
/*
* ddbridge-i2c.c: Digital Devices bridge i2c driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
* Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
static int i2c_io(struct i2c_adapter *adapter, u8 adr,
u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = wbuf, .len = wlen },
{.addr = adr, .flags = I2C_M_RD,
.buf = rbuf, .len = rlen } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0,
.buf = data, .len = len};
return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
}
static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
{
struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
}
static int i2c_read_regs(struct i2c_adapter *adapter,
u8 adr, u8 reg, u8 *val, u8 len)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1 },
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = len } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static int i2c_read_regs16(struct i2c_adapter *adapter,
u8 adr, u16 reg, u8 *val, u8 len)
{
u8 reg16[2] = { reg >> 8, reg };
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = reg16, .len = 2 },
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = len } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
u16 reg, u8 *val)
{
u8 msg[2] = {reg >> 8, reg & 0xff};
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = msg, .len = 2},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
u16 reg, u8 val)
{
u8 msg[3] = {reg >> 8, reg & 0xff, val};
return i2c_write(adap, adr, msg, 3);
}
static int i2c_write_reg(struct i2c_adapter *adap, u8 adr,
u8 reg, u8 val)
{
u8 msg[2] = {reg, val};
return i2c_write(adap, adr, msg, 2);
}
static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
{
struct ddb *dev = i2c->dev;
unsigned long stat;
u32 val;
ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
stat = wait_for_completion_timeout(&i2c->completion, HZ);
if (stat == 0) {
pr_err("DDBridge I2C timeout, card %d, port %d, link %u\n",
dev->nr, i2c->nr, i2c->link);
#ifdef CONFIG_PCI_MSI
{ /* MSI debugging*/
u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
dev_err(dev->dev, "DDBridge IRS %08x\n", istat);
ddbwritel(dev, istat, INTERRUPT_ACK);
}
#endif
return -EIO;
}
val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
if (val & 0x70000)
return -EIO;
return 0;
}
static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
struct i2c_msg msg[], int num)
{
struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
struct ddb *dev = i2c->dev;
u8 addr = 0;
if (num != 1 && num != 2)
return -EIO;
addr = msg[0].addr;
if (msg[0].len > i2c->bsize)
return -EIO;
if (num == 2 && msg[1].flags & I2C_M_RD &&
!(msg[0].flags & I2C_M_RD)) {
if (msg[1].len > i2c->bsize)
return -EIO;
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
ddbwritel(dev, msg[0].len | (msg[1].len << 16),
i2c->regs + I2C_TASKLENGTH);
if (!ddb_i2c_cmd(i2c, addr, 1)) {
ddbcpyfrom(dev, msg[1].buf,
i2c->rbuf,
msg[1].len);
return num;
}
}
if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
if (!ddb_i2c_cmd(i2c, addr, 2))
return num;
}
if (num == 1 && (msg[0].flags & I2C_M_RD)) {
ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
if (!ddb_i2c_cmd(i2c, addr, 3)) {
ddbcpyfrom(dev, msg[0].buf,
i2c->rbuf, msg[0].len);
return num;
}
}
return -EIO;
}
static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
struct i2c_algorithm ddb_i2c_algo = {
.master_xfer = ddb_i2c_master_xfer,
.functionality = ddb_i2c_functionality,
};
static void ddb_i2c_release(struct ddb *dev)
{
int i;
struct ddb_i2c *i2c;
for (i = 0; i < dev->i2c_num; i++) {
i2c = &dev->i2c[i];
i2c_del_adapter(&i2c->adap);
}
}
static void i2c_handler(unsigned long priv)
{
struct ddb_i2c *i2c = (struct ddb_i2c *) priv;
complete(&i2c->completion);
}
static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
struct ddb_regmap *regmap, int link, int i, int num)
{
struct i2c_adapter *adap;
i2c->nr = i;
i2c->dev = dev;
i2c->link = link;
i2c->bsize = regmap->i2c_buf->size;
i2c->wbuf = DDB_LINK_TAG(link) | (regmap->i2c_buf->base + i2c->bsize * i);
i2c->rbuf = i2c->wbuf;// + i2c->bsize / 2;
i2c->regs = DDB_LINK_TAG(link) | (regmap->i2c->base + regmap->i2c->size * i);
ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
ddbwritel(dev, ((i2c->rbuf & 0xffff) << 16) | (i2c->wbuf & 0xffff),
i2c->regs + I2C_TASKADDRESS);
init_completion(&i2c->completion);
adap = &i2c->adap;
i2c_set_adapdata(adap, i2c);
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
#else
#ifdef I2C_CLASS_TV_ANALOG
adap->class = I2C_CLASS_TV_ANALOG;
#endif
#endif
strcpy(adap->name, "ddbridge");
adap->algo = &ddb_i2c_algo;
adap->algo_data = (void *)i2c;
adap->dev.parent = dev->dev;
return i2c_add_adapter(adap);
}
static int ddb_i2c_init(struct ddb *dev)
{
int stat = 0;
u32 i, j, num = 0, l;
struct ddb_i2c *i2c;
struct i2c_adapter *adap;
struct ddb_regmap *regmap;
for (l = 0; l < DDB_MAX_LINK; l++) {
if (!dev->link[l].info)
continue;
regmap = dev->link[l].info->regmap;
if (!regmap || !regmap->i2c)
continue;
for (i = 0; i < regmap->i2c->num; i++) {
if (!(dev->link[l].info->i2c_mask & (1 << i)))
continue;
i2c = &dev->i2c[num];
dev->handler_data[i + l * 32] = (unsigned long) i2c;
dev->handler[i + l * 32] = i2c_handler;
stat = ddb_i2c_add(dev, i2c, regmap, l, i, num);
if (stat)
break;
num++;
}
}
if (stat) {
for (j = 0; j < num; j++) {
i2c = &dev->i2c[j];
adap = &i2c->adap;
i2c_del_adapter(adap);
}
} else
dev->i2c_num = num;
return stat;
}

116
ddbridge/ddbridge-i2c.h Normal file
View File

@ -0,0 +1,116 @@
/*
* ddbridge-i2c.h: Digital Devices bridge i2c driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#ifndef _DDBRIDGE_I2C_H_
#define _DDBRIDGE_I2C_H_
#include <linux/i2c.h>
#include <linux/types.h>
static inline int i2c_io(struct i2c_adapter *adapter, u8 adr,
u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = wbuf, .len = wlen },
{.addr = adr, .flags = I2C_M_RD,
.buf = rbuf, .len = rlen } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static inline int i2c_write(struct i2c_adapter *adap, u8 adr,
u8 *data, int len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0,
.buf = data, .len = len};
return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
}
static inline int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
{
struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
}
static inline int i2c_read_regs(struct i2c_adapter *adapter,
u8 adr, u8 reg, u8 *val, u8 len)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1 },
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = len } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static inline int i2c_read_regs16(struct i2c_adapter *adapter,
u8 adr, u16 reg, u8 *val, u8 len)
{
u8 reg16[2] = { reg >> 8, reg };
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = reg16, .len = 2 },
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = len } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static inline int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 *val)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
u16 reg, u8 *val)
{
u8 msg[2] = {reg >> 8, reg & 0xff};
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = msg, .len = 2},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1 } };
return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}
static inline int i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
u16 reg, u8 val)
{
u8 msg[3] = {reg >> 8, reg & 0xff, val};
return i2c_write(adap, adr, msg, 3);
}
static inline int i2c_write_reg(struct i2c_adapter *adap, u8 adr,
u8 reg, u8 val)
{
u8 msg[2] = {reg, val};
return i2c_write(adap, adr, msg, 2);
}
#endif

1150
ddbridge/ddbridge-mod.c Normal file

File diff suppressed because it is too large Load Diff

491
ddbridge/ddbridge-ns.c Normal file
View File

@ -0,0 +1,491 @@
/*
* ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming
*
* Copyright (C) 2010-2015 Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
* Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
static int ddb_dvb_ns_input_start(struct ddb_input *input);
static int ddb_dvb_ns_input_stop(struct ddb_input *input);
static u16 calc_pcs(struct dvb_ns_params *p)
{
u32 sum = 0;
u16 pcs;
sum += (p->sip[0] << 8) | p->sip[1];
sum += (p->sip[2] << 8) | p->sip[3];
sum += (p->dip[0] << 8) | p->dip[1];
sum += (p->dip[2] << 8) | p->dip[3];
sum += 0x11; /* UDP proto */
sum = (sum >> 16) + (sum & 0xffff);
pcs = sum;
return pcs;
}
static u16 calc_pcs16(struct dvb_ns_params *p, int ipv)
{
u32 sum = 0, i;
u16 pcs;
for (i = 0; i < ipv ? 16 : 4; i += 2) {
sum += (p->sip[i] << 8) | p->sip[i + 1];
sum += (p->dip[i] << 8) | p->dip[i + 1];
}
sum += 0x11; /* UDP proto */
sum = (sum >> 16) + (sum & 0xffff);
pcs = sum;
return pcs;
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static void ns_free(struct dvbnss *nss)
{
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
mutex_lock(&dev->mutex);
dns->input = 0;
mutex_unlock(&dev->mutex);
}
static int ns_alloc(struct dvbnss *nss)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
int i, ret = -EBUSY;
mutex_lock(&dev->mutex);
for (i = 0; i < dev->ns_num; i++) {
if (dev->ns[i].input)
continue;
dev->ns[i].input = input;
dev->ns[i].fe = input;
nss->priv = &dev->ns[i];
ret = 0;
/*pr_info("%s i=%d fe=%d\n", __func__, i, input->nr); */
break;
}
ddbwritel(dev, 0x03, RTP_MASTER_CONTROL);
mutex_unlock(&dev->mutex);
return ret;
}
static int ns_set_pids(struct dvbnss *nss)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
if (dev->ids.devid == 0x0301dd01) {
u32 sys = 0;
int pid, j = 1;
sys |= nss->pids[0] & 3;
sys |= (nss->pids[2] & 0x1f) << 4;
ddbwritel(dev, sys, PID_FILTER_SYSTEM_PIDS(dns->nr));
for (pid = 20; j < 5 && pid < 8192; pid++)
if (nss->pids[pid >> 3] & (1 << (pid & 7))) {
ddbwritel(dev, 0x8000 | pid,
PID_FILTER_PID(dns->nr, j));
j++;
}
/* disable unused pids */
for (; j < 5; j++)
ddbwritel(dev, 0, PID_FILTER_PID(dns->nr, j));
} else
ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400);
return 0;
}
static int ns_set_pid(struct dvbnss *nss, u16 pid)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
u16 byte = (pid & 0x1fff) >> 3;
u8 bit = 1 << (pid & 7);
u32 off = STREAM_PIDS(dns->nr);
#if 1
if (dev->ids.devid == 0x0301dd01) {
if (pid & 0x2000) {
if (pid & 0x8000)
memset(nss->pids, 0xff, 0x400);
else
memset(nss->pids, 0x00, 0x400);
} else {
if (pid & 0x8000)
nss->pids[byte] |= bit;
else
nss->pids[byte] &= ~bit;
}
ns_set_pids(nss);
} else {
if (pid & 0x2000) {
if (pid & 0x8000)
ddbmemset(dev, off, 0xff, 0x400);
else
ddbmemset(dev, off, 0x00, 0x400);
} else {
u8 val = ddbreadb(dev, off + byte);
if (pid & 0x8000)
ddbwriteb(dev, val | bit, off + byte);
else
ddbwriteb(dev, val & ~bit, off + byte);
}
}
#else
ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400);
#endif
return 0;
}
static int citoport(struct ddb *dev, u8 ci)
{
int i, j;
for (i = j = 0; i < dev->link[0].info->port_num; i++) {
if (dev->port[i].class == DDB_PORT_CI) {
if (j == ci)
return i;
j++;
}
}
return -1;
}
static int ns_set_ci(struct dvbnss *nss, u8 ci)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
int ciport;
if (ci == 255) {
dns->fe = input;
return 0;
}
ciport = citoport(dev, ci);
if (ciport < 0)
return -EINVAL;
pr_info("input %d.%d to ci %d at port %d\n", input->port->lnr, input->nr, ci, ciport);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1c, TS_OUTPUT_CONTROL(ciport));
usleep_range(1, 5);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d, TS_OUTPUT_CONTROL(ciport));
dns->fe = dev->port[ciport].input[0];
return 0;
}
static u8 rtp_head[] = {
0x80, 0x21,
0x00, 0x00, /* seq number */
0x00, 0x00, 0x00, 0x00, /* time stamp*/
0x91, 0x82, 0x73, 0x64, /* SSRC */
};
static u8 rtcp_head[] = {
/* SR off 42:8 len 28*/
0x80, 0xc8, /* SR type */
0x00, 0x06, /* len */
0x91, 0x82, 0x73, 0x64, /* SSRC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* NTP */
0x73, 0x64, 0x00, 0x00, /* RTP TS */
0x00, 0x00, 0x00, 0x00, /* packet count */
0x00, 0x00, 0x00, 0x00, /* octet count */
/* SDES off 70:36 len 20 */
0x81, 0xca, /* SDES */
0x00, 0x03, /* len */
0x91, 0x82, 0x73, 0x64, /* SSRC */
0x01, 0x05, /* CNAME item */
0x53, 0x41, 0x54, 0x49, 0x50, /* "SATIP" */
0x00, /* item type 0 */
/* APP off 86:52 len 16+string length */
0x80, 0xcc, /* APP */
0x00, 0x04, /* len */
0x91, 0x82, 0x73, 0x64, /* SSRC */
0x53, 0x45, 0x53, 0x31, /* "SES1" */
0x00, 0x00, /* identifier */
0x00, 0x00, /* string length */
/* string off 102:68 */
};
static int ns_set_rtcp_msg(struct dvbnss *nss, u8 *msg, u32 len)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
u32 off = STREAM_PACKET_ADR(dns->nr);
u32 coff = 96;
u16 wlen;
if (!len) {
ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) &
~0x10,
STREAM_CONTROL(dns->nr));
return 0;
}
if (copy_from_user(dns->p + coff + dns->rtcp_len, msg, len))
return -EFAULT;
dns->p[coff + dns->rtcp_len - 2] = (len >> 8);
dns->p[coff + dns->rtcp_len - 1] = (len & 0xff);
if (len & 3) {
u32 pad = 4 - (len & 3);
memset(dns->p + coff + dns->rtcp_len + len, 0, pad);
len += pad;
}
wlen = len / 4;
wlen += 3;
dns->p[coff + dns->rtcp_len - 14] = (wlen >> 8);
dns->p[coff + dns->rtcp_len - 13] = (wlen & 0xff);
ddbcpyto(dev, off, dns->p, sizeof(dns->p));
ddbwritel(dev, (dns->rtcp_udplen + len) |
((STREAM_PACKET_OFF(dns->nr) + coff) << 16),
STREAM_RTCP_PACKET(dns->nr));
ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) | 0x10,
STREAM_CONTROL(dns->nr));
return 0;
}
static u32 set_nsbuf(struct dvb_ns_params *p, u8 *buf,
u32 *udplen, int rtcp, int vlan)
{
u32 c = 0;
u16 pcs;
u16 sport, dport;
sport = rtcp ? p->sport2 : p->sport;
dport = rtcp ? p->dport2 : p->dport;
/* MAC header */
memcpy(buf + c, p->dmac, 6);
memcpy(buf + c + 6, p->smac, 6);
c += 12;
if (vlan) {
buf[c + 0] = 0x81;
buf[c + 1] = 0x00;
buf[c + 2] = ((p->qos & 7) << 5) | ((p->vlan & 0xf00) >> 8);
buf[c + 3] = p->vlan & 0xff;
c += 4;
}
buf[c + 0] = 0x08;
buf[c + 1] = 0x00;
c += 2;
/* IP header */
if (p->flags & DVB_NS_IPV6) {
u8 ip6head[8] = { 0x65, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x00, };
memcpy(buf + c, ip6head, sizeof(ip6head));
buf[c + 7] = p->ttl;
memcpy(buf + c + 8, p->sip, 16);
memcpy(buf + c + 24, p->dip, 16);
c += 40;
/* UDP */
buf[c + 0] = sport >> 8;
buf[c + 1] = sport & 0xff;
buf[c + 2] = dport >> 8;
buf[c + 3] = dport & 0xff;
buf[c + 4] = 0; /* length */
buf[c + 5] = 0;
pcs = calc_pcs16(p, p->flags & DVB_NS_IPV6);
buf[c + 6] = pcs >> 8;
buf[c + 7] = pcs & 0xff;
c += 8;
*udplen = 8;
} else {
u8 ip4head[12] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x40, 0x11, 0x00, 0x00 };
memcpy(buf + c, ip4head, sizeof(ip4head));
buf[c + 8] = p->ttl;
memcpy(buf + c + 12, p->sip, 4);
memcpy(buf + c + 16, p->dip, 4);
c += 20;
/* UDP */
buf[c + 0] = sport >> 8;
buf[c + 1] = sport & 0xff;
buf[c + 2] = dport >> 8;
buf[c + 3] = dport & 0xff;
buf[c + 4] = 0; /* length */
buf[c + 5] = 0;
pcs = calc_pcs(p);
buf[c + 6] = pcs >> 8;
buf[c + 7] = pcs & 0xff;
c += 8;
*udplen = 8;
}
if (rtcp) {
memcpy(buf + c, rtcp_head, sizeof(rtcp_head));
memcpy(buf + c + 4, p->ssrc, 4);
memcpy(buf + c + 32, p->ssrc, 4);
memcpy(buf + c + 48, p->ssrc, 4);
c += sizeof(rtcp_head);
*udplen += sizeof(rtcp_head);
} else if (p->flags & DVB_NS_RTP) {
memcpy(buf + c, rtp_head, sizeof(rtp_head));
memcpy(buf + c + 8, p->ssrc, 4);
c += sizeof(rtp_head);
*udplen += sizeof(rtp_head);
}
return c;
}
static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len)
{
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
u32 off = STREAM_PACKET_ADR(dns->nr);
if (nss->params.flags & DVB_NS_RTCP)
return -EINVAL;
if (copy_from_user(dns->p + dns->ts_offset, buf, len))
return -EFAULT;
ddbcpyto(dev, off, dns->p, sizeof(dns->p));
return 0;
}
static int ns_insert_ts_packets(struct dvbnss *nss, u8 count)
{
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
u32 value = count;
if (nss->params.flags & DVB_NS_RTCP)
return -EINVAL;
if (count < 1 || count > 2)
return -EINVAL;
ddbwritel(dev, value, STREAM_INSERT_PACKET(dns->nr));
return 0;
}
static int ns_set_net(struct dvbnss *nss)
{
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
struct dvb_ns_params *p = &nss->params;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
u32 off = STREAM_PACKET_ADR(dns->nr);
u32 coff = 96;
dns->ts_offset = set_nsbuf(p, dns->p, &dns->udplen, 0, dev->vlan);
if (nss->params.flags & DVB_NS_RTCP)
dns->rtcp_len = set_nsbuf(p, dns->p + coff,
&dns->rtcp_udplen, 1, dev->vlan);
ddbcpyto(dev, off, dns->p, sizeof(dns->p));
ddbwritel(dev, dns->udplen | (STREAM_PACKET_OFF(dns->nr) << 16),
STREAM_RTP_PACKET(dns->nr));
ddbwritel(dev, dns->rtcp_udplen |
((STREAM_PACKET_OFF(dns->nr) + coff) << 16),
STREAM_RTCP_PACKET(dns->nr));
return 0;
}
static int ns_start(struct dvbnss *nss)
{
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
u32 reg = 0x8003;
if (nss->params.flags & DVB_NS_RTCP)
reg |= 0x10;
if (nss->params.flags & DVB_NS_RTP_TO)
reg |= 0x20;
if (nss->params.flags & DVB_NS_RTP)
reg |= 0x40;
if (nss->params.flags & DVB_NS_IPV6)
reg |= 0x80;
if (dns->fe != input)
ddb_dvb_ns_input_start(dns->fe);
ddb_dvb_ns_input_start(input);
printk("ns start ns %u, fe %u link %u\n", dns->nr, dns->fe->nr, dns->fe->port->lnr);
ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16),
STREAM_CONTROL(dns->nr));
return 0;
}
static int ns_stop(struct dvbnss *nss)
{
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
struct dvb_netstream *ns = nss->ns;
struct ddb_input *input = ns->priv;
struct ddb *dev = input->port->dev;
ddbwritel(dev, 0x00, STREAM_CONTROL(dns->nr));
ddb_dvb_ns_input_stop(input);
if (dns->fe != input)
ddb_dvb_ns_input_stop(dns->fe);
return 0;
}
static int netstream_init(struct ddb_input *input)
{
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
struct dvb_adapter *adap = dvb->adap;
struct dvb_netstream *ns = &dvb->dvbns;
struct ddb *dev = input->port->dev;
int i, res;
ddbmemset(dev, STREAM_PIDS(input->nr), 0x00, 0x400);
for (i = 0; i < dev->ns_num; i++)
dev->ns[i].nr = i;
ns->priv = input;
ns->set_net = ns_set_net;
ns->set_rtcp_msg = ns_set_rtcp_msg;
ns->set_ts_packets = ns_set_ts_packets;
ns->insert_ts_packets = ns_insert_ts_packets;
ns->set_pid = ns_set_pid;
ns->set_pids = ns_set_pids;
ns->set_ci = ns_set_ci;
ns->start = ns_start;
ns->stop = ns_stop;
ns->alloc = ns_alloc;
ns->free = ns_free;
res = dvb_netstream_init(adap, ns);
return res;
}

435
ddbridge/ddbridge-regs.h Normal file
View File

@ -0,0 +1,435 @@
/*
* ddbridge-regs.h: Digital Devices PCIe bridge driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
/* Register Definitions */
#define CUR_REGISTERMAP_VERSION 0x10003
#define CUR_REGISTERMAP_VERSION_CI 0x10000
#define CUR_REGISTERMAP_VERSION_MOD 0x10000
#define HARDWARE_VERSION 0x00
#define REGISTERMAP_VERSION 0x04
/* ------------------------------------------------------------------------- */
/* SPI Controller */
#define SPI_CONTROL 0x10
#define SPI_DATA 0x14
/* ------------------------------------------------------------------------- */
/* GPIO */
#define GPIO_OUTPUT 0x20
#define GPIO_INPUT 0x24
#define GPIO_DIRECTION 0x28
/* ------------------------------------------------------------------------- */
/* MDIO */
#define MDIO_CTRL 0x20
#define MDIO_ADR 0x24
#define MDIO_REG 0x28
#define MDIO_VAL 0x2C
/* ------------------------------------------------------------------------- */
#define BOARD_CONTROL 0x30
/* ------------------------------------------------------------------------- */
/* Interrupt controller
How many MSI's are available depends on HW (Min 2 max 8)
How many are usable also depends on Host platform
*/
#define INTERRUPT_BASE (0x40)
#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
#define MSI0_ENABLE (INTERRUPT_BASE + 0x00)
#define MSI1_ENABLE (INTERRUPT_BASE + 0x04)
#define MSI2_ENABLE (INTERRUPT_BASE + 0x08)
#define MSI3_ENABLE (INTERRUPT_BASE + 0x0C)
#define MSI4_ENABLE (INTERRUPT_BASE + 0x10)
#define MSI5_ENABLE (INTERRUPT_BASE + 0x14)
#define MSI6_ENABLE (INTERRUPT_BASE + 0x18)
#define MSI7_ENABLE (INTERRUPT_BASE + 0x1C)
#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
#define INTERRUPT_ACK (INTERRUPT_BASE + 0x20)
#define INTMASK_CLOCKGEN (0x00000001)
#define INTMASK_TEMPMON (0x00000002)
#define INTMASK_I2C1 (0x00000001)
#define INTMASK_I2C2 (0x00000002)
#define INTMASK_I2C3 (0x00000004)
#define INTMASK_I2C4 (0x00000008)
#define INTMASK_CIRQ1 (0x00000010)
#define INTMASK_CIRQ2 (0x00000020)
#define INTMASK_CIRQ3 (0x00000040)
#define INTMASK_CIRQ4 (0x00000080)
#define INTMASK_TSINPUT1 (0x00000100)
#define INTMASK_TSINPUT2 (0x00000200)
#define INTMASK_TSINPUT3 (0x00000400)
#define INTMASK_TSINPUT4 (0x00000800)
#define INTMASK_TSINPUT5 (0x00001000)
#define INTMASK_TSINPUT6 (0x00002000)
#define INTMASK_TSINPUT7 (0x00004000)
#define INTMASK_TSINPUT8 (0x00008000)
#define INTMASK_TSOUTPUT1 (0x00010000)
#define INTMASK_TSOUTPUT2 (0x00020000)
#define INTMASK_TSOUTPUT3 (0x00040000)
#define INTMASK_TSOUTPUT4 (0x00080000)
/* Modulator registers */
/* Clock Generator ( Sil598 @ 0xAA I2c ) */
#define CLOCKGEN_BASE (0x80)
#define CLOCKGEN_CONTROL (CLOCKGEN_BASE + 0x00)
#define CLOCKGEN_INDEX (CLOCKGEN_BASE + 0x04)
#define CLOCKGEN_WRITEDATA (CLOCKGEN_BASE + 0x08)
#define CLOCKGEN_READDATA (CLOCKGEN_BASE + 0x0C)
/* DAC ( AD9781/AD9783 SPI ) */
#define DAC_BASE (0x090)
#define DAC_CONTROL (DAC_BASE)
#define DAC_WRITE_DATA (DAC_BASE+4)
#define DAC_READ_DATA (DAC_BASE+8)
#define DAC_CONTROL_INSTRUCTION_REG (0xFF)
#define DAC_CONTROL_STARTIO (0x100)
#define DAC_CONTROL_RESET (0x200)
/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */
#define TEMPMON_BASE (0xA0)
#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00)
/* SHORT Temperature in °C x 256 */
#define TEMPMON_CORE (TEMPMON_BASE + 0x04)
#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08)
#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C)
/* ------------------------------------------------------------------------- */
/* I2C Master Controller */
#define I2C_BASE (0x80) /* Byte offset */
#define I2C_COMMAND (0x00)
#define I2C_TIMING (0x04)
#define I2C_TASKLENGTH (0x08) /* High read, low write */
#define I2C_TASKADDRESS (0x0C) /* High read, low write */
#define I2C_MONITOR (0x1C)
#define I2C_SPEED_666 (0x02010202)
#define I2C_SPEED_400 (0x04030404)
#define I2C_SPEED_200 (0x09080909)
#define I2C_SPEED_154 (0x0C0B0C0C)
#define I2C_SPEED_100 (0x13121313)
#define I2C_SPEED_77 (0x19181919)
#define I2C_SPEED_50 (0x27262727)
/* ------------------------------------------------------------------------- */
/* DMA Controller */
#define DMA_BASE_WRITE (0x100)
#define DMA_BASE_READ (0x140)
#define DMA_CONTROL (0x00)
#define DMA_ERROR (0x04)
#define DMA_DIAG_CONTROL (0x1C)
#define DMA_DIAG_PACKETCOUNTER_LOW (0x20)
#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24)
#define DMA_DIAG_TIMECOUNTER_LOW (0x28)
#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C)
#define DMA_DIAG_RECHECKCOUNTER (0x30)
#define DMA_DIAG_WAITTIMEOUTINIT (0x34)
#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38)
#define DMA_DIAG_WAITCOUNTER (0x3C)
#define TS_INPUT_BASE (0x200)
#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00)
#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04)
#define TS_OUTPUT_BASE (0x280)
#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00)
#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04)
/* ------------------------------------------------------------------------- */
/* DMA Buffer */
#define DMA_BUFFER_BASE (0x300)
#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00)
#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04)
#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
#define DMA_BASE_ADDRESS_TABLE (0x2000)
#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
/* ------------------------------------------------------------------------- */
#define LNB_BASE (0x400)
#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00)
#define LNB_CMD (7ULL << 0)
#define LNB_CMD_NOP 0
#define LNB_CMD_INIT 1
#define LNB_CMD_STATUS 2
#define LNB_CMD_LOW 3
#define LNB_CMD_HIGH 4
#define LNB_CMD_OFF 5
#define LNB_CMD_DISEQC 6
#define LNB_CMD_UNI 7
#define LNB_BUSY (1ULL << 4)
#define LNB_TONE (1ULL << 15)
#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04)
#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08)
#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c)
#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14)
/* ------------------------------------------------------------------------- */
/* CI Interface (only CI-Bridge) */
#define CI_BASE (0x400)
#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00)
#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04)
#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08)
#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c)
#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10)
#define CI_RESET_CAM (0x00000001)
#define CI_POWER_ON (0x00000002)
#define CI_ENABLE (0x00000004)
#define CI_BLOCKIO_ENABLE (0x00000008)
#define CI_BYPASS_DISABLE (0x00000010)
#define CI_DISABLE_AUTO_OFF (0x00000020)
#define CI_CAM_READY (0x00010000)
#define CI_CAM_DETECT (0x00020000)
#define CI_READY (0x80000000)
#define CI_BLOCKIO_ACTIVE (0x40000000)
#define CI_BLOCKIO_RCVDATA (0x20000000)
#define CI_BLOCKIO_SEND_PENDING (0x10000000)
#define CI_BLOCKIO_SEND_COMPLETE (0x08000000)
#define CI_READ_CMD (0x40000000)
#define CI_WRITE_CMD (0x80000000)
#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14)
#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18)
#define CI_BLOCKIO_SEND_COMMAND (0x80000000)
#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000)
#define CI_BLOCKIO_RCVDATA_ACK (0x40000000)
#define CI_BUFFER_BASE (0x3000)
#define CI_BUFFER_SIZE (0x0800)
#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2)
#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
#define CI_BLOCKIO_SEND_BUFFER(i) \
(CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE)
#define VCO1_BASE (0xC0)
#define VCO1_CONTROL (VCO1_BASE + 0x00)
#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */
/* 1 = Trigger write, resets when done */
#define VCO1_CONTROL_WRITE (0x00000001)
/* 0 = Put VCO into power down */
#define VCO1_CONTROL_CE (0x00000002)
/* Muxout from VCO (usually = Lock) */
#define VCO1_CONTROL_MUXOUT (0x00000004)
#define VCO2_BASE (0xC8)
#define VCO2_CONTROL (VCO2_BASE + 0x00)
#define VCO2_DATA (VCO2_BASE + 0x04) /* 24 Bit */
/* 1 = Trigger write, resets when done */
#define VCO2_CONTROL_WRITE (0x00000001)
/* 0 = Put VCO into power down */
#define VCO2_CONTROL_CE (0x00000002)
/* Muxout from VCO (usually = Lock) */
#define VCO2_CONTROL_MUXOUT (0x00000004)
#define VCO3_BASE (0xD0)
#define VCO3_CONTROL (VCO3_BASE + 0x00)
#define VCO3_DATA (VCO3_BASE + 0x04) /* 32 Bit */
/* 1 = Trigger write, resets when done */
#define VCO3_CONTROL_WRITE (0x00000001)
/* 0 = Put VCO into power down */
#define VCO3_CONTROL_CE (0x00000002)
/* Muxout from VCO (usually = Lock) */
#define VCO3_CONTROL_MUXOUT (0x00000004)
#define RF_ATTENUATOR (0xD8)
/* 0x00 = 0 dB
0x01 = 1 dB
...
0x1F = 31 dB
*/
#define RF_POWER (0xE0)
#define RF_POWER_BASE (0xE0)
#define RF_POWER_CONTROL (RF_POWER_BASE + 0x00)
#define RF_POWER_DATA (RF_POWER_BASE + 0x04)
#define RF_POWER_CONTROL_START (0x00000001)
#define RF_POWER_CONTROL_DONE (0x00000002)
#define RF_POWER_CONTROL_VALIDMASK (0x00000700)
#define RF_POWER_CONTROL_VALID (0x00000500)
/* --------------------------------------------------------------------------
Output control
*/
#define IQOUTPUT_BASE (0x240)
#define IQOUTPUT_CONTROL (IQOUTPUT_BASE + 0x00)
#define IQOUTPUT_CONTROL2 (IQOUTPUT_BASE + 0x04)
#define IQOUTPUT_PEAK_DETECTOR (IQOUTPUT_BASE + 0x08)
#define IQOUTPUT_POSTSCALER (IQOUTPUT_BASE + 0x0C)
#define IQOUTPUT_PRESCALER (IQOUTPUT_BASE + 0x10)
#define IQOUTPUT_EQUALIZER_0 (IQOUTPUT_BASE + 0x14)
#define IQOUTPUT_EQUALIZER_1 (IQOUTPUT_BASE + 0x18)
#define IQOUTPUT_EQUALIZER_2 (IQOUTPUT_BASE + 0x1C)
#define IQOUTPUT_EQUALIZER_3 (IQOUTPUT_BASE + 0x20)
#define IQOUTPUT_EQUALIZER_4 (IQOUTPUT_BASE + 0x24)
#define IQOUTPUT_EQUALIZER_5 (IQOUTPUT_BASE + 0x28)
#define IQOUTPUT_EQUALIZER_6 (IQOUTPUT_BASE + 0x2C)
#define IQOUTPUT_EQUALIZER_7 (IQOUTPUT_BASE + 0x30)
#define IQOUTPUT_EQUALIZER_8 (IQOUTPUT_BASE + 0x34)
#define IQOUTPUT_EQUALIZER_9 (IQOUTPUT_BASE + 0x38)
#define IQOUTPUT_EQUALIZER_10 (IQOUTPUT_BASE + 0x3C)
#define IQOUTPUT_EQUALIZER(i) (IQOUTPUT_EQUALIZER_0 + (i) * 4)
#define IQOUTPUT_CONTROL_RESET (0x00000001)
#define IQOUTPUT_CONTROL_ENABLE (0x00000002)
#define IQOUTPUT_CONTROL_RESET_PEAK (0x00000004)
#define IQOUTPUT_CONTROL_ENABLE_PEAK (0x00000008)
#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010)
/* Modulator Base */
#define MODULATOR_BASE (0x200)
#define MODULATOR_CONTROL (MODULATOR_BASE)
#define MODULATOR_IQTABLE_END (MODULATOR_BASE+4)
#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE+8)
#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE+12)
#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK (0x000F0000)
#define MODULATOR_IQTABLE_INDEX_IQ_MASK (0x00008000)
#define MODULATOR_IQTABLE_INDEX_ADDRESS_MASK (0x000007FF)
#define MODULATOR_IQTABLE_INDEX_SEL_I (0x00000000)
#define MODULATOR_IQTABLE_INDEX_SEL_Q (MODULATOR_IQTABLE_INDEX_IQ_MASK)
#define MODULATOR_IQTABLE_SIZE (2048)
/* Modulator Channels */
#define CHANNEL_BASE (0x400)
#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00)
#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04)
#define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C)
#define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10)
#define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14)
#define CHANNEL_PCR_ADJUST_INL(i) (CHANNEL_BASE + (i) * 64 + 0x18)
#define CHANNEL_PCR_ADJUST_INH(i) (CHANNEL_BASE + (i) * 64 + 0x1C)
#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20)
#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24)
#define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28)
#define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C)
#define CHANNEL_CONTROL_RESET (0x00000001)
#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002)
#define CHANNEL_CONTROL_ENABLE_IQ (0x00000004)
#define CHANNEL_CONTROL_ENABLE_SOURCE (0x00000008)
#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010)
#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100)
#define CHANNEL_CONTROL_RESET_ERROR (0x00010000)
#define CHANNEL_CONTROL_BUSY (0x01000000)
#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000)
#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000)
#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000)
#define CHANNEL_SETTINGS_QAM_MASK (0x00000007)
#define CHANNEL_SETTINGS_QAM16 (0x00000000)
#define CHANNEL_SETTINGS_QAM32 (0x00000001)
#define CHANNEL_SETTINGS_QAM64 (0x00000002)
#define CHANNEL_SETTINGS_QAM128 (0x00000003)
#define CHANNEL_SETTINGS_QAM256 (0x00000004)
/* OCTONET */
#define ETHER_BASE (0x100)
#define ETHER_CONTROL (ETHER_BASE + 0x00)
#define ETHER_LENGTH (ETHER_BASE + 0x04)
#define RTP_MASTER_BASE (0x120)
#define RTP_MASTER_CONTROL (RTP_MASTER_BASE + 0x00)
#define RTP_RTCP_INTERRUPT (RTP_MASTER_BASE + 0x04)
#define RTP_MASTER_RTCP_SETTINGS (RTP_MASTER_BASE + 0x0c)
#define STREAM_BASE (0x400)
#define STREAM_CONTROL(i) (STREAM_BASE + (i) * 0x20 + 0x00)
#define STREAM_RTP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x04)
#define STREAM_RTCP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x08)
#define STREAM_RTP_SETTINGS(i) (STREAM_BASE + (i) * 0x20 + 0x0c)
#define STREAM_INSERT_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x10)
#define STREAM_PACKET_OFF(i) ((i) * 0x200)
#define STREAM_PACKET_ADR(i) (0x2000 + (STREAM_PACKET_OFF(i)))
#define STREAM_PIDS(i) (0x4000 + (i) * 0x400)
#define TS_CAPTURE_BASE (0x0140)
#define TS_CAPTURE_CONTROL (TS_CAPTURE_BASE + 0x00)
#define TS_CAPTURE_PID (TS_CAPTURE_BASE + 0x04)
#define TS_CAPTURE_RECEIVED (TS_CAPTURE_BASE + 0x08)
#define TS_CAPTURE_TIMEOUT (TS_CAPTURE_BASE + 0x0c)
#define TS_CAPTURE_TABLESECTION (TS_CAPTURE_BASE + 0x10)
#define TS_CAPTURE_MEMORY (0x7000)
#define PID_FILTER_BASE (0x800)
#define PID_FILTER_SYSTEM_PIDS(i) (PID_FILTER_BASE + (i) * 0x20)
#define PID_FILTER_PID(i, j) (PID_FILTER_BASE + (i) * 0x20 + (j) * 4)

533
ddbridge/ddbridge.c Normal file
View File

@ -0,0 +1,533 @@
/*
* ddbridge.c: Digital Devices PCIe bridge driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
* Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de>
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
/*#define DDB_ALT_DMA*/
#define DDB_USE_WORK
/*#define DDB_TEST_THREADED*/
#include "ddbridge.h"
#include "ddbridge-regs.h"
static struct workqueue_struct *ddb_wq;
static int adapter_alloc;
module_param(adapter_alloc, int, 0444);
MODULE_PARM_DESC(adapter_alloc,
"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
#ifdef CONFIG_PCI_MSI
static int msi = 1;
module_param(msi, int, 0444);
MODULE_PARM_DESC(msi,
" Control MSI interrupts: 0-disable, 1-enable (default)");
#endif
#include "ddbridge-core.c"
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static void ddb_unmap(struct ddb *dev)
{
if (dev->regs)
iounmap(dev->regs);
vfree(dev);
}
static void __devexit ddb_remove(struct pci_dev *pdev)
{
struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
ddb_nsd_detach(dev);
ddb_ports_detach(dev);
ddb_i2c_release(dev);
if (dev->link[0].info->ns_num)
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0, INTERRUPT_ENABLE);
ddbwritel(dev, 0, MSI1_ENABLE);
if (dev->msi == 2)
free_irq(dev->pdev->irq + 1, dev);
free_irq(dev->pdev->irq, dev);
#ifdef CONFIG_PCI_MSI
if (dev->msi)
pci_disable_msi(dev->pdev);
#endif
ddb_ports_release(dev);
ddb_buffers_free(dev);
ddb_device_destroy(dev);
ddb_unmap(dev);
pci_set_drvdata(pdev, 0);
pci_disable_device(pdev);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define __devinit
#define __devinitdata
#endif
static int __devinit ddb_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ddb *dev;
int stat = 0;
int irq_flag = IRQF_SHARED;
if (pci_enable_device(pdev) < 0)
return -ENODEV;
dev = vzalloc(sizeof(struct ddb));
if (dev == NULL)
return -ENOMEM;
mutex_init(&dev->mutex);
dev->has_dma = 1;
dev->pdev = pdev;
dev->dev = &pdev->dev;
pci_set_drvdata(pdev, dev);
dev->ids.vendor = id->vendor;
dev->ids.device = id->device;
dev->ids.subvendor = id->subvendor;
dev->ids.subdevice = id->subdevice;
dev->link[0].dev = dev;
dev->link[0].info = (struct ddb_info *) id->driver_data;
pr_info("DDBridge driver detected: %s\n", dev->link[0].info->name);
dev->regs_len = pci_resource_len(dev->pdev, 0);
dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
pci_resource_len(dev->pdev, 0));
if (!dev->regs) {
pr_err("DDBridge: not enough memory for register map\n");
stat = -ENOMEM;
goto fail;
}
if (ddbreadl(dev, 0) == 0xffffffff) {
pr_err("DDBridge: cannot read registers\n");
stat = -ENODEV;
goto fail;
}
dev->ids.hwid = ddbreadl(dev, 0);
dev->ids.regmapid = ddbreadl(dev, 4);
pr_info("DDBridge: HW %08x REGMAP %08x\n",
dev->ids.hwid, dev->ids.regmapid);
if (dev->link[0].info->ns_num) {
int i;
ddbwritel(dev, 0, ETHER_CONTROL);
for (i = 0; i < 16; i++)
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
usleep_range(5000, 6000);
}
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
ddbwritel(dev, 0x00000000, MSI2_ENABLE);
ddbwritel(dev, 0x00000000, MSI3_ENABLE);
ddbwritel(dev, 0x00000000, MSI4_ENABLE);
ddbwritel(dev, 0x00000000, MSI5_ENABLE);
ddbwritel(dev, 0x00000000, MSI6_ENABLE);
ddbwritel(dev, 0x00000000, MSI7_ENABLE);
#ifdef CONFIG_PCI_MSI
if (msi && pci_msi_enabled()) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
stat = pci_enable_msi_range(dev->pdev, 1, 2);
if (stat >= 1) {
dev->msi = stat;
pr_info("DDBridge: using %d MSI interrupt(s)\n", dev->msi);
irq_flag = 0;
} else
pr_info("DDBridge: MSI not available.\n");
#else
stat = pci_enable_msi_block(dev->pdev, 2);
if (stat == 0) {
dev->msi = 1;
pr_info("DDBridge: using 2 MSI interrupts\n");
}
if (stat == 1)
stat = pci_enable_msi(dev->pdev);
if (stat < 0) {
pr_info("DDBridge: MSI not available.\n");
} else {
irq_flag = 0;
dev->msi++;
}
#endif
}
if (dev->msi == 2) {
stat = request_irq(dev->pdev->irq, irq_handler0,
irq_flag, "ddbridge", (void *) dev);
if (stat < 0)
goto fail0;
stat = request_irq(dev->pdev->irq + 1, irq_handler1,
irq_flag, "ddbridge", (void *) dev);
if (stat < 0) {
free_irq(dev->pdev->irq, dev);
goto fail0;
}
} else
#endif
{
#ifdef DDB_TEST_THREADED
stat = request_threaded_irq(dev->pdev->irq, irq_handler,
irq_thread,
irq_flag,
"ddbridge", (void *) dev);
#else
stat = request_irq(dev->pdev->irq, irq_handler,
irq_flag, "ddbridge", (void *) dev);
#endif
if (stat < 0)
goto fail0;
}
ddbwritel(dev, 0, DMA_BASE_READ);
if (dev->link[0].info->type != DDB_MOD)
ddbwritel(dev, 0, DMA_BASE_WRITE);
if (dev->link[0].info->type == DDB_MOD) {
if (ddbreadl(dev, 0x1c) == 4)
dev->link[0].info->port_num = 4;
}
/*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/
if (dev->msi == 2) {
ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
} else {
ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
ddbwritel(dev, 0x00000000, MSI1_ENABLE);
}
if (ddb_init(dev) == 0)
return 0;
ddbwritel(dev, 0, INTERRUPT_ENABLE);
ddbwritel(dev, 0, MSI1_ENABLE);
free_irq(dev->pdev->irq, dev);
if (dev->msi == 2)
free_irq(dev->pdev->irq + 1, dev);
fail0:
pr_err("fail0\n");
if (dev->msi)
pci_disable_msi(dev->pdev);
fail:
pr_err("fail\n");
ddb_unmap(dev);
pci_set_drvdata(pdev, 0);
pci_disable_device(pdev);
return -1;
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static struct ddb_regset octopus_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
/****************************************************************************/
static struct ddb_regmap octopus_map = {
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
};
static struct ddb_regmap octopus_net_map = {
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
};
static struct ddb_regmap octopus_mod_map = {
};
/****************************************************************************/
static struct ddb_info ddb_none = {
.type = DDB_NONE,
.name = "unknown Digital Devices PCIe card, install newer driver",
.regmap = &octopus_map,
};
static struct ddb_info ddb_octopus = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus DVB adapter",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
};
static struct ddb_info ddb_octopusv3 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus V3 DVB adapter",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
};
static struct ddb_info ddb_octopus_le = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus LE DVB adapter",
.regmap = &octopus_map,
.port_num = 2,
.i2c_mask = 0x03,
};
static struct ddb_info ddb_octopus_oem = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus OEM",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.led_num = 1,
.fan_num = 1,
.temp_num = 1,
.temp_bus = 0,
};
static struct ddb_info ddb_octopus_mini = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus Mini",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
};
static struct ddb_info ddb_v6 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V6 DVB adapter",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x07,
};
static struct ddb_info ddb_v6_5 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V6.5 DVB adapter",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
};
static struct ddb_info ddb_v7 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V7 DVB adapter",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 2,
};
static struct ddb_info ddb_ctv7 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine CT V7 DVB adapter",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 3,
};
static struct ddb_info ddb_satixS2v3 = {
.type = DDB_OCTOPUS,
.name = "Mystique SaTiX-S2 V3 DVB adapter",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x07,
};
static struct ddb_info ddb_ci = {
.type = DDB_OCTOPUS_CI,
.name = "Digital Devices Octopus CI",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x03,
};
static struct ddb_info ddb_cis = {
.type = DDB_OCTOPUS_CI,
.name = "Digital Devices Octopus CI single",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x01,
};
static struct ddb_info ddb_ci_s2_pro = {
.type = DDB_OCTOPUS_CI,
.name = "Digital Devices Octopus CI S2 Pro",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 3,
};
static struct ddb_info ddb_dvbct = {
.type = DDB_OCTOPUS,
.name = "Digital Devices DVBCT V6.1 DVB adapter",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x07,
};
/****************************************************************************/
static struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 1,
};
static struct ddb_info ddb_mod = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C modulator",
.regmap = &octopus_mod_map,
.port_num = 10,
.temp_num = 1,
};
static struct ddb_info ddb_octopus_net = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet network DVB adapter",
.regmap = &octopus_net_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.ns_num = 12,
.mdio_num = 1,
};
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
#define DDVID 0xdd01 /* Digital Devices Vendor ID */
#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
.vendor = _vend, .device = _dev, \
.subvendor = _subvend, .subdevice = _subdev, \
.driver_data = (unsigned long)&_driverdata }
static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem),
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
DDB_ID(DDVID, 0x0005, DDVID, 0x0011, ddb_octopus_mini),
DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7),
DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7),
DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7),
DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7),
DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48),
DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
DDB_ID(DDVID, 0x0012, DDVID, 0x0042, ddb_ci),
DDB_ID(DDVID, 0x0013, DDVID, 0x0043, ddb_ci_s2_pro),
DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
DDB_ID(DDVID, 0x0201, DDVID, 0x0002, ddb_mod),
DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_octopus_net),
/* in case sub-ids got deleted in flash */
DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0005, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0006, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0007, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0013, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
{0}
};
MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
static struct pci_driver ddb_pci_driver = {
.name = "ddbridge",
.id_table = ddb_id_tbl,
.probe = ddb_probe,
.remove = ddb_remove,
};
static __init int module_init_ddbridge(void)
{
int stat = -1;
pr_info("Digital Devices PCIE bridge driver "
DDBRIDGE_VERSION
", Copyright (C) 2010-15 Digital Devices GmbH\n");
if (ddb_class_create() < 0)
return -1;
ddb_wq = create_workqueue("ddbridge");
if (ddb_wq == NULL)
goto exit1;
stat = pci_register_driver(&ddb_pci_driver);
if (stat < 0)
goto exit2;
return stat;
exit2:
destroy_workqueue(ddb_wq);
exit1:
ddb_class_destroy();
return stat;
}
static __exit void module_exit_ddbridge(void)
{
pci_unregister_driver(&ddb_pci_driver);
destroy_workqueue(ddb_wq);
ddb_class_destroy();
}
module_init(module_init_ddbridge);
module_exit(module_exit_ddbridge);
MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
MODULE_LICENSE("GPL");
MODULE_VERSION(DDBRIDGE_VERSION);

711
ddbridge/ddbridge.h Normal file
View File

@ -0,0 +1,711 @@
/*
* ddbridge.h: Digital Devices PCIe bridge driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
* Ralph Metzler <rmetzler@digitaldevices.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#ifndef _DDBRIDGE_H_
#define _DDBRIDGE_H_
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define __devexit
#define __devinit
#define __devinitconst
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/io.h>
#include <linux/pci.h>
//#include <linux/pci_ids.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/swab.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/completion.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/dvb/ca.h>
#include <linux/socket.h>
#include <linux/device.h>
#include <linux/io.h>
#include "dvb_netstream.h"
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_ringbuffer.h"
#include "dvb_ca_en50221.h"
#include "dvb_net.h"
#include "tda18271c2dd.h"
#include "stv6110x.h"
#include "stv090x.h"
#include "lnbh24.h"
#include "drxk.h"
#include "stv0367dd.h"
#include "tda18212dd.h"
#include "cxd2843.h"
#include "cxd2099.h"
#include "stv0910.h"
#include "stv6111.h"
#include "lnbh25.h"
#include "mxl5xx.h"
#define DDB_MAX_I2C 16
#define DDB_MAX_PORT 16
#define DDB_MAX_INPUT 44
#define DDB_MAX_OUTPUT 10
#define DDB_MAX_LINK 4
#define DDB_LINK_SHIFT 28
#define DDB_LINK_TAG(_x) (_x << DDB_LINK_SHIFT)
struct ddb_regset {
u32 base;
u32 num;
u32 size;
};
struct ddb_ports {
u32 base;
u32 num;
u32 size;
};
struct ddb_regmap {
struct ddb_ports *bc;
struct ddb_regset *i2c;
struct ddb_regset *i2c_buf;
struct ddb_regset *dma;
struct ddb_regset *dma_buf;
struct ddb_regset *input;
struct ddb_regset *output;
struct ddb_regset *channel;
struct ddb_regset *ci;
struct ddb_regset *pid_filter;
struct ddb_regset *ns;
struct ddb_regset *gtl;
};
struct ddb_ids {
u16 vendor;
u16 device;
u16 subvendor;
u16 subdevice;
u32 hwid;
u32 regmapid;
u32 devid;
u32 mac;
};
struct ddb_info {
int type;
#define DDB_NONE 0
#define DDB_OCTOPUS 1
#define DDB_OCTOPUS_CI 2
#define DDB_MOD 3
#define DDB_OCTONET 4
#define DDB_OCTOPUS_MAX 5
char *name;
u32 i2c_mask;
u8 port_num;
u8 led_num;
u8 fan_num;
u8 temp_num;
u8 temp_bus;
u8 board_control;
u8 ns_num;
u8 mdio_num;
u8 con_clock;
struct ddb_regmap *regmap;
};
/* DMA_SIZE MUST be smaller than 256k and
MUST be divisible by 188 and 128 !!! */
#define DMA_MAX_BUFS 32 /* hardware table limit */
#define INPUT_DMA_BUFS 8
#define INPUT_DMA_SIZE (128*47*21)
#define INPUT_DMA_IRQ_DIV 1
#define OUTPUT_DMA_BUFS 8
#define OUTPUT_DMA_SIZE (128*47*21)
#define OUTPUT_DMA_IRQ_DIV 1
struct ddb;
struct ddb_port;
struct ddb_dma {
void *io;
u32 nr;
dma_addr_t pbuf[DMA_MAX_BUFS];
u8 *vbuf[DMA_MAX_BUFS];
u32 num;
u32 size;
u32 div;
u32 bufreg;
#ifdef DDB_USE_WORK
struct work_struct work;
#else
struct tasklet_struct tasklet;
#endif
spinlock_t lock;
wait_queue_head_t wq;
int running;
u32 stat;
u32 ctrl;
u32 cbuf;
u32 coff;
};
struct ddb_dvb {
struct dvb_adapter *adap;
int adap_registered;
struct dvb_device *dev;
struct dvb_frontend *fe;
struct dvb_frontend *fe2;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvbnet;
struct dvb_netstream dvbns;
struct dmx_frontend hw_frontend;
struct dmx_frontend mem_frontend;
int users;
u32 attached;
u8 input;
fe_sec_tone_mode_t tone;
fe_sec_voltage_t voltage;
int (*i2c_gate_ctrl)(struct dvb_frontend *, int);
int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
int (*set_input)(struct dvb_frontend *fe, int input);
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
};
struct ddb_ci {
struct dvb_ca_en50221 en;
struct ddb_port *port;
u32 nr;
struct mutex lock;
};
struct ddb_io {
struct ddb_port *port;
u32 nr;
struct ddb_dma *dma;
struct ddb_io *redo;
struct ddb_io *redi;
};
#define ddb_output ddb_io
#define ddb_input ddb_io
struct ddb_i2c {
struct ddb *dev;
u32 nr;
u32 regs;
u32 link;
struct i2c_adapter adap;
u32 rbuf;
u32 wbuf;
u32 bsize;
struct completion completion;
};
struct ddb_port {
struct ddb *dev;
u32 nr;
u32 pnr;
u32 regs;
u32 lnr;
struct ddb_i2c *i2c;
struct mutex i2c_gate_lock;
u32 class;
#define DDB_PORT_NONE 0
#define DDB_PORT_CI 1
#define DDB_PORT_TUNER 2
#define DDB_PORT_LOOP 3
#define DDB_PORT_MOD 4
char *name;
u32 type;
#define DDB_TUNER_NONE 0
#define DDB_TUNER_DVBS_ST 1
#define DDB_TUNER_DVBS_ST_AA 2
#define DDB_TUNER_DVBCT_TR 3
#define DDB_TUNER_DVBCT_ST 4
#define DDB_CI_INTERNAL 5
#define DDB_CI_EXTERNAL_SONY 6
#define DDB_TUNER_DVBCT2_SONY_P 7
#define DDB_TUNER_DVBC2T2_SONY_P 8
#define DDB_TUNER_ISDBT_SONY_P 9
#define DDB_TUNER_DVBS_STV0910_P 10
#define DDB_TUNER_MXL5XX 11
#define DDB_CI_EXTERNAL_XO2 12
#define DDB_CI_EXTERNAL_XO2_B 13
#define DDB_TUNER_XO2 16
#define DDB_TUNER_DVBS_STV0910 16
#define DDB_TUNER_DVBCT2_SONY 17
#define DDB_TUNER_ISDBT_SONY 18
#define DDB_TUNER_DVBC2T2_SONY 19
#define DDB_TUNER_ATSC_ST 20
#define DDB_TUNER_DVBC2T2_ST 21
struct ddb_input *input[2];
struct ddb_output *output;
struct dvb_ca_en50221 *en;
struct ddb_dvb dvb[2];
u32 gap;
u32 obr;
u8 creg;
};
struct mod_base {
u32 frequency;
u32 flat_start;
u32 flat_end;
};
struct mod_state {
u32 modulation;
u64 obitrate;
u64 ibitrate;
u32 pcr_correction;
u32 rate_inc;
u32 Control;
u32 State;
u32 StateCounter;
s32 LastPCRAdjust;
s32 PCRAdjustSum;
s32 InPacketsSum;
s32 OutPacketsSum;
s64 PCRIncrement;
s64 PCRDecrement;
s32 PCRRunningCorr;
u32 OutOverflowPacketCount;
u32 InOverflowPacketCount;
u32 LastOutPacketCount;
u32 LastInPacketCount;
u64 LastOutPackets;
u64 LastInPackets;
u32 MinInputPackets;
};
#define CM_STARTUP_DELAY 2
#define CM_AVERAGE 20
#define CM_GAIN 10
#define HW_LSB_SHIFT 12
#define HW_LSB_MASK 0x1000
#define CM_IDLE 0
#define CM_STARTUP 1
#define CM_ADJUST 2
#define TS_CAPTURE_LEN (4096)
/* net streaming hardware block */
#define DDB_NS_MAX 15
struct ddb_ns {
struct ddb_input *input;
int nr;
struct ddb_input *fe;
u32 rtcp_udplen;
u32 rtcp_len;
u32 ts_offset;
u32 udplen;
u8 p[512];
};
struct ddb_lnb {
struct mutex lock;
u32 tone;
fe_sec_voltage_t oldvoltage[4];
u32 voltage[4];
u32 voltages;
u32 fmode;
u32 setmode;
};
struct ddb_link {
struct ddb *dev;
struct ddb_info *info;
u32 nr;
u32 regs;
spinlock_t lock;
struct mutex flash_mutex;
struct ddb_lnb lnb;
struct tasklet_struct tasklet;
};
struct ddb {
struct pci_dev *pdev;
struct platform_device *pfdev;
struct device *dev;
struct ddb_ids ids;
int msi;
struct workqueue_struct *wq;
u32 has_dma;
u32 has_ns;
struct ddb_link link[DDB_MAX_LINK];
unsigned char *regs;
u32 regs_len;
u32 port_num;
struct ddb_port port[DDB_MAX_PORT];
u32 i2c_num;
struct ddb_i2c i2c[DDB_MAX_I2C];
struct ddb_input input[DDB_MAX_INPUT];
struct ddb_output output[DDB_MAX_OUTPUT];
struct dvb_adapter adap[DDB_MAX_INPUT];
struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT];
void (*handler[128])(unsigned long);
unsigned long handler_data[128];
struct device *ddb_dev;
u32 ddb_dev_users;
u32 nr;
u8 iobuf[1028];
u8 leds;
u32 ts_irq;
u32 i2c_irq;
int ns_num;
struct ddb_ns ns[DDB_NS_MAX];
int vlan;
struct mutex mutex;
struct dvb_device *nsd_dev;
u8 tsbuf[TS_CAPTURE_LEN];
struct mod_base mod_base;
struct mod_state mod[10];
};
static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
{
writeb(val, (char *) (dev->regs + (adr)));
}
static inline u32 ddbreadb(struct ddb *dev, u32 adr)
{
return readb((char *) (dev->regs + (adr)));
}
static inline void ddbwritel0(struct ddb_link *link, u32 val, u32 adr)
{
writel(val, (char *) (link->dev->regs + (adr)));
}
static inline u32 ddbreadl0(struct ddb_link *link, u32 adr)
{
return readl((char *) (link->dev->regs + (adr)));
}
#if 0
static inline void gtlw(struct ddb_link *link)
{
u32 count = 0;
static u32 max = 0;
while (1 & ddbreadl0(link, link->regs + 0x10)) {
if (++count == 1024) {
printk("LTO\n");
break;
}
}
if (count > max) {
max = count;
printk("TO=%u\n", max);
}
if (ddbreadl0(link, link->regs + 0x10) & 0x8000)
printk("link error\n");
}
#else
static inline void gtlw(struct ddb_link *link)
{
while (1 & ddbreadl0(link, link->regs + 0x10));
}
#endif
static u32 ddblreadl(struct ddb_link *link, u32 adr)
{
if (unlikely(link->nr)) {
unsigned long flags;
u32 val;
spin_lock_irqsave(&link->lock, flags);
gtlw(link);
ddbwritel0(link, adr & 0xfffc, link->regs + 0x14);
ddbwritel0(link, 3, link->regs + 0x10);
gtlw(link);
val = ddbreadl0(link, link->regs + 0x1c);
spin_unlock_irqrestore(&link->lock, flags);
return val;
}
return readl((char *) (link->dev->regs + (adr)));
}
static void ddblwritel(struct ddb_link *link, u32 val, u32 adr)
{
if (unlikely(link->nr)) {
unsigned long flags;
spin_lock_irqsave(&link->lock, flags);
gtlw(link);
ddbwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
ddbwritel0(link, val, link->regs + 0x18);
ddbwritel0(link, 1, link->regs + 0x10);
spin_unlock_irqrestore(&link->lock, flags);
return;
}
writel(val, (char *) (link->dev->regs + (adr)));
}
static u32 ddbreadl(struct ddb *dev, u32 adr)
{
if (unlikely(adr & 0xf0000000)) {
unsigned long flags;
u32 val, l = (adr >> DDB_LINK_SHIFT);
struct ddb_link *link = &dev->link[l];
spin_lock_irqsave(&link->lock, flags);
gtlw(link);
ddbwritel0(link, adr & 0xfffc, link->regs + 0x14);
ddbwritel0(link, 3, link->regs + 0x10);
gtlw(link);
val = ddbreadl0(link, link->regs + 0x1c);
spin_unlock_irqrestore(&link->lock, flags);
return val;
}
return readl((char *) (dev->regs + (adr)));
}
static void ddbwritel(struct ddb *dev, u32 val, u32 adr)
{
if (unlikely(adr & 0xf0000000)) {
unsigned long flags;
u32 l = (adr >> DDB_LINK_SHIFT);
struct ddb_link *link = &dev->link[l];
spin_lock_irqsave(&link->lock, flags);
gtlw(link);
ddbwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
ddbwritel0(link, val, link->regs + 0x18);
ddbwritel0(link, 1, link->regs + 0x10);
spin_unlock_irqrestore(&link->lock, flags);
return;
}
writel(val, (char *) (dev->regs + (adr)));
}
static void gtlcpyto(struct ddb *dev, u32 adr, const u8 *buf,
unsigned int count)
{
u32 val = 0, p = adr;
u32 aa = p & 3;
if (aa) {
while (p & 3 && count) {
val >>= 8;
val |= *buf << 24;
p++;
buf++;
count--;
}
ddbwritel(dev, val, adr);
}
while (count >= 4) {
val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
ddbwritel(dev, val, p);
p += 4;
buf += 4;
count -= 4;
}
if (count) {
val = buf[0];
if (count > 1)
val |= buf[1] << 8;
if (count > 2)
val |= buf[2] << 16;
ddbwritel(dev, val, p);
}
}
static void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count)
{
u32 val = 0, p = adr;
u32 a = p & 3;
if (a) {
val = ddbreadl(dev, p) >> (8 * a);
while (p & 3 && count) {
*buf = val & 0xff;
val >>= 8;
p++;
buf++;
count--;
}
}
while (count >= 4) {
val = ddbreadl(dev, p);
buf[0] = val & 0xff;
buf[1] = (val >> 8) & 0xff;
buf[2] = (val >> 16) & 0xff;
buf[3] = (val >> 24) & 0xff;
p += 4;
buf += 4;
count -= 4;
}
if (count) {
val = ddbreadl(dev, p);
buf[0] = val & 0xff;
if (count > 1)
buf[1] = (val >> 8) & 0xff;
if (count > 2)
buf[2] = (val >> 16) & 0xff;
}
}
static void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count)
{
if (unlikely(adr & 0xf0000000))
return gtlcpyto(dev, adr, src, count);
return memcpy_toio((char *) (dev->regs + adr), src, count);
}
static void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count)
{
if (unlikely(adr & 0xf0000000))
return gtlcpyfrom(dev, dst, adr, count);
return memcpy_fromio(dst, (char *) (dev->regs + adr), count);
}
#if 0
#define ddbcpyto(_dev, _adr, _src, _count) \
memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count))
#define ddbcpyfrom(_dev, _dst, _adr, _count) \
memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count))
#endif
#define ddbmemset(_dev, _adr, _val, _count) \
memset_io((char *) (_dev->regs + (_adr)), (_val), (_count))
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
#define dd_uint8 u8
#define dd_uint16 u16
#define dd_int16 s16
#define dd_uint32 u32
#define dd_int32 s32
#define dd_uint64 u64
#define dd_int64 s64
#define DDMOD_FLASH_START 0x1000
struct DDMOD_FLASH_DS {
dd_uint32 Symbolrate; /* kSymbols/s */
dd_uint32 DACFrequency; /* kHz */
dd_uint16 FrequencyResolution; /* kHz */
dd_uint16 IQTableLength;
dd_uint16 FrequencyFactor;
dd_int16 PhaseCorr; /* TBD */
dd_uint32 Control2;
dd_uint16 PostScaleI;
dd_uint16 PostScaleQ;
dd_uint16 PreScale;
dd_int16 EQTap[11];
dd_uint16 FlatStart;
dd_uint16 FlatEnd;
dd_uint32 FlashOffsetPrecalculatedIQTables; /* 0 = none */
dd_uint8 Reserved[28];
};
struct DDMOD_FLASH {
dd_uint32 Magic;
dd_uint16 Version;
dd_uint16 DataSets;
dd_uint16 VCORefFrequency; /* MHz */
dd_uint16 VCO1Frequency; /* MHz */
dd_uint16 VCO2Frequency; /* MHz */
dd_uint16 DACAux1; /* TBD */
dd_uint16 DACAux2; /* TBD */
dd_uint8 Reserved1[238];
struct DDMOD_FLASH_DS DataSet[1];
};
#define DDMOD_FLASH_MAGIC 0x5F564d5F
int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
int ddbridge_mod_init(struct ddb *dev);
void ddbridge_mod_output_stop(struct ddb_output *output);
void ddbridge_mod_output_start(struct ddb_output *output);
void ddbridge_mod_rate_handler(unsigned long data);
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
#define DDBRIDGE_VERSION "0.9.19"
#endif

260
ddbridge/octonet.c Normal file
View File

@ -0,0 +1,260 @@
/*
* octonet.c: Digital Devices network tuner driver
*
* Copyright (C) 2012-15 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include "ddbridge.h"
#include "ddbridge-regs.h"
#include <asm-generic/pci-dma-compat.h>
static int adapter_alloc = 3;
module_param(adapter_alloc, int, 0444);
MODULE_PARM_DESC(adapter_alloc,
"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
#include "ddbridge-core.c"
static struct ddb_regset octopus_i2c = {
.base = 0x80,
.num = 0x04,
.size = 0x20,
};
static struct ddb_regset octopus_i2c_buf = {
.base = 0x1000,
.num = 0x04,
.size = 0x200,
};
static struct ddb_regmap octopus_net_map = {
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
};
static struct ddb_regset octopus_gtl = {
.base = 0x180,
.num = 0x01,
.size = 0x20,
};
static struct ddb_regmap octopus_net_gtl = {
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.gtl = &octopus_gtl,
};
static struct ddb_info ddb_octonet = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet network DVB adapter",
.regmap = &octopus_net_map,
.port_num = 4,
.i2c_mask = 0x0f,
.ns_num = 12,
.mdio_num = 1,
};
static struct ddb_info ddb_octonet_jse = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet network DVB adapter JSE",
.regmap = &octopus_net_map,
.port_num = 4,
.i2c_mask = 0x0f,
.ns_num = 15,
.mdio_num = 1,
};
static struct ddb_info ddb_octonet_gtl = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet GTL",
.regmap = &octopus_net_gtl,
.port_num = 4,
.i2c_mask = 0x05,
.ns_num = 12,
.mdio_num = 1,
.con_clock = 1,
};
static struct ddb_info ddb_octonet_tbd = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet",
.regmap = &octopus_net_map,
};
static void octonet_unmap(struct ddb *dev)
{
if (dev->regs)
iounmap(dev->regs);
vfree(dev);
}
static int __exit octonet_remove(struct platform_device *pdev)
{
struct ddb *dev;
dev = platform_get_drvdata(pdev);
ddb_nsd_detach(dev);
ddb_ports_detach(dev);
ddb_i2c_release(dev);
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0, INTERRUPT_ENABLE);
free_irq(platform_get_irq(dev->pfdev, 0), dev);
ddb_ports_release(dev);
ddb_device_destroy(dev);
octonet_unmap(dev);
platform_set_drvdata(pdev, 0);
return 0;
}
static int __init octonet_probe(struct platform_device *pdev)
{
struct ddb *dev;
struct resource *regs;
int irq;
int i;
dev = vzalloc(sizeof(struct ddb));
if (!dev)
return -ENOMEM;
platform_set_drvdata(pdev, dev);
dev->dev = &pdev->dev;
dev->pfdev = pdev;
mutex_init(&dev->mutex);
regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0);
if (!regs)
return -ENXIO;
dev->regs_len = (regs->end - regs->start) + 1;
dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n",
(u32) regs->start, (u32) dev->regs_len);
dev->regs = ioremap(regs->start, dev->regs_len);
if (!dev->regs) {
dev_err(dev->dev, "ioremap failed\n");
return -ENOMEM;
}
dev->ids.hwid = ddbreadl(dev, 0);
dev->ids.regmapid = ddbreadl(dev, 4);
dev->ids.devid = ddbreadl(dev, 8);
dev->ids.mac = ddbreadl(dev, 12);
dev->ids.vendor = dev->ids.devid & 0xffff;
dev->ids.device = dev->ids.devid >> 16;
dev->ids.subvendor = dev->ids.devid & 0xffff;
dev->ids.subdevice = dev->ids.devid >> 16;
dev->link[0].dev = dev;
if (dev->ids.devid == 0x0300dd01)
dev->link[0].info = &ddb_octonet;
else if (dev->ids.devid == 0x0301dd01)
dev->link[0].info = &ddb_octonet_jse;
else if (dev->ids.devid == 0x0307dd01)
dev->link[0].info = &ddb_octonet_gtl;
else
dev->link[0].info = &ddb_octonet_tbd;
pr_info("HW %08x REGMAP %08x\n", dev->ids.hwid, dev->ids.regmapid);
pr_info("MAC %08x DEVID %08x\n", dev->ids.mac, dev->ids.devid);
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS);
for (i = 0; i < 16; i++)
ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i));
usleep_range(5000, 6000);
irq = platform_get_irq(dev->pfdev, 0);
if (irq < 0)
goto fail;
if (request_irq(irq, irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"octonet-dvb", (void *) dev) < 0)
goto fail;
ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
if (ddb_init(dev) == 0)
return 0;
fail:
dev_err(dev->dev, "fail\n");
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0, INTERRUPT_ENABLE);
octonet_unmap(dev);
platform_set_drvdata(pdev, 0);
return -1;
}
#ifdef CONFIG_OF
static const struct of_device_id octonet_dt_ids[] = {
{ .compatible = "digitaldevices,octonet-dvb" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, octonet_dt_ids);
#endif
static struct platform_driver octonet_driver = {
.remove = __exit_p(octonet_remove),
.probe = octonet_probe,
.driver = {
.name = "octonet-dvb",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = of_match_ptr(octonet_dt_ids),
#endif
},
};
static __init int init_octonet(void)
{
int res;
pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION
", Copyright (C) 2010-14 Digital Devices GmbH\n");
res = ddb_class_create();
if (res)
return res;
res = platform_driver_probe(&octonet_driver, octonet_probe);
if (res) {
ddb_class_destroy();
return res;
}
return 0;
}
static __exit void exit_octonet(void)
{
platform_driver_unregister(&octonet_driver);
ddb_class_destroy();
}
module_init(init_octonet);
module_exit(exit_octonet);
MODULE_DESCRIPTION("GPL");
MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung GbR");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.6");

5
ddip/Kbuild Normal file
View File

@ -0,0 +1,5 @@
obj-$(CONFIG_DVB_DDBRIDGE) += ddip.o
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
EXTRA_CFLAGS += -Idrivers/media/common/tuners
NOSTDINC_FLAGS += -I$(SUBDIRS)/frontends -I$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core

18
ddip/Makefile Normal file
View File

@ -0,0 +1,18 @@
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
MODDEFS := CONFIG_DVB_DDIP=m
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MODDEFS) modules
dep:
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
install: all
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules_install
clean:
rm -rf */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*

24
ddip/ddip.c Normal file
View File

@ -0,0 +1,24 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
static __init int init_ddip(void)
{
return 0;
}
static __exit void exit_ddip(void)
{
}
module_init(init_ddip);
module_exit(exit_ddip);
MODULE_DESCRIPTION("GPL");
MODULE_AUTHOR("Metzler Brothers Systementwicklung");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");

7
docs/adapter_alloc Normal file
View File

@ -0,0 +1,7 @@
The module parameter adapter_alloc lets you choose how adapter names are allocated.
0 = one adapter per io if modules are present
1 = one adapter for each tab on which a module was detected
2 = one per tab even if no modules were detected
3 = one adapter for all devices of one card

31
docs/ci Normal file
View File

@ -0,0 +1,31 @@
The caX device associated with a CI device behaves just like any other
caX interface. You usually use it through a library like libdvben50221
which is part of the dvb-apps package available at linuxtv.org.
But contrary to other hardware where the CI module is physically placed
in the data path between the the demod and PCIe bridge, in the Digital
Devices cards the CI module is separate hardware.
So, you have to feed data to the CI module by writing to the secX
(in later kernel ci0) device and read it back from the same secX device.
The advantage is that the CI module can be used with any data coming from
any frontend or file. The disadvantage is that the user application has to
write/read the data to/from the module by itself.
The sample application apps/cit.c shows how to pipe a stream through
the CI interface. In its ouput it will show discontinuities. Those should
only occur at the start of the program (due to old packets inside the CI
interface hardware and the CI module itself) and when a CI module is
inserted or removed.
Since some users have problems using standard software which cannot use
the CI interface in this way, there is now the redirect feature which allows
you to tell the driver to automatically pass the data coming from one
demod through a CI before offering it through the normal demux/dvr interface.
But note that this is a kludge to support old software until they can
use the new interface.
See docs/redirect for more info.

29
docs/modulator Normal file
View File

@ -0,0 +1,29 @@
Modulator channels will automatically be enabled if you redirect data
from a demodulator to it.
E.g._:
first demod on bridge 0 TAB1, modulator on bridge 1.
echo "00 10" > /sys/class/ddbridge/ddbridge0/redirect
Currently it is fixed to QAM256. Controls will be added later.
Rate control is experimental and PCR correction also not
implemented yet. So, depending on the reception device
there can be disturbances in playback.
It is now also possible to chain redirects.
E.g., demod and modulator as above, CI on bridge 0 TAB 2:
echo "00 01" > /sys/class/ddbridge/ddbridge0/redirect
echo "02 10" > /sys/class/ddbridge/ddbridge0/redirect
The stream is also still available at the demux device
belonging to the demod devices.
Now write and start an application (not provided) that
talks to the CI to decrypt the desired services.
For testing one can use a standard application that
supports decryption. Additionally to seeing the
decoded service on the PC it will then also be streamed
into cable by the modulator.

89
docs/octopusnet Normal file
View File

@ -0,0 +1,89 @@
OctopusNet
----------
Hardware:
- SoC Atmel SAM9G45 400MHz ARM 926
64 MB DRAM
256 MB NAND flash
- FPGA Lattice ECP3 17
data flash
- 5 port switch Marvell 88E6175R
The FPGA is connected to the memory bus of the G45 and maps control registers into the memory space
of the G45. This is mainly to control the data flow on the FPGA. Only minimal data can be transferred
(e.g. single sections). Transport streams cannot be transferred to the G45 this way!
The FPGA can receive up to 8 TS from up to 4 Duo-Flex cards. You can also can alternatively connect
CI modules to port 2 and 3 (TAP 3 and 4).
The FPGA is also connected to one of the ports of the gigabit switch.
There are up to 12 channels. Each channel can select one input TS, which is then passed through
a PID filter (8192 bit array) and sent to the switch as a UDP/RTP stream.
The G45 is connected to another port of the switch (but only with 100 MBit)
Booting:
The G45 does not boot from the NAND flash but from the dataflash connected to the FPGA. The G45
does not support error correction for the boot sector and NAND with zero error boot pages
is no longer easily available.
Newer Atmel SoCs support 4-bit error correction in boot ROM but not the G45.
So, the G45 boot looks like this:
- Run a minimal boot rom mapped by the FPGA.
- Boot rom loads a modified bootstrap via SPI (provided via FPGA ports) from the dataflash.
- Bootstrap loads u-boot via SPI from dataflash.
- u-boot boots Linux ...
If you remove jumper XX, boot rom is disabled and the G45 will boot from NAND flash like this:
- Internal G45 boot rom bootstrap from NAND flash.
- Bootstrap boots u-boot from NAND flash
- u-boot boots Linux ...
This is just a fall-back since page 0 can contain errors which cannot be corrected by the G45 boot ROM
and the bootstrap code which loads u-boot also does not contain error correction.
- SPI dataflash
0x000000 - 0x003fff FPGA config data
0x004000 - 0x005fff G45 bootstrap
0x010000 - 0x0affff FPGA bitstream
0x0b0000 - 0x15ffff G45 u-boot
0x160000 - 0x1fefff FPGA golden image
0x1ff000 - 0x1fffff FPGA jump to golden image
- NAND flash 256MB, block size 128K (0x20000)
0x00000000 - 0x0001ffff G45 bootstrap (fallback bootstrap if SPI corrupted, pull jumper to use)
0x00020000 - 0x0007ffff G45 u-boot (fallback u-boot if SPI corrupted)
0x00080000 - 0x0009ffff spare (e.g. for bigger u-boot)
0x000a0000 - 0x000bffff G45 u-boot environment
0x000c0000 - 0x000dffff G45 u-boot redundant environment
0x000e0000 - 0x000fffff spare
0x00100000 - 0x01ffffff G45 Linux recovery
0x02000000 - 0x0fffffff Linux UBI

104
docs/octopusnet.multicast Normal file
View File

@ -0,0 +1,104 @@
Multicast
---------
Multicast setup supports 2 file formats.
1) Simple variant for the avarage home user
2) More parameters for the expert.
The file is in csv (comma seperated values) format, which can be created with any plain text editor or imported/exported
to/from Microsoft Office Excel or OpenOffice Scalc. With Excel or Scalc care for character set (should be UTF-8) and
column formats is required. First line is contain then column headers.
Standard parameters
-------------------
TITLE: Stream Title
REQUEST: SAT>IP tune request string without the pid parameter. Exact format depends on frontend (DVB-S,DVB-T ..)
use "-" to stream another program from the previous full entry (tuner sharing)
PIDS: Pid list. Must start with a P, the values separated with a colon. "Pall" streams the whole transponder.
(The P is there to ensure Excel or Scalc don't do some fancy format detection, like time conversion)
LANPORTS: Empty or a list with colon separated lan ports starting with L, "Lall" = all ports.
If empty, the stream will only be activated when subscribed with an IGMPv3 request. It will also
only be active on the lan ports through which an IGMPv3 request for the stream has benn received.
(For details how IGMPv3 works look up the relevant RFCs.)
If not empty the stream will be preactived on the listed lan ports (and permanently using bandwidth!).
It still can be subscribed with IGMPv3 on the other ports.
TITLE,REQUEST,PIDS,LANPORTS
"Das Erste","?freq=346&msys=dvbc&sr=6900&mtype=256qam","P0:100:101:104:102:103:106",""
"Bayerisches FS Nord","-","P0:500:201:204:202:203:206",""
"hr-fernsehen","-","P0:300:301:304:302:303",""
"SWR Fernsehen BW","-","P0:800:801:804:802:803:806",""
"WDR Köln","-","P0:600:601:604:602:603",""
"ZDF","?freq=370&msys=dvbc&sr=6900&mtype=256qam","P0:100:110:130:120:121:122:125",""
"ZDF HD","-","P0:6100:6110:6130:6120:6121:6122:6123",""
"zdf neo","-","P0:650:660:680:670:671:672:675",""
"zdf kultur","-","P0:1100:1110:1130:1120:1121:1122:1125",""
"ZDFInfo","-","P0:600:610:630:620:621:622:625",""
"KiKA","-","P0:300:310:330:320:321:325","L3:4:5"
"3sat","-","P0:200:210:230:220:221:222:225",""
Expert parameters:
------------------
PROTO: Protocol, must be "RTP" or "UDP". If you don't know what this means use "RTP".
IP: Multicast IP address, recommended range 239.5.0.0 - 239.126.255.255, see notes below
about selecting a multicast IP address.
PORT: Destination port. If you don't know what this means set it to 6670
TTL: Time to live used in the IP headers. If you don't know what this means set it to 5.
TITLE,REQUEST,PIDS,PROTO,IP,PORT,TTL,LANPORTS
"Das Erste","?freq=346&msys=dvbc&sr=6900&mtype=256qam","P0:100:101:104:102:103:106","UDP","239.7.7.100",1234,7,""
"Bayerisches FS Nord","-","P0:500:201:204:202:203:206","UDP","239.7.7.101",1234,7,""
"hr-fernsehen","-","P0:300:301:304:302:303","UDP","239.7.7.102",1234,7,""
"SWR Fernsehen BW","-","P0:800:801:804:802:803:806","UDP","239.7.7.103",1234,7,""
"WDR Köln","-","P0:600:601:604:602:603","UDP","239.7.7.104",1234,7,""
"ZDF","?freq=370&msys=dvbc&sr=6900&mtype=256qam","P0:100:110:130:120:121:122:125","UDP","239.7.8.100",1234,7,""
"ZDF HD","-","P0:6100:6110:6130:6120:6121:6122:6123","UDP","239.7.8.101",1234,7,""
"zdf neo","-","P0:650:660:680:670:671:672:675","UDP","239.7.8.102",1234,7,""
"zdf kultur","-","P0:1100:1110:1130:1120:1121:1122:1125","UDP","239.7.8.103",1234,7,""
"ZDFInfo","-","P0:600:610:630:620:621:622:625","UDP","239.7.8.104",1234,7,""
"KiKA","-","P0:300:310:330:320:321:325","UDP","239.7.8.105",1234,7,"L3:4:5"
"3sat","-","P0:200:210:230:220:221:222:225","UDP","239.7.8.106",1234,7,""
Selecting a multicast IP address.
---------------------------------
It is obvious that there should be no conflicts with other services (like UPnP, Windows network ...)
which also use Multicast for communication and advertisments.
For media streaming usually an IP in the range 239.0.0.0 - 239.255.255.255 is used and
will usually only conflict with other media sources. But this is not the whole truth!
The complete IP multicast range is 224.0.0.0 - 255.255.255.254, that is 536870911 different values.
But there are only 8388608 different Ethernet MAC addresses allocated for IPv4 multicast. That
means a lot of collisions. For example, 239.0.0.22 uses the same MAC address as 224.0.0.22 (IGMP).
This means that 239.0.0.22 can't be blocked in an Ethernet switch without breaking IGMP.
An IP from the range 239.5.0.0 - 239.126.255.255 does not collide with most documented
services, and should be safe to use in most situations and the benefit from IGMPv3
snooping Ethernet switches.
Multicast and WLAN
------------------
As there is no real support for it (due to encryption) Multicast over WLAN will not work very well.
Therefor it should be avoided to send a out a multicast stream on a lan port there a WLAN router
is connected (at least when the WLAN router is configured as LAN-WLAN bridge).
As long there are free streams on the OctopusNet a RTSP player (including WLAN connected players)
can request any service from a configured multicast source.
For exmaple RTSP://<onetip>/stream=2?pids=0,300,310,330,320,321,325 will request KIKA
as single cast stream from the above example. This is possible even if the entry for KIKA
is removed from the multicast setup.
(the above sample has no free streams left, but it should be clear what is meant)

9
docs/octopusnetpro Normal file
View File

@ -0,0 +1,9 @@
- NAND flash
0x00000000 - 0x0025ffff U-boot
0x00260000 - 0x0027ffff ENV
0x00300000 - 0x00ffffff Linux image
0x01000000 - 0x01ffffff Linux recovery
0x02000000 - 0x1fffffff Linux UBI

30
docs/redirect Normal file
View File

@ -0,0 +1,30 @@
NOTE: This is an unsupported hack so that legacy software works
with the hardware!
To properly pass data through a CI CAM you should read
the TS from a dvr device and write it to a ci device
in user space!
Redirection of TS streams through CI modules is now supported
through /sys/class/ddbridge/ddbridge0/redirect.
It only works with cards based on the ddbridge PCIe bridge, not
with nGene based cards.
It is set up in such a way that you can write "AB CD" to
a "redirect" attribute and data from input B of card A is then piped through
port D (meaning TAB (D+1) which uses output D and input 2*D for CI io)
of card C and then shows up in the demux device belonging to
input B (input (B&1) of TAB (B/2+1)) of card A.
E.g.:
echo "00 01" > /sys/class/ddbridge/ddbridge0/redirect
will pipe input 0 of card 0 through CI at port 1 (TAB 2) of card 0.
Redirection should only be done right after loading the driver
(or booting if the driver is built-in) and before using the
devices in any way.
adapter_alloc=3 is rcommended when using redirect
The ci device will then show up in the same adapter directory and most
software will then assume it belongs to the frontend in the same directory.

12
dvb-core/Makefile Normal file
View File

@ -0,0 +1,12 @@
#
# Makefile for the kernel DVB device drivers.
#
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o dvb_math.o dvb_netstream.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET
NOSTDINC_FLAGS += -I$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core

241
dvb-core/demux.h Normal file
View File

@ -0,0 +1,241 @@
/*
* demux.h
*
* Copyright (c) 2002 Convergence GmbH
*
* based on code:
* Copyright (c) 2000 Nokia Research Center
* Tampere, FINLAND
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __DEMUX_H
#define __DEMUX_H
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/dvb/dmx.h>
/*--------------------------------------------------------------------------*/
/* Common definitions */
/*--------------------------------------------------------------------------*/
/*
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
*/
#ifndef DMX_MAX_FILTER_SIZE
#define DMX_MAX_FILTER_SIZE 18
#endif
/*
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
*/
#ifndef DMX_MAX_SECTION_SIZE
#define DMX_MAX_SECTION_SIZE 4096
#endif
#ifndef DMX_MAX_SECFEED_SIZE
#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
#endif
/*
* enum dmx_success: Success codes for the Demux Callback API.
*/
enum dmx_success {
DMX_OK = 0, /* Received Ok */
DMX_LENGTH_ERROR, /* Incorrect length */
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
DMX_CRC_ERROR, /* Incorrect CRC */
DMX_FRAME_ERROR, /* Frame alignment error */
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
DMX_MISSED_ERROR /* Receiver missed packet */
} ;
/*--------------------------------------------------------------------------*/
/* TS packet reception */
/*--------------------------------------------------------------------------*/
/* TS filter type for set() */
#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */
#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS
payload (<=184 bytes per packet) to callback */
#define TS_DECODER 4 /* send stream to built-in decoder (if present) */
#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
the demux device, not to the dvr device */
struct dmx_ts_feed {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux *parent; /* Back-pointer */
void *priv; /* Pointer to private data of the API client */
int (*set) (struct dmx_ts_feed *feed,
u16 pid,
int type,
enum dmx_ts_pes pes_type,
size_t circular_buffer_size,
struct timespec timeout);
int (*start_filtering) (struct dmx_ts_feed* feed);
int (*stop_filtering) (struct dmx_ts_feed* feed);
};
/*--------------------------------------------------------------------------*/
/* Section reception */
/*--------------------------------------------------------------------------*/
struct dmx_section_filter {
u8 filter_value [DMX_MAX_FILTER_SIZE];
u8 filter_mask [DMX_MAX_FILTER_SIZE];
u8 filter_mode [DMX_MAX_FILTER_SIZE];
struct dmx_section_feed* parent; /* Back-pointer */
void* priv; /* Pointer to private data of the API client */
};
struct dmx_section_feed {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux* parent; /* Back-pointer */
void* priv; /* Pointer to private data of the API client */
int check_crc;
u32 crc_val;
u8 *secbuf;
u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
u16 secbufp, seclen, tsfeedp;
int (*set) (struct dmx_section_feed* feed,
u16 pid,
size_t circular_buffer_size,
int check_crc);
int (*allocate_filter) (struct dmx_section_feed* feed,
struct dmx_section_filter** filter);
int (*release_filter) (struct dmx_section_feed* feed,
struct dmx_section_filter* filter);
int (*start_filtering) (struct dmx_section_feed* feed);
int (*stop_filtering) (struct dmx_section_feed* feed);
};
/*--------------------------------------------------------------------------*/
/* Callback functions */
/*--------------------------------------------------------------------------*/
typedef int (*dmx_ts_cb) ( const u8 * buffer1,
size_t buffer1_length,
const u8 * buffer2,
size_t buffer2_length,
struct dmx_ts_feed* source,
enum dmx_success success);
typedef int (*dmx_section_cb) ( const u8 * buffer1,
size_t buffer1_len,
const u8 * buffer2,
size_t buffer2_len,
struct dmx_section_filter * source,
enum dmx_success success);
/*--------------------------------------------------------------------------*/
/* DVB Front-End */
/*--------------------------------------------------------------------------*/
enum dmx_frontend_source {
DMX_MEMORY_FE,
DMX_FRONTEND_0,
DMX_FRONTEND_1,
DMX_FRONTEND_2,
DMX_FRONTEND_3,
DMX_STREAM_0, /* external stream input, e.g. LVDS */
DMX_STREAM_1,
DMX_STREAM_2,
DMX_STREAM_3
};
struct dmx_frontend {
struct list_head connectivity_list; /* List of front-ends that can
be connected to a particular
demux */
enum dmx_frontend_source source;
};
/*--------------------------------------------------------------------------*/
/* MPEG-2 TS Demux */
/*--------------------------------------------------------------------------*/
/*
* Flags OR'ed in the capabilities field of struct dmx_demux.
*/
#define DMX_TS_FILTERING 1
#define DMX_PES_FILTERING 2
#define DMX_SECTION_FILTERING 4
#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
#define DMX_CRC_CHECKING 16
#define DMX_TS_DESCRAMBLING 32
/*
* Demux resource type identifier.
*/
/*
* DMX_FE_ENTRY(): Casts elements in the list of registered
* front-ends from the generic type struct list_head
* to the type * struct dmx_frontend
*.
*/
#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
struct dmx_demux {
u32 capabilities; /* Bitfield of capability flags */
struct dmx_frontend* frontend; /* Front-end connected to the demux */
void* priv; /* Pointer to private data of the API client */
int (*open) (struct dmx_demux* demux);
int (*close) (struct dmx_demux* demux);
int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
int (*allocate_ts_feed) (struct dmx_demux* demux,
struct dmx_ts_feed** feed,
dmx_ts_cb callback);
int (*release_ts_feed) (struct dmx_demux* demux,
struct dmx_ts_feed* feed);
int (*allocate_section_feed) (struct dmx_demux* demux,
struct dmx_section_feed** feed,
dmx_section_cb callback);
int (*release_section_feed) (struct dmx_demux* demux,
struct dmx_section_feed* feed);
int (*add_frontend) (struct dmx_demux* demux,
struct dmx_frontend* frontend);
int (*remove_frontend) (struct dmx_demux* demux,
struct dmx_frontend* frontend);
struct list_head* (*get_frontends) (struct dmx_demux* demux);
int (*connect_frontend) (struct dmx_demux* demux,
struct dmx_frontend* frontend);
int (*disconnect_frontend) (struct dmx_demux* demux);
int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
int (*get_stc) (struct dmx_demux* demux, unsigned int num,
u64 *stc, unsigned int *base);
};
#endif /* #ifndef __DEMUX_H */

1272
dvb-core/dmxdev.c Normal file

File diff suppressed because it is too large Load Diff

119
dvb-core/dmxdev.h Normal file
View File

@ -0,0 +1,119 @@
/*
* dmxdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _DMXDEV_H_
#define _DMXDEV_H_
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/dvb/dmx.h>
#include "dvbdev.h"
#include "demux.h"
#include "dvb_ringbuffer.h"
enum dmxdev_type {
DMXDEV_TYPE_NONE,
DMXDEV_TYPE_SEC,
DMXDEV_TYPE_PES,
};
enum dmxdev_state {
DMXDEV_STATE_FREE,
DMXDEV_STATE_ALLOCATED,
DMXDEV_STATE_SET,
DMXDEV_STATE_GO,
DMXDEV_STATE_DONE,
DMXDEV_STATE_TIMEDOUT
};
struct dmxdev_feed {
u16 pid;
struct dmx_ts_feed *ts;
struct list_head next;
};
struct dmxdev_filter {
union {
struct dmx_section_filter *sec;
} filter;
union {
/* list of TS and PES feeds (struct dmxdev_feed) */
struct list_head ts;
struct dmx_section_feed *sec;
} feed;
union {
struct dmx_sct_filter_params sec;
struct dmx_pes_filter_params pes;
} params;
enum dmxdev_type type;
enum dmxdev_state state;
struct dmxdev *dev;
struct dvb_ringbuffer buffer;
struct mutex mutex;
/* only for sections */
struct timer_list timer;
int todo;
u8 secheader[3];
};
struct dmxdev {
struct dvb_device *dvbdev;
struct dvb_device *dvr_dvbdev;
struct dmxdev_filter *filter;
struct dmx_demux *demux;
int filternum;
int capabilities;
unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe;
struct dvb_ringbuffer dvr_buffer;
#define DVR_BUFFER_SIZE (10*188*1024)
struct mutex mutex;
spinlock_t lock;
};
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
void dvb_dmxdev_release(struct dmxdev *dmxdev);
#endif /* _DMXDEV_H_ */

1814
dvb-core/dvb_ca_en50221.c Normal file

File diff suppressed because it is too large Load Diff

140
dvb-core/dvb_ca_en50221.h Normal file
View File

@ -0,0 +1,140 @@
/*
* dvb_ca.h: generic DVB functions for EN50221 CA interfaces
*
* Copyright (C) 2004 Andrew de Quincey
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DVB_CA_EN50221_H_
#define _DVB_CA_EN50221_H_
#include <linux/list.h>
#include <linux/dvb/ca.h>
#include "dvbdev.h"
#define DVB_CA_EN50221_POLL_CAM_PRESENT 1
#define DVB_CA_EN50221_POLL_CAM_CHANGED 2
#define DVB_CA_EN50221_POLL_CAM_READY 4
#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1
#define DVB_CA_EN50221_FLAG_IRQ_FR 2
#define DVB_CA_EN50221_FLAG_IRQ_DA 4
#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0
#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1
/* Structure describing a CA interface */
struct dvb_ca_en50221 {
/* the module owning this structure */
struct module* owner;
/* NOTE: the read_*, write_* and poll_slot_status functions will be
* called for different slots concurrently and need to use locks where
* and if appropriate. There will be no concurrent access to one slot.
*/
/* functions for accessing attribute memory on the CAM */
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
/* functions for accessing the control interface on the CAM */
int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
/* functions for readin/writing data */
int (*read_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
int (*write_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
/* Functions for controlling slots */
int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
/*
* Poll slot status.
* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
*/
int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
/* private data, used by caller */
void* data;
/* Opaque data used by the dvb_ca core. Do not modify! */
void* private;
};
/* ******************************************************************************** */
/* Functions for reporting IRQ events */
/**
* A CAMCHANGE IRQ has occurred.
*
* @param ca CA instance.
* @param slot Slot concerned.
* @param change_type One of the DVB_CA_CAMCHANGE_* values
*/
void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
/**
* A CAMREADY IRQ has occurred.
*
* @param ca CA instance.
* @param slot Slot concerned.
*/
void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
/**
* An FR or a DA IRQ has occurred.
*
* @param ca CA instance.
* @param slot Slot concerned.
*/
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
/* ******************************************************************************** */
/* Initialisation/shutdown functions */
/**
* Initialise a new DVB CA device.
*
* @param dvb_adapter DVB adapter to attach the new CA device to.
* @param ca The dvb_ca instance.
* @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
* @param slot_count Number of slots supported.
*
* @return 0 on success, nonzero on failure
*/
extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
/**
* Release a DVB CA device.
*
* @param ca The associated dvb_ca instance.
*/
extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
#endif

1320
dvb-core/dvb_demux.c Normal file

File diff suppressed because it is too large Load Diff

151
dvb-core/dvb_demux.h Normal file
View File

@ -0,0 +1,151 @@
/*
* dvb_demux.h: DVB kernel demux API
*
* Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include "demux.h"
#define DMX_TYPE_TS 0
#define DMX_TYPE_SEC 1
#define DMX_TYPE_PES 2
#define DMX_STATE_FREE 0
#define DMX_STATE_ALLOCATED 1
#define DMX_STATE_SET 2
#define DMX_STATE_READY 3
#define DMX_STATE_GO 4
#define DVB_DEMUX_MASK_MAX 18
#define MAX_PID 0x1fff
#define SPEED_PKTS_INTERVAL 50000
struct dvb_demux_filter {
struct dmx_section_filter filter;
u8 maskandmode[DMX_MAX_FILTER_SIZE];
u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
int doneq;
struct dvb_demux_filter *next;
struct dvb_demux_feed *feed;
int index;
int state;
int type;
u16 hw_handle;
struct timer_list timer;
};
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
struct dvb_demux_feed {
union {
struct dmx_ts_feed ts;
struct dmx_section_feed sec;
} feed;
union {
dmx_ts_cb ts;
dmx_section_cb sec;
} cb;
struct dvb_demux *demux;
void *priv;
int type;
int state;
u16 pid;
u8 *buffer;
int buffer_size;
struct timespec timeout;
struct dvb_demux_filter *filter;
int ts_type;
enum dmx_ts_pes pes_type;
int cc;
int pusi_seen; /* prevents feeding of garbage from previous section */
u16 peslen;
struct list_head list_head;
unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
};
struct dvb_demux {
struct dmx_demux dmx;
void *priv;
int filternum;
int feednum;
int (*start_feed)(struct dvb_demux_feed *feed);
int (*stop_feed)(struct dvb_demux_feed *feed);
int (*write_to_decoder)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
u32 (*check_crc32)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
int users;
#define MAX_DVB_DEMUX_USERS 10
struct dvb_demux_filter *filter;
struct dvb_demux_feed *feed;
struct list_head frontend_list;
struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
u16 pids[DMX_PES_OTHER];
int playing;
int recording;
#define DMX_MAX_PID 0x2000
struct list_head feed_list;
u8 tsbuf[204];
int tsbufp;
struct mutex mutex;
spinlock_t lock;
uint8_t *cnt_storage; /* for TS continuity check */
struct timespec speed_last_time; /* for TS speed check */
uint32_t speed_pkts_cnt; /* for TS speed check */
};
int dvb_dmx_init(struct dvb_demux *dvbdemux);
void dvb_dmx_release(struct dvb_demux *dvbdemux);
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
size_t count);
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
size_t count);
#endif /* _DVB_DEMUX_H_ */

603
dvb-core/dvb_filter.c Normal file
View File

@ -0,0 +1,603 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include "dvb_filter.h"
#if 0
static unsigned int bitrates[3][16] =
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
#endif
static u32 freq[4] = {480, 441, 320, 0};
static unsigned int ac3_bitrates[32] =
{32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
0,0,0,0,0,0,0,0,0,0,0,0,0};
static u32 ac3_frames[3][32] =
{{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
{69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
{96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
#if 0
static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
void (*pes_write)(u8 *buf, int count, void *data),
void *priv)
{
dvb_filter_ipack_init(pa, IPACKS, pes_write);
dvb_filter_ipack_init(pv, IPACKS, pes_write);
pa->pid = pida;
pv->pid = pidv;
pa->data = priv;
pv->data = priv;
}
#endif
#if 0
static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
{
u8 off = 0;
if (!buf || !p ){
printk("NULL POINTER IDIOT\n");
return;
}
if (buf[1]&PAY_START) {
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
p->plength = p->found-6;
p->found = 0;
send_ipack(p);
dvb_filter_ipack_reset(p);
}
}
if (buf[3] & ADAPT_FIELD) { // adaptation field?
off = buf[4] + 1;
if (off+4 > 187) return;
}
dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
}
#endif
#if 0
/* needs 5 byte input, returns picture coding type*/
static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
{
u8 pct;
if (pr) printk( "Pic header: ");
pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
pct = ( headr[1] >> 2 ) & 0x07;
pic->picture_coding_type[field] = pct;
if (pr) {
switch(pct){
case I_FRAME:
printk( " I-FRAME");
break;
case B_FRAME:
printk( " B-FRAME");
break;
case P_FRAME:
printk( " P-FRAME");
break;
}
}
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
return pct;
}
#endif
#if 0
/* needs 4 byte input */
static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
{
if (pr) printk("GOP header: ");
pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
if ( ( headr[3] & 0x40 ) != 0 ){
pic->closed_gop = 1;
} else {
pic->closed_gop = 0;
}
if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
} else {
pic->broken_link = 0;
}
if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
}
#endif
#if 0
/* needs 8 byte input */
static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
{
int sw;
int form = -1;
if (pr) printk("Reading sequence header\n");
vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]);
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
case 1:
if (pr)
printk("Videostream: ASPECT: 1:1");
vi->aspect_ratio = 100;
break;
case 2:
if (pr)
printk("Videostream: ASPECT: 4:3");
vi->aspect_ratio = 133;
break;
case 3:
if (pr)
printk("Videostream: ASPECT: 16:9");
vi->aspect_ratio = 177;
break;
case 4:
if (pr)
printk("Videostream: ASPECT: 2.21:1");
vi->aspect_ratio = 221;
break;
case 5 ... 15:
if (pr)
printk("Videostream: ASPECT: reserved");
vi->aspect_ratio = 0;
break;
default:
vi->aspect_ratio = 0;
return -1;
}
if (pr)
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
sw = (int)(headr[3]&0x0F);
switch ( sw ) {
case 1:
if (pr)
printk(" FRate: 23.976 fps");
vi->framerate = 23976;
form = -1;
break;
case 2:
if (pr)
printk(" FRate: 24 fps");
vi->framerate = 24000;
form = -1;
break;
case 3:
if (pr)
printk(" FRate: 25 fps");
vi->framerate = 25000;
form = VIDEO_MODE_PAL;
break;
case 4:
if (pr)
printk(" FRate: 29.97 fps");
vi->framerate = 29970;
form = VIDEO_MODE_NTSC;
break;
case 5:
if (pr)
printk(" FRate: 30 fps");
vi->framerate = 30000;
form = VIDEO_MODE_NTSC;
break;
case 6:
if (pr)
printk(" FRate: 50 fps");
vi->framerate = 50000;
form = VIDEO_MODE_PAL;
break;
case 7:
if (pr)
printk(" FRate: 60 fps");
vi->framerate = 60000;
form = VIDEO_MODE_NTSC;
break;
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
if (pr){
printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
printk("\n");
}
vi->video_format = form;
return 0;
}
#endif
#if 0
static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
while (found < 4 && c+4 < count){
u8 *b;
b = mbuf+c;
if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
&& b[3] == 0xb3) found = 4;
else {
c++;
}
}
if (! found) return -1;
c += 4;
if (c+12 >= count) return -1;
headr = mbuf+c;
if (read_sequence_header(headr, vi, pr) < 0) return -1;
vi->off = c-4;
return 0;
}
#endif
#if 0
static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
int fr = 0;
while (found < 2 && c < count){
u8 b[2];
memcpy( b, mbuf+c, 2);
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
found = 2;
else {
c++;
}
}
if (!found) return -1;
if (c+3 >= count) return -1;
headr = mbuf+c;
ai->layer = (headr[1] & 0x06) >> 1;
if (pr)
printk("Audiostream: Layer: %d", 4-ai->layer);
ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
if (pr){
if (ai->bit_rate == 0)
printk(" Bit rate: free");
else if (ai->bit_rate == 0xf)
printk(" BRate: reserved");
else
printk(" BRate: %d kb/s", ai->bit_rate/1000);
}
fr = (headr[2] & 0x0c ) >> 2;
ai->frequency = freq[fr]*100;
if (pr){
if (ai->frequency == 3)
printk(" Freq: reserved\n");
else
printk(" Freq: %d kHz\n",ai->frequency);
}
ai->off = c;
return 0;
}
#endif
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
u8 frame = 0;
int fr = 0;
while ( !found && c < count){
u8 *b = mbuf+c;
if ( b[0] == 0x0b && b[1] == 0x77 )
found = 1;
else {
c++;
}
}
if (!found) return -1;
if (pr)
printk("Audiostream: AC3");
ai->off = c;
if (c+5 >= count) return -1;
ai->layer = 0; // 0 for AC3
headr = mbuf+c+2;
frame = (headr[2]&0x3f);
ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
if (pr)
printk(" BRate: %d kb/s", (int) ai->bit_rate/1000);
ai->frequency = (headr[2] & 0xc0 ) >> 6;
fr = (headr[2] & 0xc0 ) >> 6;
ai->frequency = freq[fr]*100;
if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency);
ai->framesize = ac3_frames[fr][frame >> 1];
if ((frame & 1) && (fr == 1)) ai->framesize++;
ai->framesize = ai->framesize << 1;
if (pr) printk (" Framesize %d\n",(int) ai->framesize);
return 0;
}
EXPORT_SYMBOL(dvb_filter_get_ac3info);
#if 0
static u8 *skip_pes_header(u8 **bufp)
{
u8 *inbuf = *bufp;
u8 *buf = inbuf;
u8 *pts = NULL;
int skip = 0;
static const int mpeg1_skip_table[16] = {
1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
break;
}
if ((*buf & 0xc0) == 0x40)
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
buf += mpeg1_skip_table [*buf >> 4];
}
*bufp = buf;
return pts;
}
#endif
#if 0
static void initialize_quant_matrix( u32 *matrix )
{
int i;
matrix[0] = 0x08101013;
matrix[1] = 0x10131616;
matrix[2] = 0x16161616;
matrix[3] = 0x1a181a1b;
matrix[4] = 0x1b1b1a1a;
matrix[5] = 0x1a1a1b1b;
matrix[6] = 0x1b1d1d1d;
matrix[7] = 0x2222221d;
matrix[8] = 0x1d1d1b1b;
matrix[9] = 0x1d1d2020;
matrix[10] = 0x22222526;
matrix[11] = 0x25232322;
matrix[12] = 0x23262628;
matrix[13] = 0x28283030;
matrix[14] = 0x2e2e3838;
matrix[15] = 0x3a454553;
for ( i = 16 ; i < 32 ; i++ )
matrix[i] = 0x10101010;
}
#endif
#if 0
static void initialize_mpg_picture(struct mpg_picture *pic)
{
int i;
/* set MPEG1 */
pic->mpeg1_flag = 1;
pic->profile_and_level = 0x4A ; /* MP@LL */
pic->progressive_sequence = 1;
pic->low_delay = 0;
pic->sequence_display_extension_flag = 0;
for ( i = 0 ; i < 4 ; i++ ){
pic->frame_centre_horizontal_offset[i] = 0;
pic->frame_centre_vertical_offset[i] = 0;
}
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->picture_display_extension_flag[0] = 0;
pic->picture_display_extension_flag[1] = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
}
#endif
#if 0
static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
{
int16_t last_h_offset;
int16_t last_v_offset;
int16_t *p_h_offset;
int16_t *p_v_offset;
if ( pic->mpeg1_flag ){
pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
pic->top_field_first = 0;
pic->repeat_first_field = 0;
pic->progressive_frame = 1;
pic->picture_coding_parameter = 0x000010;
}
/* Reset flag */
pic->picture_display_extension_flag[field_type] = 0;
last_h_offset = pic->last_frame_centre_horizontal_offset;
last_v_offset = pic->last_frame_centre_vertical_offset;
if ( field_type == FIRST_FIELD ){
p_h_offset = pic->frame_centre_horizontal_offset;
p_v_offset = pic->frame_centre_vertical_offset;
*p_h_offset = last_h_offset;
*(p_h_offset + 1) = last_h_offset;
*(p_h_offset + 2) = last_h_offset;
*p_v_offset = last_v_offset;
*(p_v_offset + 1) = last_v_offset;
*(p_v_offset + 2) = last_v_offset;
} else {
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
}
}
#endif
#if 0
static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
{
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
| ( INIT_VERTICAL_SIZE << 8 )
| ( INIT_ASPECT_RATIO << 4 )
| ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
pic->vinfo.vertical_size
= INIT_DISP_VERTICAL_SIZE;
pic->picture_display_extension_flag[field_type]
= 0;
pic->pts_flag[field_type] = 0;
pic->sequence_gop_header = 0;
pic->picture_header = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
pic->sequence_display_extension_flag = 0;
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->channel = chan;
}
#endif
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv)
{
unsigned char *buf=p2ts->buf;
buf[0]=0x47;
buf[1]=(pid>>8);
buf[2]=pid&0xff;
p2ts->cc=0;
p2ts->cb=cb;
p2ts->priv=priv;
}
EXPORT_SYMBOL(dvb_filter_pes2ts_init);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start)
{
unsigned char *buf=p2ts->buf;
int ret=0, rest;
//len=6+((pes[4]<<8)|pes[5]);
if (payload_start)
buf[1]|=0x40;
else
buf[1]&=~0x40;
while (len>=184) {
buf[3]=0x10|((p2ts->cc++)&0x0f);
memcpy(buf+4, pes, 184);
if ((ret=p2ts->cb(p2ts->priv, buf)))
return ret;
len-=184; pes+=184;
buf[1]&=~0x40;
}
if (!len)
return 0;
buf[3]=0x30|((p2ts->cc++)&0x0f);
rest=183-len;
if (rest) {
buf[5]=0x00;
if (rest-1)
memset(buf+6, 0xff, rest-1);
}
buf[4]=rest;
memcpy(buf+5+rest, pes, len);
return p2ts->cb(p2ts->priv, buf);
}
EXPORT_SYMBOL(dvb_filter_pes2ts);

246
dvb-core/dvb_filter.h Normal file
View File

@ -0,0 +1,246 @@
/*
* dvb_filter.h
*
* Copyright (C) 2003 Convergence GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DVB_FILTER_H_
#define _DVB_FILTER_H_
#include <linux/slab.h>
#include "demux.h"
typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
struct dvb_filter_pes2ts {
unsigned char buf[188];
unsigned char cc;
dvb_filter_pes2ts_cb_t *cb;
void *priv;
};
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start);
#define PROG_STREAM_MAP 0xBC
#define PRIVATE_STREAM1 0xBD
#define PADDING_STREAM 0xBE
#define PRIVATE_STREAM2 0xBF
#define AUDIO_STREAM_S 0xC0
#define AUDIO_STREAM_E 0xDF
#define VIDEO_STREAM_S 0xE0
#define VIDEO_STREAM_E 0xEF
#define ECM_STREAM 0xF0
#define EMM_STREAM 0xF1
#define DSM_CC_STREAM 0xF2
#define ISO13522_STREAM 0xF3
#define PROG_STREAM_DIR 0xFF
#define DVB_PICTURE_START 0x00
#define DVB_USER_START 0xb2
#define DVB_SEQUENCE_HEADER 0xb3
#define DVB_SEQUENCE_ERROR 0xb4
#define DVB_EXTENSION_START 0xb5
#define DVB_SEQUENCE_END 0xb7
#define DVB_GOP_START 0xb8
#define DVB_EXCEPT_SLICE 0xb0
#define SEQUENCE_EXTENSION 0x01
#define SEQUENCE_DISPLAY_EXTENSION 0x02
#define PICTURE_CODING_EXTENSION 0x08
#define QUANT_MATRIX_EXTENSION 0x03
#define PICTURE_DISPLAY_EXTENSION 0x07
#define I_FRAME 0x01
#define B_FRAME 0x02
#define P_FRAME 0x03
/* Initialize sequence_data */
#define INIT_HORIZONTAL_SIZE 720
#define INIT_VERTICAL_SIZE 576
#define INIT_ASPECT_RATIO 0x02
#define INIT_FRAME_RATE 0x03
#define INIT_DISP_HORIZONTAL_SIZE 540
#define INIT_DISP_VERTICAL_SIZE 576
//flags2
#define PTS_DTS_FLAGS 0xC0
#define ESCR_FLAG 0x20
#define ES_RATE_FLAG 0x10
#define DSM_TRICK_FLAG 0x08
#define ADD_CPY_FLAG 0x04
#define PES_CRC_FLAG 0x02
#define PES_EXT_FLAG 0x01
//pts_dts flags
#define PTS_ONLY 0x80
#define PTS_DTS 0xC0
#define TS_SIZE 188
#define TRANS_ERROR 0x80
#define PAY_START 0x40
#define TRANS_PRIO 0x20
#define PID_MASK_HI 0x1F
//flags
#define TRANS_SCRMBL1 0x80
#define TRANS_SCRMBL2 0x40
#define ADAPT_FIELD 0x20
#define PAYLOAD 0x10
#define COUNT_MASK 0x0F
// adaptation flags
#define DISCON_IND 0x80
#define RAND_ACC_IND 0x40
#define ES_PRI_IND 0x20
#define PCR_FLAG 0x10
#define OPCR_FLAG 0x08
#define SPLICE_FLAG 0x04
#define TRANS_PRIV 0x02
#define ADAP_EXT_FLAG 0x01
// adaptation extension flags
#define LTW_FLAG 0x80
#define PIECE_RATE 0x40
#define SEAM_SPLICE 0x20
#define MAX_PLENGTH 0xFFFF
#define MMAX_PLENGTH (256*MAX_PLENGTH)
#ifndef IPACKS
#define IPACKS 2048
#endif
struct ipack {
int size;
int found;
u8 *buf;
u8 cid;
u32 plength;
u8 plen[2];
u8 flag1;
u8 flag2;
u8 hlength;
u8 pts[5];
u16 *pid;
int mpeg;
u8 check;
int which;
int done;
void *data;
void (*func)(u8 *buf, int size, void *priv);
int count;
int repack_subids;
};
struct dvb_video_info {
u32 horizontal_size;
u32 vertical_size;
u32 aspect_ratio;
u32 framerate;
u32 video_format;
u32 bit_rate;
u32 comp_bit_rate;
u32 vbv_buffer_size;
s16 vbv_delay;
u32 CSPF;
u32 off;
};
#define OFF_SIZE 4
#define FIRST_FIELD 0
#define SECOND_FIELD 1
#define VIDEO_FRAME_PICTURE 0x03
struct mpg_picture {
int channel;
struct dvb_video_info vinfo;
u32 *sequence_gop_header;
u32 *picture_header;
s32 time_code;
int low_delay;
int closed_gop;
int broken_link;
int sequence_header_flag;
int gop_flag;
int sequence_end_flag;
u8 profile_and_level;
s32 picture_coding_parameter;
u32 matrix[32];
s8 matrix_change_flag;
u8 picture_header_parameter;
/* bit 0 - 2: bwd f code
bit 3 : fpb vector
bit 4 - 6: fwd f code
bit 7 : fpf vector */
int mpeg1_flag;
int progressive_sequence;
int sequence_display_extension_flag;
u32 sequence_header_data;
s16 last_frame_centre_horizontal_offset;
s16 last_frame_centre_vertical_offset;
u32 pts[2]; /* [0] 1st field, [1] 2nd field */
int top_field_first;
int repeat_first_field;
int progressive_frame;
int bank;
int forward_bank;
int backward_bank;
int compress;
s16 frame_centre_horizontal_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
s16 frame_centre_vertical_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
s16 temporal_reference[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_coding_type[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_structure[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_display_extension_flag[2];
/* [0] 1st field, [1] 2nd field */
/* picture_display_extenion() 0:no 1:exit*/
s8 pts_flag[2];
/* [0] 1st field, [1] 2nd field */
};
struct dvb_audio_info {
int layer;
u32 bit_rate;
u32 frequency;
u32 mode;
u32 mode_extension ;
u32 emphasis;
u32 framesize;
u32 off;
};
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
#endif

2713
dvb-core/dvb_frontend.c Normal file

File diff suppressed because it is too large Load Diff

441
dvb-core/dvb_frontend.h Normal file
View File

@ -0,0 +1,441 @@
/*
* dvb_frontend.h
*
* Copyright (C) 2001 convergence integrated media GmbH
* Copyright (C) 2004 convergence GmbH
*
* Written by Ralph Metzler
* Overhauled by Holger Waechtler
* Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _DVB_FRONTEND_H_
#define _DVB_FRONTEND_H_
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/dvb/frontend.h>
#include "dvbdev.h"
/*
* Maximum number of Delivery systems per frontend. It
* should be smaller or equal to 32
*/
#define MAX_DELSYS 8
struct dvb_frontend_tune_settings {
int min_delay_ms;
int step_size;
int max_drift;
};
struct dvb_frontend;
struct dvb_tuner_info {
char name[128];
u32 frequency_min;
u32 frequency_max;
u32 frequency_step;
u32 bandwidth_min;
u32 bandwidth_max;
u32 bandwidth_step;
};
struct analog_parameters {
unsigned int frequency;
unsigned int mode;
unsigned int audmode;
u64 std;
};
enum dvbfe_modcod {
DVBFE_MODCOD_DUMMY_PLFRAME = 0,
DVBFE_MODCOD_QPSK_1_4,
DVBFE_MODCOD_QPSK_1_3,
DVBFE_MODCOD_QPSK_2_5,
DVBFE_MODCOD_QPSK_1_2,
DVBFE_MODCOD_QPSK_3_5,
DVBFE_MODCOD_QPSK_2_3,
DVBFE_MODCOD_QPSK_3_4,
DVBFE_MODCOD_QPSK_4_5,
DVBFE_MODCOD_QPSK_5_6,
DVBFE_MODCOD_QPSK_8_9,
DVBFE_MODCOD_QPSK_9_10,
DVBFE_MODCOD_8PSK_3_5,
DVBFE_MODCOD_8PSK_2_3,
DVBFE_MODCOD_8PSK_3_4,
DVBFE_MODCOD_8PSK_5_6,
DVBFE_MODCOD_8PSK_8_9,
DVBFE_MODCOD_8PSK_9_10,
DVBFE_MODCOD_16APSK_2_3,
DVBFE_MODCOD_16APSK_3_4,
DVBFE_MODCOD_16APSK_4_5,
DVBFE_MODCOD_16APSK_5_6,
DVBFE_MODCOD_16APSK_8_9,
DVBFE_MODCOD_16APSK_9_10,
DVBFE_MODCOD_32APSK_3_4,
DVBFE_MODCOD_32APSK_4_5,
DVBFE_MODCOD_32APSK_5_6,
DVBFE_MODCOD_32APSK_8_9,
DVBFE_MODCOD_32APSK_9_10,
DVBFE_MODCOD_RESERVED_1,
DVBFE_MODCOD_BPSK_1_3,
DVBFE_MODCOD_BPSK_1_4,
DVBFE_MODCOD_RESERVED_2
};
enum tuner_param {
DVBFE_TUNER_FREQUENCY = (1 << 0),
DVBFE_TUNER_TUNERSTEP = (1 << 1),
DVBFE_TUNER_IFFREQ = (1 << 2),
DVBFE_TUNER_BANDWIDTH = (1 << 3),
DVBFE_TUNER_REFCLOCK = (1 << 4),
DVBFE_TUNER_IQSENSE = (1 << 5),
DVBFE_TUNER_DUMMY = (1 << 31)
};
/*
* ALGO_HW: (Hardware Algorithm)
* ----------------------------------------------------------------
* Devices that support this algorithm do everything in hardware
* and no software support is needed to handle them.
* Requesting these devices to LOCK is the only thing required,
* device is supposed to do everything in the hardware.
*
* ALGO_SW: (Software Algorithm)
* ----------------------------------------------------------------
* These are dumb devices, that require software to do everything
*
* ALGO_CUSTOM: (Customizable Agorithm)
* ----------------------------------------------------------------
* Devices having this algorithm can be customized to have specific
* algorithms in the frontend driver, rather than simply doing a
* software zig-zag. In this case the zigzag maybe hardware assisted
* or it maybe completely done in hardware. In all cases, usage of
* this algorithm, in conjunction with the search and track
* callbacks, utilizes the driver specific algorithm.
*
* ALGO_RECOVERY: (Recovery Algorithm)
* ----------------------------------------------------------------
* These devices have AUTO recovery capabilities from LOCK failure
*/
enum dvbfe_algo {
DVBFE_ALGO_HW = (1 << 0),
DVBFE_ALGO_SW = (1 << 1),
DVBFE_ALGO_CUSTOM = (1 << 2),
DVBFE_ALGO_RECOVERY = (1 << 31)
};
struct tuner_state {
u32 frequency;
u32 tunerstep;
u32 ifreq;
u32 bandwidth;
u32 iqsense;
u32 refclock;
};
/*
* search callback possible return status
*
* DVBFE_ALGO_SEARCH_SUCCESS
* The frontend search algorithm completed and returned successfully
*
* DVBFE_ALGO_SEARCH_ASLEEP
* The frontend search algorithm is sleeping
*
* DVBFE_ALGO_SEARCH_FAILED
* The frontend search for a signal failed
*
* DVBFE_ALGO_SEARCH_INVALID
* The frontend search algorith was probably supplied with invalid
* parameters and the search is an invalid one
*
* DVBFE_ALGO_SEARCH_ERROR
* The frontend search algorithm failed due to some error
*
* DVBFE_ALGO_SEARCH_AGAIN
* The frontend search algorithm was requested to search again
*/
enum dvbfe_search {
DVBFE_ALGO_SEARCH_SUCCESS = (1 << 0),
DVBFE_ALGO_SEARCH_ASLEEP = (1 << 1),
DVBFE_ALGO_SEARCH_FAILED = (1 << 2),
DVBFE_ALGO_SEARCH_INVALID = (1 << 3),
DVBFE_ALGO_SEARCH_AGAIN = (1 << 4),
DVBFE_ALGO_SEARCH_ERROR = (1 << 31),
};
struct dvb_tuner_ops {
struct dvb_tuner_info info;
int (*release)(struct dvb_frontend *fe);
int (*init)(struct dvb_frontend *fe);
int (*sleep)(struct dvb_frontend *fe);
/** This is for simple PLLs - set all parameters in one go. */
int (*set_params)(struct dvb_frontend *fe);
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
/** This is to allow setting tuner-specific configs */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
#define TUNER_STATUS_LOCKED 1
#define TUNER_STATUS_STEREO 2
int (*get_status)(struct dvb_frontend *fe, u32 *status);
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
/** These are provided separately from set_params in order to facilitate silicon
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
/*
* These are provided separately from set_params in order to facilitate silicon
* tuners which require sophisticated tuning loops, controlling each parameter separately.
*/
int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
};
struct analog_demod_info {
char *name;
};
struct analog_demod_ops {
struct analog_demod_info info;
void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);
int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
/** This is to allow setting tuner-specific configuration */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
};
struct dtv_frontend_properties;
struct dvb_frontend_ops {
struct dvb_frontend_info info;
u8 delsys[MAX_DELSYS];
void (*release)(struct dvb_frontend* fe);
void (*release_sec)(struct dvb_frontend* fe);
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
/* if this is set, it overrides the default swzigzag */
int (*tune)(struct dvb_frontend* fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status);
/* get frontend tuning algorithm from the module */
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend *fe);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
int (*get_frontend)(struct dvb_frontend *fe);
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
int (*read_snr)(struct dvb_frontend* fe, u16* snr);
int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
int (*diseqc_reset_overload)(struct dvb_frontend* fe);
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
int (*set_lna)(struct dvb_frontend *);
int (*set_input)(struct dvb_frontend *, int);
/* These callbacks are for devices that implement their own
* tuning algorithms, rather than a simple swzigzag
*/
enum dvbfe_search (*search)(struct dvb_frontend *fe);
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
u8 xbar[3];
};
#ifdef __DVB_CORE__
#define MAX_EVENT 8
struct dvb_fe_events {
struct dvb_frontend_event events[MAX_EVENT];
int eventw;
int eventr;
int overflow;
wait_queue_head_t wait_queue;
struct mutex mtx;
};
#endif
struct dtv_frontend_properties {
/* Cache State */
u32 state;
u32 frequency;
fe_modulation_t modulation;
fe_sec_voltage_t voltage;
fe_sec_tone_mode_t sectone;
fe_spectral_inversion_t inversion;
fe_code_rate_t fec_inner;
fe_transmit_mode_t transmission_mode;
u32 bandwidth_hz; /* 0 = AUTO */
fe_guard_interval_t guard_interval;
fe_hierarchy_t hierarchy;
u32 symbol_rate;
fe_code_rate_t code_rate_HP;
fe_code_rate_t code_rate_LP;
fe_pilot_t pilot;
fe_rolloff_t rolloff;
fe_delivery_system_t delivery_system;
enum fe_interleaving interleaving;
/* ISDB-T specifics */
u8 isdbt_partial_reception;
u8 isdbt_sb_mode;
u8 isdbt_sb_subchannel;
u32 isdbt_sb_segment_idx;
u32 isdbt_sb_segment_count;
u8 isdbt_layer_enabled;
struct {
u8 segment_count;
fe_code_rate_t fec;
fe_modulation_t modulation;
u8 interleaving;
} layer[3];
/* Multistream specifics */
u32 stream_id;
/* ATSC-MH specifics */
u8 atscmh_fic_ver;
u8 atscmh_parade_id;
u8 atscmh_nog;
u8 atscmh_tnog;
u8 atscmh_sgn;
u8 atscmh_prc;
u8 atscmh_rs_frame_mode;
u8 atscmh_rs_frame_ensemble;
u8 atscmh_rs_code_mode_pri;
u8 atscmh_rs_code_mode_sec;
u8 atscmh_sccc_block_mode;
u8 atscmh_sccc_code_mode_a;
u8 atscmh_sccc_code_mode_b;
u8 atscmh_sccc_code_mode_c;
u8 atscmh_sccc_code_mode_d;
u32 lna;
s32 input;
/* statistics data */
struct dtv_fe_stats strength;
struct dtv_fe_stats cnr;
struct dtv_fe_stats pre_bit_error;
struct dtv_fe_stats pre_bit_count;
struct dtv_fe_stats post_bit_error;
struct dtv_fe_stats post_bit_count;
struct dtv_fe_stats block_error;
struct dtv_fe_stats block_count;
};
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
void *demodulator_priv;
void *tuner_priv;
void *frontend_priv;
void *sec_priv;
void *analog_demod_priv;
struct dtv_frontend_properties dtv_property_cache;
#define DVB_FRONTEND_COMPONENT_TUNER 0
#define DVB_FRONTEND_COMPONENT_DEMOD 1
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
};
extern int dvb_register_frontend(struct dvb_adapter *dvb,
struct dvb_frontend *fe);
extern int dvb_unregister_frontend(struct dvb_frontend *fe);
extern void dvb_frontend_detach(struct dvb_frontend *fe);
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
extern int dvb_frontend_suspend(struct dvb_frontend *fe);
extern int dvb_frontend_resume(struct dvb_frontend *fe);
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
#endif

145
dvb-core/dvb_math.c Normal file
View File

@ -0,0 +1,145 @@
/*
* dvb-math provides some complex fixed-point math
* operations shared between the dvb related stuff
*
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/bug.h>
#include "dvb_math.h"
static const unsigned short logtable[256] = {
0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
};
unsigned int intlog2(u32 value)
{
/**
* returns: log2(value) * 2^24
* wrong result if value = 0 (log2(0) is undefined)
*/
unsigned int msb;
unsigned int logentry;
unsigned int significand;
unsigned int interpolation;
if (unlikely(value == 0)) {
WARN_ON(1);
return 0;
}
/* first detect the msb (count begins at 0) */
msb = fls(value) - 1;
/**
* now we use a logtable after the following method:
*
* log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
* where x = msb and therefore 1 <= y < 2
* first y is determined by shifting the value left
* so that msb is bit 31
* 0x00231f56 -> 0x8C7D5800
* the result is y * 2^31 -> "significand"
* then the highest 9 bits are used for a table lookup
* the highest bit is discarded because it's always set
* the highest nine bits in our example are 100011000
* so we would use the entry 0x18
*/
significand = value << (31 - msb);
logentry = (significand >> 23) & 0xff;
/**
* last step we do is interpolation because of the
* limitations of the log table the error is that part of
* the significand which isn't used for lookup then we
* compute the ratio between the error and the next table entry
* and interpolate it between the log table entry used and the
* next one the biggest error possible is 0x7fffff
* (in our example it's 0x7D5800)
* needed value for next table entry is 0x800000
* so the interpolation is
* (error / 0x800000) * (logtable_next - logtable_current)
* in the implementation the division is moved to the end for
* better accuracy there is also an overflow correction if
* logtable_next is 256
*/
interpolation = ((significand & 0x7fffff) *
((logtable[(logentry + 1) & 0xff] -
logtable[logentry]) & 0xffff)) >> 15;
/* now we return the result */
return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
}
EXPORT_SYMBOL(intlog2);
unsigned int intlog10(u32 value)
{
/**
* returns: log10(value) * 2^24
* wrong result if value = 0 (log10(0) is undefined)
*/
u64 log;
if (unlikely(value == 0)) {
WARN_ON(1);
return 0;
}
log = intlog2(value);
/**
* we use the following method:
* log10(x) = log2(x) * log10(2)
*/
return (log * 646456993) >> 31;
}
EXPORT_SYMBOL(intlog10);

58
dvb-core/dvb_math.h Normal file
View File

@ -0,0 +1,58 @@
/*
* dvb-math provides some complex fixed-point math
* operations shared between the dvb related stuff
*
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DVB_MATH_H
#define __DVB_MATH_H
#include <linux/types.h>
/**
* computes log2 of a value; the result is shifted left by 24 bits
*
* to use rational values you can use the following method:
* intlog2(value) = intlog2(value * 2^x) - x * 2^24
*
* example: intlog2(8) will give 3 << 24 = 3 * 2^24
* example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
* example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
*
* @param value The value (must be != 0)
* @return log2(value) * 2^24
*/
extern unsigned int intlog2(u32 value);
/**
* computes log10 of a value; the result is shifted left by 24 bits
*
* to use rational values you can use the following method:
* intlog10(value) = intlog10(value * 10^x) - x * 2^24
*
* example: intlog10(1000) will give 3 << 24 = 3 * 2^24
* due to the implementation intlog10(1000) might be not exactly 3 * 2^24
*
* look at intlog2 for similar examples
*
* @param value The value (must be != 0)
* @return log10(value) * 2^24
*/
extern unsigned int intlog10(u32 value);
#endif

1547
dvb-core/dvb_net.c Normal file

File diff suppressed because it is too large Load Diff

67
dvb-core/dvb_net.h Normal file
View File

@ -0,0 +1,67 @@
/*
* dvb_net.h
*
* Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _DVB_NET_H_
#define _DVB_NET_H_
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include "dvbdev.h"
#define DVB_NET_DEVICES_MAX 10
#ifdef CONFIG_DVB_NET
struct dvb_net {
struct dvb_device *dvbdev;
struct net_device *device[DVB_NET_DEVICES_MAX];
int state[DVB_NET_DEVICES_MAX];
unsigned int exit:1;
struct dmx_demux *demux;
struct mutex ioctl_mutex;
};
void dvb_net_release(struct dvb_net *);
int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
#else
struct dvb_net {
struct dvb_device *dvbdev;
};
static inline void dvb_net_release(struct dvb_net *dvbnet)
{
}
static inline int dvb_net_init(struct dvb_adapter *adap,
struct dvb_net *dvbnet, struct dmx_demux *dmx)
{
return 0;
}
#endif /* ifdef CONFIG_DVB_NET */
#endif

259
dvb-core/dvb_netstream.c Normal file
View File

@ -0,0 +1,259 @@
/*
* dvb_netstream.c: support for DVB to network streaming hardware
*
* Copyright (C) 2012-2013 Marcus and Ralph Metzler
* for Digital Devices GmbH
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/net.h>
#include "dvb_netstream.h"
static ssize_t ns_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
pr_info("%s\n", __func__);
return 0;
}
static ssize_t ns_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
pr_info("%s\n", __func__);
return 0;
}
static unsigned int ns_poll(struct file *file, poll_table *wait)
{
pr_info("%s\n", __func__);
return 0;
}
static int ns_stop(struct dvbnss *nss)
{
struct dvb_netstream *ns = nss->ns;
mutex_lock(&ns->mutex);
if (nss->running && ns->stop) {
ns->stop(nss);
nss->running = 0;
}
mutex_unlock(&ns->mutex);
return 0;
}
static int ns_release(struct inode *inode, struct file *file)
{
struct dvbnss *nss = file->private_data;
struct dvb_netstream *ns = nss->ns;
ns_stop(nss);
if (ns->free)
ns->free(nss);
mutex_lock(&ns->mutex);
list_del(&nss->nssl);
mutex_unlock(&ns->mutex);
vfree(nss);
return 0;
}
static int ns_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_netstream *ns = dvbdev->priv;
struct dvbnss *nss;
nss = vmalloc(sizeof(*nss));
if (!nss)
return -ENOMEM;
nss->ns = ns;
if (ns->alloc && ns->alloc(nss) < 0) {
vfree(nss);
return -EBUSY;
}
file->private_data = nss;
nss->running = 0;
mutex_lock(&ns->mutex);
list_add(&nss->nssl, &ns->nssl);
mutex_unlock(&ns->mutex);
return 0;
}
static int set_net(struct dvbnss *nss, struct dvb_ns_params *p)
{
return 0;
}
static int do_ioctl(struct file *file, unsigned int cmd, void *parg)
{
struct dvbnss *nss = file->private_data;
struct dvb_netstream *ns = nss->ns;
/*unsigned long arg = (unsigned long) parg;*/
int ret = 0;
switch (cmd) {
case NS_SET_RTCP_MSG:
{
struct dvb_ns_rtcp *rtcpm = parg;
if (ns->set_rtcp_msg)
ret = ns->set_rtcp_msg(nss, rtcpm->msg, rtcpm->len);
break;
}
case NS_SET_NET:
memcpy(&nss->params, parg, sizeof(nss->params));
if (ns->set_net)
ret = ns->set_net(nss);
else
ret = set_net(nss, (struct dvb_ns_params *) parg);
break;
case NS_START:
mutex_lock(&ns->mutex);
if (nss->running) {
ret = -EBUSY;
} else if (ns->start) {
ret = ns->start(nss);
nss->running = 1;
}
mutex_unlock(&ns->mutex);
break;
case NS_STOP:
ns_stop(nss);
break;
case NS_SET_PACKETS:
{
struct dvb_ns_packet *packet = parg;
if (ns->set_ts_packets)
ret = ns->set_ts_packets(nss, packet->buf,
packet->count * 188);
break;
}
case NS_INSERT_PACKETS:
{
u8 count = *(u8 *) parg;
if (ns->insert_ts_packets)
ret = ns->insert_ts_packets(nss, count);
break;
}
case NS_SET_PID:
{
u16 pid = *(u16 *) parg;
u16 byte = (pid & 0x1fff) >> 3;
u8 bit = 1 << (pid & 7);
if (pid & 0x2000) {
if (pid & 0x8000)
memset(nss->pids, 0xff, 0x400);
else
memset(nss->pids, 0x00, 0x400);
} else {
if (pid & 0x8000)
nss->pids[byte] |= bit;
else
nss->pids[byte] &= ~bit;
}
if (ns->set_pid)
ret = ns->set_pid(nss, pid);
break;
}
case NS_SET_PIDS:
ret = copy_from_user(nss->pids, *(u8 **) parg, 0x400);
if (ret < 0)
return ret;
if (ns->set_pids)
ret = ns->set_pids(nss);
break;
case NS_SET_CI:
{
u8 ci = *(u8 *) parg;
if (nss->running)
ret = -EBUSY;
else if (ns->set_ci)
ret = ns->set_ci(nss, ci);
break;
}
default:
ret = -EINVAL;
break;
}
return ret;
}
static long ns_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, do_ioctl);
}
static const struct file_operations ns_fops = {
.owner = THIS_MODULE,
.read = ns_read,
.write = ns_write,
.open = ns_open,
.release = ns_release,
.poll = ns_poll,
.mmap = 0,
.unlocked_ioctl = ns_ioctl,
};
static struct dvb_device ns_dev = {
.priv = 0,
.readers = 1,
.writers = 1,
.users = 1,
.fops = &ns_fops,
};
int dvb_netstream_init(struct dvb_adapter *dvb_adapter,
struct dvb_netstream *ns)
{
mutex_init(&ns->mutex);
spin_lock_init(&ns->lock);
ns->exit = 0;
dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns,
DVB_DEVICE_NS);
INIT_LIST_HEAD(&ns->nssl);
return 0;
}
EXPORT_SYMBOL(dvb_netstream_init);
void dvb_netstream_release(struct dvb_netstream *ns)
{
ns->exit = 1;
if (ns->dvbdev->users > 1) {
wait_event(ns->dvbdev->wait_queue,
ns->dvbdev->users == 1);
}
dvb_unregister_device(ns->dvbdev);
}
EXPORT_SYMBOL(dvb_netstream_release);

93
dvb-core/dvb_netstream.h Normal file
View File

@ -0,0 +1,93 @@
/*
* dvb_netstream.c: support for DVB to network streaming hardware
*
* Copyright (C) 2012-2013 Marcus and Ralph Metzler
* for Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#ifndef _DVB_NETSTREAM_H_
#define _DVB_NETSTREAM_H_
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <asm/uaccess.h>
#include <linux/dvb/ns.h>
#include "dvbdev.h"
#define DVBNS_MAXPIDS 32
struct dvbnss {
struct dvb_netstream *ns;
void *priv;
u8 pids[1024];
u8 packet[1328];
u32 pp;
struct socket *sock;
struct sockaddr_in sadr;
u32 sn;
struct dvb_ns_params params;
struct list_head nssl;
int running;
};
#define MAX_DVBNSS 32
struct dvb_netstream {
void *priv;
struct mutex mutex;
spinlock_t lock;
struct dvb_device *dvbdev;
int exit;
struct list_head nssl;
int (*set_net)(struct dvbnss *);
int (*set_pid)(struct dvbnss *, u16);
int (*set_pids)(struct dvbnss *);
int (*set_ci)(struct dvbnss *, u8);
int (*set_rtcp_msg)(struct dvbnss *, u8 *, u32);
int (*set_ts_packets)(struct dvbnss *, u8 *, u32);
int (*insert_ts_packets)(struct dvbnss *, u8);
int (*start)(struct dvbnss *);
int (*stop)(struct dvbnss *);
int (*alloc)(struct dvbnss *);
void (*free)(struct dvbnss *);
};
void dvb_netstream_release(struct dvb_netstream *);
int dvb_netstream_init(struct dvb_adapter *, struct dvb_netstream *);
#endif

299
dvb-core/dvb_ringbuffer.c Normal file
View File

@ -0,0 +1,299 @@
/*
*
* dvb_ringbuffer.c: ring buffer implementation for the dvb driver
*
* Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
*
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include "dvb_ringbuffer.h"
#define PKT_READY 0
#define PKT_DISPOSED 1
void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
{
rbuf->pread=rbuf->pwrite=0;
rbuf->data=data;
rbuf->size=len;
rbuf->error=0;
init_waitqueue_head(&rbuf->queue);
spin_lock_init(&(rbuf->lock));
}
int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
{
return (rbuf->pread==rbuf->pwrite);
}
ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
{
ssize_t free;
free = rbuf->pread - rbuf->pwrite;
if (free <= 0)
free += rbuf->size;
return free-1;
}
ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
{
ssize_t avail;
avail = rbuf->pwrite - rbuf->pread;
if (avail < 0)
avail += rbuf->size;
return avail;
}
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
{
rbuf->pread = rbuf->pwrite;
rbuf->error = 0;
}
EXPORT_SYMBOL(dvb_ringbuffer_flush);
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
{
rbuf->pread = rbuf->pwrite = 0;
rbuf->error = 0;
}
void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
{
unsigned long flags;
spin_lock_irqsave(&rbuf->lock, flags);
dvb_ringbuffer_flush(rbuf);
spin_unlock_irqrestore(&rbuf->lock, flags);
wake_up(&rbuf->queue);
}
ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
{
size_t todo = len;
size_t split;
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
}
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
return len;
}
void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
{
size_t todo = len;
size_t split;
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
memcpy(buf, rbuf->data+rbuf->pread, split);
buf += split;
todo -= split;
rbuf->pread = 0;
}
memcpy(buf, rbuf->data+rbuf->pread, todo);
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
}
ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
{
size_t todo = len;
size_t split;
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
if (split > 0) {
memcpy(rbuf->data+rbuf->pwrite, buf, split);
buf += split;
todo -= split;
rbuf->pwrite = 0;
}
memcpy(rbuf->data+rbuf->pwrite, buf, todo);
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
return len;
}
ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
{
int status;
ssize_t oldpwrite = rbuf->pwrite;
DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8);
DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff);
DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY);
status = dvb_ringbuffer_write(rbuf, buf, len);
if (status < 0) rbuf->pwrite = oldpwrite;
return status;
}
ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8 __user *buf, size_t len)
{
size_t todo;
size_t split;
size_t pktlen;
pktlen = rbuf->data[idx] << 8;
pktlen |= rbuf->data[(idx + 1) % rbuf->size];
if (offset > pktlen) return -EINVAL;
if ((offset + len) > pktlen) len = pktlen - offset;
idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
todo = len;
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
if (copy_to_user(buf, rbuf->data+idx, split))
return -EFAULT;
buf += split;
todo -= split;
idx = 0;
}
if (copy_to_user(buf, rbuf->data+idx, todo))
return -EFAULT;
return len;
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8* buf, size_t len)
{
size_t todo;
size_t split;
size_t pktlen;
pktlen = rbuf->data[idx] << 8;
pktlen |= rbuf->data[(idx + 1) % rbuf->size];
if (offset > pktlen) return -EINVAL;
if ((offset + len) > pktlen) len = pktlen - offset;
idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
todo = len;
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
memcpy(buf, rbuf->data+idx, split);
buf += split;
todo -= split;
idx = 0;
}
memcpy(buf, rbuf->data+idx, todo);
return len;
}
void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
{
size_t pktlen;
rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED;
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
} else {
// first packet is not disposed, so we stop cleaning now
break;
}
}
}
ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen)
{
int consumed;
int curpktlen;
int curpktstatus;
if (idx == -1) {
idx = rbuf->pread;
} else {
curpktlen = rbuf->data[idx] << 8;
curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
}
consumed = (idx - rbuf->pread) % rbuf->size;
while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
curpktlen = rbuf->data[idx] << 8;
curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
if (curpktstatus == PKT_READY) {
*pktlen = curpktlen;
return idx;
}
consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
}
// no packets available
return -1;
}
EXPORT_SYMBOL(dvb_ringbuffer_init);
EXPORT_SYMBOL(dvb_ringbuffer_empty);
EXPORT_SYMBOL(dvb_ringbuffer_free);
EXPORT_SYMBOL(dvb_ringbuffer_avail);
EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write);

186
dvb-core/dvb_ringbuffer.h Normal file
View File

@ -0,0 +1,186 @@
/*
*
* dvb_ringbuffer.h: ring buffer implementation for the dvb driver
*
* Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
*
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DVB_RINGBUFFER_H_
#define _DVB_RINGBUFFER_H_
#include <linux/spinlock.h>
#include <linux/wait.h>
struct dvb_ringbuffer {
u8 *data;
ssize_t size;
ssize_t pread;
ssize_t pwrite;
int error;
wait_queue_head_t queue;
spinlock_t lock;
};
#define DVB_RINGBUFFER_PKTHDRSIZE 3
/*
** Notes:
** ------
** (1) For performance reasons read and write routines don't check buffer sizes
** and/or number of bytes free/available. This has to be done before these
** routines are called. For example:
**
** *** write <buflen> bytes ***
** free = dvb_ringbuffer_free(rbuf);
** if (free >= buflen)
** count = dvb_ringbuffer_write(rbuf, buffer, buflen);
** else
** ...
**
** *** read min. 1000, max. <bufsize> bytes ***
** avail = dvb_ringbuffer_avail(rbuf);
** if (avail >= 1000)
** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
** else
** ...
**
** (2) If there is exactly one reader and one writer, there is no need
** to lock read or write operations.
** Two or more readers must be locked against each other.
** Flushing the buffer counts as a read operation.
** Resetting the buffer counts as a read and write operation.
** Two or more writers must be locked against each other.
*/
/* initialize ring buffer, lock and queue */
extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len);
/* test whether buffer is empty */
extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
/* return the number of free bytes in the buffer */
extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
/* return the number of bytes waiting in the buffer */
extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
/*
** Reset the read and write pointers to zero and flush the buffer
** This counts as a read and write operation
*/
extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
/* read routines & macros */
/* ---------------------- */
/* flush buffer */
extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
/* flush buffer protected by spinlock and wake-up waiting task(s) */
extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
/* peek at byte <offs> in the buffer */
#define DVB_RINGBUFFER_PEEK(rbuf,offs) \
(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
/* advance read ptr by <num> bytes */
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
/*
** read <len> bytes from ring buffer into <buf>
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
u8 __user *buf, size_t len);
extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
u8 *buf, size_t len);
/* write routines & macros */
/* ----------------------- */
/* write single byte to ring buffer */
#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \
{ (rbuf)->data[(rbuf)->pwrite]=(byte); \
(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
/*
** write <len> bytes to ring buffer
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
size_t len);
/**
* Write a packet into the ringbuffer.
*
* <rbuf> Ringbuffer to write to.
* <buf> Buffer to write.
* <len> Length of buffer (currently limited to 65535 bytes max).
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
size_t len);
/**
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
* does NOT update the read pointer in the ringbuffer. You must use
* dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required.
*
* <rbuf> Ringbuffer concerned.
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
* <offset> Offset into packet to read from.
* <buf> Destination buffer for data.
* <len> Size of destination buffer.
* <usermem> Set to 1 if <buf> is in userspace.
* returns Number of bytes read, or -EFAULT.
*/
extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8 __user *buf, size_t len);
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8 *buf, size_t len);
/**
* Dispose of a packet in the ring buffer.
*
* <rbuf> Ring buffer concerned.
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
*/
extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
/**
* Get the index of the next packet in a ringbuffer.
*
* <rbuf> Ringbuffer concerned.
* <idx> Previous packet index, or -1 to return the first packet index.
* <pktlen> On success, will be updated to contain the length of the packet in bytes.
* returns Packet index (if >=0), or -1 if no packets available.
*/
extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen);
#endif /* _DVB_RINGBUFFER_H_ */

514
dvb-core/dvbdev.c Normal file
View File

@ -0,0 +1,514 @@
/*
* dvbdev.c
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/version.h>
#include "dvbdev.h"
static DEFINE_MUTEX(dvbdev_mutex);
static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644);
MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
#define dprintk if (dvbdev_debug) printk
static LIST_HEAD(dvb_adapter_list);
static DEFINE_MUTEX(dvbdev_register_lock);
static const char * const dnames[] = {
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
"net", "osd", "ci", "mod", "ns", "nsd"
};
#ifdef CONFIG_DVB_DYNAMIC_MINORS
#define MAX_DVB_MINORS 256
#define DVB_MAX_IDS MAX_DVB_MINORS
#else
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
#endif
static struct class *dvb_class;
static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
static DECLARE_RWSEM(minor_rwsem);
static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
mutex_lock(&dvbdev_mutex);
down_read(&minor_rwsem);
dvbdev = dvb_minors[iminor(inode)];
if (dvbdev && dvbdev->fops) {
int err = 0;
const struct file_operations *old_fops;
file->private_data = dvbdev;
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
if (file->f_op == NULL) {
file->f_op = old_fops;
goto fail;
}
if(file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
up_read(&minor_rwsem);
mutex_unlock(&dvbdev_mutex);
return err;
}
fail:
up_read(&minor_rwsem);
mutex_unlock(&dvbdev_mutex);
return -ENODEV;
}
static const struct file_operations dvb_device_fops =
{
.owner = THIS_MODULE,
.open = dvb_device_open,
.llseek = noop_llseek,
};
static struct cdev dvb_device_cdev;
int dvb_generic_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
if (!dvbdev)
return -ENODEV;
if (!dvbdev->users)
return -EBUSY;
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
if (!dvbdev->readers)
return -EBUSY;
dvbdev->readers--;
} else {
if (!dvbdev->writers)
return -EBUSY;
dvbdev->writers--;
}
dvbdev->users--;
return 0;
}
EXPORT_SYMBOL(dvb_generic_open);
int dvb_generic_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
if (!dvbdev)
return -ENODEV;
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
dvbdev->readers++;
} else {
dvbdev->writers++;
}
dvbdev->users++;
return 0;
}
EXPORT_SYMBOL(dvb_generic_release);
long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
if (!dvbdev)
return -ENODEV;
if (!dvbdev->kernel_ioctl)
return -EINVAL;
return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
}
EXPORT_SYMBOL(dvb_generic_ioctl);
static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
{
u32 id = 0;
while (id < DVB_MAX_IDS) {
struct dvb_device *dev;
list_for_each_entry(dev, &adap->device_list, list_head)
if (dev->type == type && dev->id == id)
goto skip;
return id;
skip:
id++;
}
return -ENFILE;
}
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
const struct dvb_device *template, void *priv, int type)
{
struct dvb_device *dvbdev;
struct file_operations *dvbdevfops;
struct device *clsdev;
int minor;
int id;
mutex_lock(&dvbdev_register_lock);
if ((id = dvbdev_get_free_id (adap, type)) < 0){
mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
return -ENFILE;
}
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
if (!dvbdev){
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
if (!dvbdevfops){
kfree (dvbdev);
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
dvbdev->id = id;
dvbdev->adapter = adap;
dvbdev->priv = priv;
dvbdev->fops = dvbdevfops;
init_waitqueue_head (&dvbdev->wait_queue);
memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
dvbdevfops->owner = adap->module;
list_add_tail (&dvbdev->list_head, &adap->device_list);
down_write(&minor_rwsem);
#ifdef CONFIG_DVB_DYNAMIC_MINORS
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
if (dvb_minors[minor] == NULL)
break;
if (minor == MAX_DVB_MINORS) {
kfree(dvbdevfops);
kfree(dvbdev);
up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock);
return -EINVAL;
}
#else
minor = nums2minor(adap->num, type, id);
#endif
dvbdev->minor = minor;
dvb_minors[minor] = dvbdev;
up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock);
clsdev = device_create(dvb_class, adap->device,
MKDEV(DVB_MAJOR, minor),
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
return PTR_ERR(clsdev);
}
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, minor, minor);
return 0;
}
EXPORT_SYMBOL(dvb_register_device);
void dvb_unregister_device(struct dvb_device *dvbdev)
{
if (!dvbdev)
return;
down_write(&minor_rwsem);
dvb_minors[dvbdev->minor] = NULL;
up_write(&minor_rwsem);
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
list_del (&dvbdev->list_head);
kfree (dvbdev->fops);
kfree (dvbdev);
}
EXPORT_SYMBOL(dvb_unregister_device);
static int dvbdev_check_free_adapter_num(int num)
{
struct list_head *entry;
list_for_each(entry, &dvb_adapter_list) {
struct dvb_adapter *adap;
adap = list_entry(entry, struct dvb_adapter, list_head);
if (adap->num == num)
return 0;
}
return 1;
}
static int dvbdev_get_free_adapter_num (void)
{
int num = 0;
while (num < DVB_MAX_ADAPTERS) {
if (dvbdev_check_free_adapter_num(num))
return num;
num++;
}
return -ENFILE;
}
int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
struct module *module, struct device *device,
short *adapter_nums)
{
int i, num;
mutex_lock(&dvbdev_register_lock);
for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
num = adapter_nums[i];
if (num >= 0 && num < DVB_MAX_ADAPTERS) {
/* use the one the driver asked for */
if (dvbdev_check_free_adapter_num(num))
break;
} else {
num = dvbdev_get_free_adapter_num();
break;
}
num = -1;
}
if (num < 0) {
mutex_unlock(&dvbdev_register_lock);
return -ENFILE;
}
memset (adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list);
printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
adap->num = num;
adap->name = name;
adap->module = module;
adap->device = device;
adap->mfe_shared = 0;
adap->mfe_dvbdev = NULL;
mutex_init (&adap->mfe_lock);
list_add_tail (&adap->list_head, &dvb_adapter_list);
mutex_unlock(&dvbdev_register_lock);
return num;
}
EXPORT_SYMBOL(dvb_register_adapter);
int dvb_unregister_adapter(struct dvb_adapter *adap)
{
mutex_lock(&dvbdev_register_lock);
list_del (&adap->list_head);
mutex_unlock(&dvbdev_register_lock);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
/* if the miracle happens and "generic_usercopy()" is included into
the kernel, then this can vanish. please don't make the mistake and
define this as video_usercopy(). this will introduce a dependecy
to the v4l "videodev.o" module, which is unnecessary for some
cards (ie. the budget dvb-cards don't need the v4l module...) */
int dvb_usercopy(struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct file *file,
unsigned int cmd, void *arg))
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
int err = -EINVAL;
/* Copy arguments into temp kernel buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_NONE:
/*
* For this command, the pointer is actually an integer
* argument.
*/
parg = (void *) arg;
break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
break;
}
/* call driver */
/* this lock is much too coarse */
//mutex_lock(&dvbdev_mutex);
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
err = -ENOTTY;
//mutex_unlock(&dvbdev_mutex);
if (err < 0)
goto out;
/* Copy results into user buffer */
switch (_IOC_DIR(cmd))
{
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
err = -EFAULT;
break;
}
out:
kfree(mbuf);
return err;
}
EXPORT_SYMBOL(dvb_usercopy);
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
return 0;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
static char *dvb_devnode(struct device *dev, mode_t *mode)
#else
static char *dvb_devnode(struct device *dev, umode_t *mode)
#endif
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
}
static int __init init_dvbdev(void)
{
int retval;
dev_t dev = MKDEV(DVB_MAJOR, 0);
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
return retval;
}
cdev_init(&dvb_device_cdev, &dvb_device_fops);
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
printk(KERN_ERR "dvb-core: unable register character device\n");
goto error;
}
dvb_class = class_create(THIS_MODULE, "dvb");
if (IS_ERR(dvb_class)) {
retval = PTR_ERR(dvb_class);
goto error;
}
dvb_class->dev_uevent = dvb_uevent;
dvb_class->devnode = dvb_devnode;
return 0;
error:
cdev_del(&dvb_device_cdev);
unregister_chrdev_region(dev, MAX_DVB_MINORS);
return retval;
}
static void __exit exit_dvbdev(void)
{
class_destroy(dvb_class);
cdev_del(&dvb_device_cdev);
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
}
subsys_initcall(init_dvbdev);
module_exit(exit_dvbdev);
MODULE_DESCRIPTION("DVB Core Driver");
MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
MODULE_LICENSE("GPL");

150
dvb-core/dvbdev.h Normal file
View File

@ -0,0 +1,150 @@
/*
* dvbdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _DVBDEV_H_
#define _DVBDEV_H_
#include <linux/types.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/list.h>
#define DVB_MAJOR 212
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
#else
#define DVB_MAX_ADAPTERS 8
#endif
#define DVB_UNSET (-1)
#define DVB_DEVICE_VIDEO 0
#define DVB_DEVICE_AUDIO 1
#define DVB_DEVICE_SEC 2
#define DVB_DEVICE_FRONTEND 3
#define DVB_DEVICE_DEMUX 4
#define DVB_DEVICE_DVR 5
#define DVB_DEVICE_CA 6
#define DVB_DEVICE_NET 7
#define DVB_DEVICE_OSD 8
#define DVB_DEVICE_CI 9
#define DVB_DEVICE_MOD 10
#define DVB_DEVICE_NS 11
#define DVB_DEVICE_NSD 12
#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
static short adapter_nr[] = \
{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
module_param_array(adapter_nr, short, NULL, 0444); \
MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
struct dvb_frontend;
struct dvb_adapter {
int num;
struct list_head list_head;
struct list_head device_list;
const char *name;
u8 proposed_mac [6];
void* priv;
struct device *device;
struct module *module;
int mfe_shared; /* indicates mutually exclusive frontends */
struct dvb_device *mfe_dvbdev; /* frontend device in use */
struct mutex mfe_lock; /* access lock for thread creation */
};
struct dvb_device {
struct list_head list_head;
const struct file_operations *fops;
struct dvb_adapter *adapter;
int type;
int minor;
u32 id;
/* in theory, 'users' can vanish now,
but I don't want to change too much now... */
int readers;
int writers;
int users;
wait_queue_head_t wait_queue;
/* don't really need those !? -- FIXME: use video_usercopy */
int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
void *priv;
};
extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
struct module *module, struct device *device,
short *adapter_nums);
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
struct dvb_device **pdvbdev,
const struct dvb_device *template,
void *priv,
int type);
extern void dvb_unregister_device (struct dvb_device *dvbdev);
extern int dvb_generic_open (struct inode *inode, struct file *file);
extern int dvb_generic_release (struct inode *inode, struct file *file);
extern long dvb_generic_ioctl (struct file *file,
unsigned int cmd, unsigned long arg);
/* we don't mess with video_usercopy() any more,
we simply define out own dvb_usercopy(), which will hopefully become
generic_usercopy() someday... */
extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, unsigned int cmd, void *arg));
/** generic DVB attach function. */
#ifdef CONFIG_MEDIA_ATTACH
#define dvb_attach(FUNCTION, ARGS...) ({ \
void *__r = NULL; \
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
if (__a) { \
__r = (void *) __a(ARGS); \
if (__r == NULL) \
symbol_put(FUNCTION); \
} else { \
printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
} \
__r; \
})
#else
#define dvb_attach(FUNCTION, ARGS...) ({ \
FUNCTION(ARGS); \
})
#endif
#endif /* #ifndef _DVBDEV_H_ */

37
frontends/Makefile Normal file
View File

@ -0,0 +1,37 @@
#
# Makefile for the kernel DVB frontend device drivers.
#
EXTRA_CFLAGS += -DCONFIG_DVB_LNBP21
EXTRA_CFLAGS += -DCONFIG_DVB_STV090x
EXTRA_CFLAGS += -DCONFIG_DVB_STV6110x
#EXTRA_CFLAGS += -DCONFIG_DVB_STV0367
EXTRA_CFLAGS += -DCONFIG_DVB_STV0367DD
#EXTRA_CFLAGS += -DCONFIG_DVB_TDA18212
EXTRA_CFLAGS += -DCONFIG_DVB_TDA18212DD
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843
EXTRA_CFLAGS += -DCONFIG_DVB_STV6111
EXTRA_CFLAGS += -DCONFIG_DVB_STV0910
EXTRA_CFLAGS += -DCONFIG_DVB_LNBH25
EXTRA_CFLAGS += -DCONFIG_DVB_MXL5XX
EXTRA_CFLAGS += -DDBVALS
NOSTDINC_FLAGS += -I$(SUBDIRS)/include -I$(SUBDIRS)/dvb-core
drxk-objs := drxk_hard.o
obj-$(CONFIG_DVB_DRXK) += drxk.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_STV090x) += stv090x.o
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
#obj-$(CONFIG_DVB_STV0367) += stv0367.o
obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
#obj-$(CONFIG_DVB_TDA18212) += tda18212.o
obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
obj-$(CONFIG_DVB_STV6111) += stv6111.o
obj-$(CONFIG_DVB_STV0910) += stv0910.o
obj-$(CONFIG_DVB_LNBH25) += lnbh25.o
obj-$(CONFIG_DVB_MXL5XX) += mxl5xx.o

726
frontends/cxd2099.c Normal file
View File

@ -0,0 +1,726 @@
/*
* cxd2099.c: Driver for the CXD2099AR Common Interface Controller
*
* Copyright (C) 2010-2013 Digital Devices GmbH
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include "cxd2099.h"
//#define BUFFER_MODE 1
static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);
struct cxd {
struct dvb_ca_en50221 en;
struct i2c_adapter *i2c;
struct cxd2099_cfg cfg;
u8 regs[0x23];
u8 lastaddress;
u8 clk_reg_f;
u8 clk_reg_b;
int mode;
int ready;
int dr;
int write_busy;
int slot_stat;
u8 amem[1024];
int amem_read;
int cammode;
struct mutex lock;
u8 rbuf[1028];
u8 wbuf[1028];
};
static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 data)
{
u8 m[2] = {reg, data};
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
if (i2c_transfer(adapter, &msg, 1) != 1) {
pr_err("Failed to write to I2C register %02x@%02x!\n",
reg, adr);
return -1;
}
return 0;
}
static int i2c_write(struct i2c_adapter *adapter, u8 adr,
u8 *data, u16 len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
if (i2c_transfer(adapter, &msg, 1) != 1) {
pr_err("Failed to write to I2C!\n");
return -1;
}
return 0;
}
static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 *val)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1} };
if (i2c_transfer(adapter, msgs, 2) != 2) {
pr_err("error in i2c_read_reg\n");
return -1;
}
return 0;
}
static int i2c_read(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 *data, u16 n)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = data, .len = n} };
if (i2c_transfer(adapter, msgs, 2) != 2) {
pr_err("error in i2c_read\n");
return -1;
}
return 0;
}
static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
{
int status = 0;
if (ci->lastaddress != adr)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
if (!status) {
ci->lastaddress = adr;
while (n) {
int len = n;
if (ci->cfg.max_i2c &&
len > ci->cfg.max_i2c)
len = ci->cfg.max_i2c;
status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len);
if (status)
return status;
data += len;
n -= len;
}
}
return status;
}
static int read_reg(struct cxd *ci, u8 reg, u8 *val)
{
return read_block(ci, reg, val, 1);
}
static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status)
status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
return status;
}
static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status) {
u8 buf[256] = {3};
memcpy(buf + 1, data, n);
status = i2c_write(ci->i2c, ci->cfg.adr, buf, n+1);
}
return status;
}
static int read_io(struct cxd *ci, u16 address, u8 *val)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status)
status = i2c_read(ci->i2c, ci->cfg.adr, 3, val, 1);
return status;
}
static int write_io(struct cxd *ci, u16 address, u8 val)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
u8 buf[2] = {3, val};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status)
status = i2c_write(ci->i2c, ci->cfg.adr, buf, 2);
return status;
}
#if 0
static int read_io_data(struct cxd *ci, u8 *data, u16 n)
{
int status;
u8 addr[3] = { 2, 0, 0 };
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status)
status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
return 0;
}
static int write_io_data(struct cxd *ci, u8 *data, u16 n)
{
int status;
u8 addr[3] = {2, 0, 0};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
if (!status) {
u8 buf[256] = {3};
memcpy(buf + 1, data, n);
status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
}
return 0;
}
#endif
static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
{
int status = 0;
if (ci->lastaddress != reg)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg);
if (!status && reg >= 6 && reg <= 8 && mask != 0xff)
status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]);
ci->lastaddress = reg;
ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
if (!status)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]);
if (reg == 0x20)
ci->regs[reg] &= 0x7f;
return status;
}
static int write_reg(struct cxd *ci, u8 reg, u8 val)
{
return write_regm(ci, reg, val, 0xff);
}
#ifdef BUFFER_MODE
static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
{
int status = 0;
u8 *buf = ci->wbuf;
if (ci->lastaddress != adr)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
if (status)
return status;
printk("write_block %d\n", n);
ci->lastaddress = adr;
buf[0] = 1;
while (n) {
int len = n;
if (ci->cfg.max_i2c &&
len + 1 > ci->cfg.max_i2c)
len = ci->cfg.max_i2c - 1;
printk("write %d\n", len);
memcpy(buf + 1, data, len);
status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1);
if (status)
return status;
n -= len;
data += len;
}
return status;
}
#endif
static void set_mode(struct cxd *ci, int mode)
{
if (mode == ci->mode)
return;
switch (mode) {
case 0x00: /* IO mem */
write_regm(ci, 0x06, 0x00, 0x07);
break;
case 0x01: /* ATT mem */
write_regm(ci, 0x06, 0x02, 0x07);
break;
default:
break;
}
ci->mode = mode;
}
static void cam_mode(struct cxd *ci, int mode)
{
u8 dummy;
if (mode == ci->cammode)
return;
switch (mode) {
case 0x00:
write_regm(ci, 0x20, 0x80, 0x80);
break;
case 0x01:
if (!ci->en.read_data)
return;
ci->write_busy = 0;
pr_info("enable cam buffer mode\n");
write_reg(ci, 0x0d, 0x00);
write_reg(ci, 0x0e, 0x01);
write_regm(ci, 0x08, 0x40, 0x40);
read_reg(ci, 0x12, &dummy);
write_regm(ci, 0x08, 0x80, 0x80);
break;
default:
break;
}
ci->cammode = mode;
}
#define CHK_ERROR(s) if ((status = s)) break
static int init(struct cxd *ci)
{
int status;
mutex_lock(&ci->lock);
ci->mode = -1;
do {
CHK_ERROR(write_reg(ci, 0x00, 0x00));
CHK_ERROR(write_reg(ci, 0x01, 0x00));
CHK_ERROR(write_reg(ci, 0x02, 0x10));
CHK_ERROR(write_reg(ci, 0x03, 0x00));
CHK_ERROR(write_reg(ci, 0x05, 0xFF));
CHK_ERROR(write_reg(ci, 0x06, 0x1F));
CHK_ERROR(write_reg(ci, 0x07, 0x1F));
CHK_ERROR(write_reg(ci, 0x08, 0x28));
CHK_ERROR(write_reg(ci, 0x14, 0x20));
/* TOSTRT = 8, Mode B (gated clock), falling Edge,
Serial, POL=HIGH, MSB */
CHK_ERROR(write_reg(ci, 0x0A, 0xA7));
CHK_ERROR(write_reg(ci, 0x0B, 0x33));
CHK_ERROR(write_reg(ci, 0x0C, 0x33));
CHK_ERROR(write_regm(ci, 0x14, 0x00, 0x0F));
CHK_ERROR(write_reg(ci, 0x15, ci->clk_reg_b));
CHK_ERROR(write_regm(ci, 0x16, 0x00, 0x0F));
CHK_ERROR(write_reg(ci, 0x17, ci->clk_reg_f));
if (ci->cfg.clock_mode == 2) {
/* bitrate*2^13/ 72000 */
u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000;
if (ci->cfg.polarity) {
CHK_ERROR(write_reg(ci, 0x09, 0x6f));
} else {
CHK_ERROR(write_reg(ci, 0x09, 0x6d));
}
CHK_ERROR(write_reg(ci, 0x20, 0x08));
CHK_ERROR(write_reg(ci, 0x21, (reg >> 8) & 0xff));
CHK_ERROR(write_reg(ci, 0x22, reg & 0xff));
} else if (ci->cfg.clock_mode == 1) {
if (ci->cfg.polarity) {
CHK_ERROR(write_reg(ci, 0x09, 0x6f)); /* D */
} else {
CHK_ERROR(write_reg(ci, 0x09, 0x6d));
}
CHK_ERROR(write_reg(ci, 0x20, 0x68));
CHK_ERROR(write_reg(ci, 0x21, 0x00));
CHK_ERROR(write_reg(ci, 0x22, 0x02));
} else {
if (ci->cfg.polarity) {
CHK_ERROR(write_reg(ci, 0x09, 0x4f)); /* C */
} else {
CHK_ERROR(write_reg(ci, 0x09, 0x4d));
}
CHK_ERROR(write_reg(ci, 0x20, 0x28));
CHK_ERROR(write_reg(ci, 0x21, 0x00));
CHK_ERROR(write_reg(ci, 0x22, 0x07));
}
CHK_ERROR(write_regm(ci, 0x20, 0x80, 0x80));
CHK_ERROR(write_regm(ci, 0x03, 0x02, 0x02));
CHK_ERROR(write_reg(ci, 0x01, 0x04));
CHK_ERROR(write_reg(ci, 0x00, 0x31));
/* Put TS in bypass */
CHK_ERROR(write_regm(ci, 0x09, 0x08, 0x08));
ci->cammode = -1;
cam_mode(ci, 0);
} while (0);
mutex_unlock(&ci->lock);
return 0;
}
static int read_attribute_mem(struct dvb_ca_en50221 *ca,
int slot, int address)
{
struct cxd *ci = ca->data;
#if 0
if (ci->amem_read) {
if (address <= 0 || address > 1024)
return -EIO;
return ci->amem[address];
}
mutex_lock(&ci->lock);
write_regm(ci, 0x06, 0x00, 0x05);
read_pccard(ci, 0, &ci->amem[0], 128);
read_pccard(ci, 128, &ci->amem[0], 128);
read_pccard(ci, 256, &ci->amem[0], 128);
read_pccard(ci, 384, &ci->amem[0], 128);
write_regm(ci, 0x06, 0x05, 0x05);
mutex_unlock(&ci->lock);
return ci->amem[address];
#else
u8 val;
mutex_lock(&ci->lock);
set_mode(ci, 1);
read_pccard(ci, address, &val, 1);
mutex_unlock(&ci->lock);
return val;
#endif
}
static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
int address, u8 value)
{
struct cxd *ci = ca->data;
mutex_lock(&ci->lock);
set_mode(ci, 1);
write_pccard(ci, address, &value, 1);
mutex_unlock(&ci->lock);
return 0;
}
static int read_cam_control(struct dvb_ca_en50221 *ca,
int slot, u8 address)
{
struct cxd *ci = ca->data;
u8 val;
mutex_lock(&ci->lock);
set_mode(ci, 0);
read_io(ci, address, &val);
mutex_unlock(&ci->lock);
return val;
}
static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
u8 address, u8 value)
{
struct cxd *ci = ca->data;
mutex_lock(&ci->lock);
set_mode(ci, 0);
write_io(ci, address, value);
mutex_unlock(&ci->lock);
return 0;
}
static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct cxd *ci = ca->data;
if (ci->cammode)
read_data(ca, slot, ci->rbuf, 0);
mutex_lock(&ci->lock);
#if 0
write_reg(ci, 0x00, 0x21);
write_reg(ci, 0x06, 0x1F);
write_reg(ci, 0x00, 0x31);
#else
#if 0
write_reg(ci, 0x06, 0x1F);
write_reg(ci, 0x06, 0x2F);
#else
cam_mode(ci, 0);
write_reg(ci, 0x00, 0x21);
write_reg(ci, 0x06, 0x1F);
/*msleep(300);*/
write_reg(ci, 0x00, 0x31);
write_regm(ci, 0x20, 0x80, 0x80);
write_reg(ci, 0x03, 0x02);
ci->ready = 0;
#endif
#endif
ci->mode = -1;
{
int i;
#if 0
u8 val;
#endif
for (i = 0; i < 100; i++) {
msleep(20);
#if 0
read_reg(ci, 0x06, &val);
pr_info(KERN_INFO "%d:%02x\n", i, val);
if (!(val&0x10))
break;
#else
if (ci->ready)
break;
#endif
}
}
mutex_unlock(&ci->lock);
/* msleep(500); */
return 0;
}
static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
struct cxd *ci = ca->data;
pr_info("slot_shutdown\n");
if (ci->cammode)
read_data(ca, slot, ci->rbuf, 0);
mutex_lock(&ci->lock);
write_reg(ci, 0x00, 0x21);
write_reg(ci, 0x06, 0x1F);
msleep(300);
write_regm(ci, 0x09, 0x08, 0x08);
write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */
ci->mode = -1;
ci->write_busy = 0;
mutex_unlock(&ci->lock);
return 0;
}
static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
struct cxd *ci = ca->data;
mutex_lock(&ci->lock);
write_regm(ci, 0x09, 0x00, 0x08);
set_mode(ci, 0);
cam_mode(ci, 1);
mutex_unlock(&ci->lock);
return 0;
}
static int campoll(struct cxd *ci)
{
u8 istat;
read_reg(ci, 0x04, &istat);
if (!istat)
return 0;
write_reg(ci, 0x05, istat);
if (istat & 0x40)
ci->dr = 1;
if (istat & 0x20)
ci->write_busy = 0;
if (istat & 2) {
u8 slotstat;
read_reg(ci, 0x01, &slotstat);
if (!(2 & slotstat)) {
if (!ci->slot_stat) {
ci->slot_stat |=
DVB_CA_EN50221_POLL_CAM_PRESENT;
write_regm(ci, 0x03, 0x08, 0x08);
}
} else {
if (ci->slot_stat) {
ci->slot_stat = 0;
write_regm(ci, 0x03, 0x00, 0x08);
pr_info("NO CAM\n");
ci->ready = 0;
}
}
if ((istat & 8) &&
(ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ci->ready = 1;
ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY;
}
}
return 0;
}
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{
struct cxd *ci = ca->data;
u8 slotstat;
mutex_lock(&ci->lock);
campoll(ci);
read_reg(ci, 0x01, &slotstat);
mutex_unlock(&ci->lock);
return ci->slot_stat;
}
static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
{
struct cxd *ci = ca->data;
u8 msb, lsb;
u16 len;
mutex_lock(&ci->lock);
campoll(ci);
mutex_unlock(&ci->lock);
if (!ci->dr)
return 0;
mutex_lock(&ci->lock);
read_reg(ci, 0x0f, &msb);
read_reg(ci, 0x10, &lsb);
len = ((u16) msb << 8) | lsb;
if (len > ecount || len < 2) {
/* read it anyway or cxd may hang */
read_block(ci, 0x12, ci->rbuf, len);
mutex_unlock(&ci->lock);
return -EIO;
}
read_block(ci, 0x12, ebuf, len);
ci->dr = 0;
mutex_unlock(&ci->lock);
#if 0
pr_info("read_data %d\n", len);
{
int i;
for (i = 0; i < len; i++)
pr_info("%02x ", ebuf[i]);
pr_info("\n");
}
#endif
return len;
}
#ifdef BUFFER_MODE
static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
{
struct cxd *ci = ca->data;
if (ci->write_busy)
return -EAGAIN;
mutex_lock(&ci->lock);
write_reg(ci, 0x0d, ecount >> 8);
write_reg(ci, 0x0e, ecount & 0xff);
write_block(ci, 0x11, ebuf, ecount);
ci->write_busy = 1;
mutex_unlock(&ci->lock);
return ecount;
}
#endif
static struct dvb_ca_en50221 en_templ = {
.read_attribute_mem = read_attribute_mem,
.write_attribute_mem = write_attribute_mem,
.read_cam_control = read_cam_control,
.write_cam_control = write_cam_control,
.slot_reset = slot_reset,
.slot_shutdown = slot_shutdown,
.slot_ts_enable = slot_ts_enable,
.poll_slot_status = poll_slot_status,
#ifdef BUFFER_MODE
.read_data = read_data,
.write_data = write_data,
#endif
};
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
void *priv,
struct i2c_adapter *i2c)
{
struct cxd *ci = 0;
u8 val;
if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
pr_info("No CXD2099 detected at %02x\n", cfg->adr);
return 0;
}
ci = kzalloc(sizeof(struct cxd), GFP_KERNEL);
if (!ci)
return 0;
mutex_init(&ci->lock);
memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg));
ci->i2c = i2c;
ci->lastaddress = 0xff;
ci->clk_reg_b = 0x4a;
ci->clk_reg_f = 0x1b;
memcpy(&ci->en, &en_templ, sizeof(en_templ));
ci->en.data = ci;
init(ci);
pr_info("Attached CXD2099AR at %02x\n", ci->cfg.adr);
return &ci->en;
}
EXPORT_SYMBOL(cxd2099_attach);
MODULE_DESCRIPTION("cxd2099");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");

43
frontends/cxd2099.h Normal file
View File

@ -0,0 +1,43 @@
/*
* cxd2099.h: Driver for the CXD2099AR Common Interface Controller
*
* Copyright (C) 2010-2011 Digital Devices GmbH
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#ifndef _CXD2099_H_
#define _CXD2099_H_
#include <dvb_ca_en50221.h>
struct cxd2099_cfg {
u32 bitrate;
u8 adr;
u8 polarity;
u8 clock_mode;
u32 max_i2c;
};
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
void *priv, struct i2c_adapter *i2c);
#endif

2042
frontends/cxd2843.c Normal file

File diff suppressed because it is too large Load Diff

30
frontends/cxd2843.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _CXD2843_H_
#define _CXD2843_H_
#include <linux/types.h>
#include <linux/i2c.h>
struct cxd2843_cfg {
u8 adr;
u32 ts_clock;
u8 parallel;
};
#if defined(CONFIG_DVB_CXD2843) || \
(defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE))
extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
struct cxd2843_cfg *cfg);
#else
static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
struct cxd2843_cfg *cfg)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

10
frontends/drxk.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _DRXK_H_
#define _DRXK_H_
#include <linux/types.h>
#include <linux/i2c.h>
extern struct dvb_frontend *drxk_attach(struct i2c_adapter *i2c,
u8 adr,
struct dvb_frontend **fe_t);
#endif

BIN
frontends/drxk_a3.mc Normal file

Binary file not shown.

5097
frontends/drxk_hard.c Normal file

File diff suppressed because it is too large Load Diff

343
frontends/drxk_hard.h Normal file
View File

@ -0,0 +1,343 @@
#include "drxk_map.h"
#define DRXK_VERSION_MAJOR 0
#define DRXK_VERSION_MINOR 9
#define DRXK_VERSION_PATCH 4300
#define HI_I2C_DELAY 42
#define HI_I2C_BRIDGE_DELAY 350
#define DRXK_MAX_RETRIES 100
#define DRIVER_4400 1
#define DRXX_JTAGID 0x039210D9
#define DRXX_J_JTAGID 0x239310D9
#define DRXX_K_JTAGID 0x039210D9
#define DRX_UNKNOWN 254
#define DRX_AUTO 255
#define DRX_SCU_READY 0
#define DRXK_MAX_WAITTIME (200)
#define SCU_RESULT_OK 0
#define SCU_RESULT_UNKSTD -2
#define SCU_RESULT_UNKCMD -1
#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
#endif
#define DRXK_8VSB_MPEG_BIT_RATE 19392658UL /*bps*/
#define DRXK_DVBT_MPEG_BIT_RATE 32000000UL /*bps*/
#define DRXK_QAM16_MPEG_BIT_RATE 27000000UL /*bps*/
#define DRXK_QAM32_MPEG_BIT_RATE 33000000UL /*bps*/
#define DRXK_QAM64_MPEG_BIT_RATE 40000000UL /*bps*/
#define DRXK_QAM128_MPEG_BIT_RATE 46000000UL /*bps*/
#define DRXK_QAM256_MPEG_BIT_RATE 52000000UL /*bps*/
#define DRXK_MAX_MPEG_BIT_RATE 52000000UL /*bps*/
#define IQM_CF_OUT_ENA_OFDM__M 0x4
#define IQM_FS_ADJ_SEL_B_QAM 0x1
#define IQM_FS_ADJ_SEL_B_OFF 0x0
#define IQM_FS_ADJ_SEL_B_VSB 0x2
#define IQM_RC_ADJ_SEL_B_OFF 0x0
#define IQM_RC_ADJ_SEL_B_QAM 0x1
#define IQM_RC_ADJ_SEL_B_VSB 0x2
enum OperationMode {
OM_NONE,
OM_QAM_ITU_A,
OM_QAM_ITU_B,
OM_QAM_ITU_C,
OM_DVBT
};
typedef enum {
DRX_POWER_UP = 0,
DRX_POWER_MODE_1,
DRX_POWER_MODE_2,
DRX_POWER_MODE_3,
DRX_POWER_MODE_4,
DRX_POWER_MODE_5,
DRX_POWER_MODE_6,
DRX_POWER_MODE_7,
DRX_POWER_MODE_8,
DRX_POWER_MODE_9,
DRX_POWER_MODE_10,
DRX_POWER_MODE_11,
DRX_POWER_MODE_12,
DRX_POWER_MODE_13,
DRX_POWER_MODE_14,
DRX_POWER_MODE_15,
DRX_POWER_MODE_16,
DRX_POWER_DOWN = 255
}DRXPowerMode_t, *pDRXPowerMode_t;
/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
#ifndef DRXK_POWER_DOWN_OFDM
#define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1
#endif
/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
#ifndef DRXK_POWER_DOWN_CORE
#define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9
#endif
/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
#ifndef DRXK_POWER_DOWN_PLL
#define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10
#endif
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN };
enum EDrxkCoefArrayIndex {
DRXK_COEF_IDX_MN = 0,
DRXK_COEF_IDX_FM ,
DRXK_COEF_IDX_L ,
DRXK_COEF_IDX_LP ,
DRXK_COEF_IDX_BG ,
DRXK_COEF_IDX_DK ,
DRXK_COEF_IDX_I ,
DRXK_COEF_IDX_MAX
};
enum EDrxkSifAttenuation {
DRXK_SIF_ATTENUATION_0DB,
DRXK_SIF_ATTENUATION_3DB,
DRXK_SIF_ATTENUATION_6DB,
DRXK_SIF_ATTENUATION_9DB
};
enum EDrxkConstellation {
DRX_CONSTELLATION_BPSK = 0,
DRX_CONSTELLATION_QPSK,
DRX_CONSTELLATION_PSK8,
DRX_CONSTELLATION_QAM16,
DRX_CONSTELLATION_QAM32,
DRX_CONSTELLATION_QAM64,
DRX_CONSTELLATION_QAM128,
DRX_CONSTELLATION_QAM256,
DRX_CONSTELLATION_QAM512,
DRX_CONSTELLATION_QAM1024,
DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
DRX_CONSTELLATION_AUTO = DRX_AUTO
};
enum EDrxkInterleaveMode {
DRXK_QAM_I12_J17 = 16,
DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN
};
enum {
DRXK_SPIN_A1 = 0,
DRXK_SPIN_A2,
DRXK_SPIN_A3,
DRXK_SPIN_UNKNOWN
};
enum DRXKCfgDvbtSqiSpeed {
DRXK_DVBT_SQI_SPEED_FAST = 0,
DRXK_DVBT_SQI_SPEED_MEDIUM,
DRXK_DVBT_SQI_SPEED_SLOW,
DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
} ;
enum DRXFftmode_t {
DRX_FFTMODE_2K = 0,
DRX_FFTMODE_4K,
DRX_FFTMODE_8K,
DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
DRX_FFTMODE_AUTO = DRX_AUTO
};
enum DRXMPEGStrWidth_t {
DRX_MPEG_STR_WIDTH_1,
DRX_MPEG_STR_WIDTH_8
};
enum DRXQamLockRange_t {
DRX_QAM_LOCKRANGE_NORMAL,
DRX_QAM_LOCKRANGE_EXTENDED
};
struct DRXKCfgDvbtEchoThres_t {
u16 threshold;
enum DRXFftmode_t fftMode;
} ;
struct SCfgAgc
{
enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */
u16 outputLevel; /* range dependent on AGC */
u16 minOutputLevel; /* range dependent on AGC */
u16 maxOutputLevel; /* range dependent on AGC */
u16 speed; /* range dependent on AGC */
u16 top; /* rf-agc take over point */
u16 cutOffCurrent; /* rf-agc is accelerated if output current
is below cut-off current */
u16 IngainTgtMax;
u16 FastClipCtrlDelay;
};
struct SCfgPreSaw
{
u16 reference; /* pre SAW reference value, range 0 .. 31 */
bool usePreSaw; /* TRUE algorithms must use pre SAW sense */
};
struct DRXKOfdmScCmd_t
{
u16 cmd; /**< Command number */
u16 subcmd; /**< Sub-command parameter*/
u16 param0; /**< General purpous param */
u16 param1; /**< General purpous param */
u16 param2; /**< General purpous param */
u16 param3; /**< General purpous param */
u16 param4; /**< General purpous param */
};
struct drxk_state {
struct dvb_frontend c_frontend;
struct dvb_frontend t_frontend;
#ifndef USE_API3
struct dtv_frontend_properties props;
#else
struct dvb_frontend_parameters param;
#endif
struct device *dev;
struct i2c_adapter *i2c;
u8 demod_address;
void *priv;
struct mutex mutex;
struct mutex ctlock;
u32 m_Instance; ///< Channel 1,2,3 or 4
int m_ChunkSize;
u8 Chunk[256];
bool m_hasLNA;
bool m_hasDVBT;
bool m_hasDVBC;
bool m_hasAudio;
bool m_hasATV;
bool m_hasOOB;
bool m_hasSAWSW; /**< TRUE if mat_tx is available */
bool m_hasGPIO1; /**< TRUE if mat_rx is available */
bool m_hasGPIO2; /**< TRUE if GPIO is available */
bool m_hasIRQN; /**< TRUE if IRQN is available */
u16 m_oscClockFreq;
u16 m_HICfgTimingDiv;
u16 m_HICfgBridgeDelay;
u16 m_HICfgWakeUpKey;
u16 m_HICfgTimeout;
u16 m_HICfgCtrl;
s32 m_sysClockFreq ; ///< system clock frequency in kHz
enum EDrxkState m_DrxkState; ///< State of Drxk (init,stopped,started)
enum OperationMode m_OperationMode; ///< digital standards
struct SCfgAgc m_vsbRfAgcCfg; ///< settings for VSB RF-AGC
struct SCfgAgc m_vsbIfAgcCfg; ///< settings for VSB IF-AGC
u16 m_vsbPgaCfg; ///< settings for VSB PGA
struct SCfgPreSaw m_vsbPreSawCfg; ///< settings for pre SAW sense
s32 m_Quality83percent; ///< MER level (*0.1 dB) for 83% quality indication
s32 m_Quality93percent; ///< MER level (*0.1 dB) for 93% quality indication
bool m_smartAntInverted;
bool m_bDebugEnableBridge;
bool m_bPDownOpenBridge; ///< only open DRXK bridge before power-down once it has been accessed
bool m_bPowerDown; ///< Power down when not used
u32 m_IqmFsRateOfs; ///< frequency shift as written to DRXK register (28bit fixpoint)
bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */
bool m_insertRSByte; /**< If TRUE, insert RS byte */
bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */
bool m_invertDATA; /**< If TRUE, invert DATA signals */
bool m_invertERR; /**< If TRUE, invert ERR signal */
bool m_invertSTR; /**< If TRUE, invert STR signals */
bool m_invertVAL; /**< If TRUE, invert VAL signals */
bool m_invertCLK; /**< If TRUE, invert CLK signals */
bool m_DVBCStaticCLK;
bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will
be used, otherwise clockrate will
adapt to the bitrate of the TS */
u32 m_DVBTBitrate;
u32 m_DVBCBitrate;
u8 m_TSDataStrength;
u8 m_TSClockkStrength;
enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width**/
u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case
static clockrate is selected */
//LARGE_INTEGER m_StartTime; ///< Contains the time of the last demod start
s32 m_MpegLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
s32 m_DemodLockTimeOut; ///< WaitForLockStatus Timeout (counts from start time)
bool m_disableTEIhandling;
bool m_RfAgcPol;
bool m_IfAgcPol;
struct SCfgAgc m_atvRfAgcCfg; ///< settings for ATV RF-AGC
struct SCfgAgc m_atvIfAgcCfg; ///< settings for ATV IF-AGC
struct SCfgPreSaw m_atvPreSawCfg; ///< settings for ATV pre SAW sense
bool m_phaseCorrectionBypass;
s16 m_atvTopVidPeak;
u16 m_atvTopNoiseTh;
enum EDrxkSifAttenuation m_sifAttenuation;
bool m_enableCVBSOutput;
bool m_enableSIFOutput;
bool m_bMirrorFreqSpect;
enum EDrxkConstellation m_Constellation; ///< Constellation type of the channel
u32 m_CurrSymbolRate; ///< Current QAM symbol rate
struct SCfgAgc m_qamRfAgcCfg; ///< settings for QAM RF-AGC
struct SCfgAgc m_qamIfAgcCfg; ///< settings for QAM IF-AGC
u16 m_qamPgaCfg; ///< settings for QAM PGA
struct SCfgPreSaw m_qamPreSawCfg; ///< settings for QAM pre SAW sense
enum EDrxkInterleaveMode m_qamInterleaveMode; ///< QAM Interleave mode
u16 m_fecRsPlen;
u16 m_fecRsPrescale;
enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
u16 m_GPIO;
u16 m_GPIOCfg;
struct SCfgAgc m_dvbtRfAgcCfg; ///< settings for QAM RF-AGC
struct SCfgAgc m_dvbtIfAgcCfg; ///< settings for QAM IF-AGC
struct SCfgPreSaw m_dvbtPreSawCfg; ///< settings for QAM pre SAW sense
u16 m_agcFastClipCtrlDelay;
bool m_adcCompPassed;
u16 m_adcCompCoef[64];
u16 m_adcState;
u8 *m_microcode;
int m_microcode_length;
bool m_DRXK_A1_PATCH_CODE;
bool m_DRXK_A1_ROM_CODE;
bool m_DRXK_A2_ROM_CODE;
bool m_DRXK_A3_ROM_CODE;
bool m_DRXK_A2_PATCH_CODE;
bool m_DRXK_A3_PATCH_CODE;
bool m_rfmirror;
u8 m_deviceSpin;
u32 m_iqmRcRate;
u16 m_AntennaDVBC;
u16 m_AntennaDVBT;
u16 m_AntennaSwitchDVBTDVBC;
DRXPowerMode_t m_currentPowerMode;
};
#define NEVER_LOCK 0
#define NOT_LOCKED 1
#define DEMOD_LOCK 2
#define FEC_LOCK 3
#define MPEG_LOCK 4

16438
frontends/drxk_map.h Normal file

File diff suppressed because it is too large Load Diff

4340
frontends/drxk_map_b.h Normal file

File diff suppressed because it is too large Load Diff

55
frontends/lnbh24.h Normal file
View File

@ -0,0 +1,55 @@
/*
* lnbh24.h - driver for lnb supply and control ic lnbh24
*
* Copyright (C) 2009 NetUP Inc.
* Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _LNBH24_H
#define _LNBH24_H
/* system register bits */
#define LNBH24_OLF 0x01
#define LNBH24_OTF 0x02
#define LNBH24_EN 0x04
#define LNBH24_VSEL 0x08
#define LNBH24_LLC 0x10
#define LNBH24_TEN 0x20
#define LNBH24_TTX 0x40
#define LNBH24_PCL 0x80
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
&& defined(MODULE))
/* override_set and override_clear control which
system register bits (above) to always set & clear */
extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear, u8 i2c_addr);
#else
static inline struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear, u8 i2c_addr)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

157
frontends/lnbh25.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Driver for the ST LNBH25
*
* Copyright (C) 2014 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
#include "lnbh25.h"
struct lnbh25 {
struct i2c_adapter *i2c;
u8 adr;
u8 reg[4];
u8 boost;
};
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0,
.buf = data, .len = len};
if (i2c_transfer(adap, &msg, 1) != 1) {
pr_err("lnbh25: i2c_write error\n");
return -1;
}
return 0;
}
static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len)
{
u8 d[5];
memcpy(&d[1], &lnbh->reg[reg], len);
d[0] = reg + 2;
return i2c_write(lnbh->i2c, lnbh->adr, d, len + 1);
}
static int lnbh25_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
u8 oldreg0 = lnbh->reg[0];
switch (voltage) {
case SEC_VOLTAGE_OFF:
lnbh->reg[0] = 0x00;
lnbh->reg[1] &= ~0x01; /* Disable Tone */
lnbh->reg[2] = 0x00;
return lnbh25_write_regs(lnbh, 0, 3);
case SEC_VOLTAGE_13:
lnbh->reg[0] = lnbh->boost + 1;
break;
case SEC_VOLTAGE_18:
lnbh->reg[0] = lnbh->boost + 8;
break;
default:
return -EINVAL;
};
if (lnbh->reg[0] == 0x00) {
lnbh->reg[2] = 4;
lnbh25_write_regs(lnbh, 2, 2);
} else if (lnbh->reg[2] != 0x00) {
lnbh->reg[2] = 0;
lnbh25_write_regs(lnbh, 2, 2);
}
lnbh->reg[1] |= 0x01;
lnbh25_write_regs(lnbh, 0, 3);
if (oldreg0 == 0)
msleep(100);
return 0;
}
static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
{
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
lnbh->boost = arg ? 3 : 0;
return 0;
}
static int lnbh25_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t tone)
{
/* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */
return 0;
}
static int lnbh25_init(struct lnbh25 *lnbh)
{
return lnbh25_write_regs(lnbh, 0, 2);
}
static void lnbh25_release(struct dvb_frontend *fe)
{
kfree(fe->sec_priv);
fe->sec_priv = NULL;
}
struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
u8 adr)
{
struct lnbh25 *lnbh = kzalloc(sizeof(struct lnbh25), GFP_KERNEL);
if (!lnbh)
return NULL;
lnbh->i2c = i2c;
lnbh->adr = adr;
lnbh->boost = 3;
if (lnbh25_init(lnbh)) {
kfree(lnbh);
return NULL;
}
fe->sec_priv = lnbh;
fe->ops.set_voltage = lnbh25_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbh25_enable_high_lnb_voltage;
fe->ops.release_sec = lnbh25_release;
pr_info("LNB25 on %02x\n", lnbh->adr);
return fe;
}
EXPORT_SYMBOL(lnbh25_attach);
MODULE_DESCRIPTION("LNBH25");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");

28
frontends/lnbh25.h Normal file
View File

@ -0,0 +1,28 @@
/*
* lnbh25.h
*/
#ifndef _LNBH25_H
#define _LNBH25_H
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBH25) || \
(defined(CONFIG_DVB_LNBH25_MODULE) && defined(MODULE))
extern struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
u8 i2c_addr);
#else
static inline struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
u8 i2c_addr)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

194
frontends/lnbp21.c Normal file
View File

@ -0,0 +1,194 @@
/*
* lnbp21.c - driver for lnb supply and control ic lnbp21
*
* Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de>
* Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
#include "lnbp21.h"
#include "lnbh24.h"
struct lnbp21 {
u8 config;
u8 override_or;
u8 override_and;
struct i2c_adapter *i2c;
u8 i2c_addr;
};
static int lnbp21_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
if ((lnbp21->config & LNBP21_EN) == 0)
lnbp21->config |= 0x80;
else
lnbp21->config &= 0x7f;
switch(voltage) {
case SEC_VOLTAGE_OFF:
break;
case SEC_VOLTAGE_13:
lnbp21->config |= LNBP21_EN;
break;
case SEC_VOLTAGE_18:
lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
break;
default:
return -EINVAL;
};
lnbp21->config |= lnbp21->override_or;
lnbp21->config &= lnbp21->override_and;
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
if (arg)
lnbp21->config |= LNBP21_LLC;
else
lnbp21->config &= ~LNBP21_LLC;
lnbp21->config |= lnbp21->override_or;
lnbp21->config &= lnbp21->override_and;
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static int lnbp21_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t tone)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
switch (tone) {
case SEC_TONE_OFF:
lnbp21->config &= ~LNBP21_TEN;
break;
case SEC_TONE_ON:
lnbp21->config |= LNBP21_TEN;
break;
default:
return -EINVAL;
};
lnbp21->config |= lnbp21->override_or;
lnbp21->config &= lnbp21->override_and;
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static void lnbp21_release(struct dvb_frontend *fe)
{
/* LNBP power off */
lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
/* free data */
kfree(fe->sec_priv);
fe->sec_priv = NULL;
}
static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear, u8 i2c_addr, u8 config)
{
struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
if (!lnbp21)
return NULL;
/* default configuration */
lnbp21->config = config;
lnbp21->i2c = i2c;
lnbp21->i2c_addr = i2c_addr;
fe->sec_priv = lnbp21;
/* bits which should be forced to '1' */
lnbp21->override_or = override_set;
/* bits which should be forced to '0' */
lnbp21->override_and = ~override_clear;
/* detect if it is present or not */
if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
kfree(lnbp21);
return NULL;
}
/* install release callback */
fe->ops.release_sec = lnbp21_release;
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/
fe->ops.set_tone = lnbp21_set_tone;
printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe;
}
struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear, u8 i2c_addr)
{
return lnbx2x_attach(fe, i2c, override_set, override_clear,
i2c_addr, LNBH24_TTX);
}
EXPORT_SYMBOL(lnbh24_attach);
struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear)
{
return lnbx2x_attach(fe, i2c, override_set, override_clear,
0x08, LNBP21_ISEL);
}
EXPORT_SYMBOL(lnbp21_attach);
MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24");
MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin");
MODULE_LICENSE("GPL");

75
frontends/lnbp21.h Normal file
View File

@ -0,0 +1,75 @@
/*
* lnbp21.h - driver for lnb supply and control ic lnbp21
*
* Copyright (C) 2006 Oliver Endriss
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org
*/
#ifndef _LNBP21_H
#define _LNBP21_H
/* system register bits */
/* [RO] 0=OK; 1=over current limit flag */
#define LNBP21_OLF 0x01
/* [RO] 0=OK; 1=over temperature flag (150 C) */
#define LNBP21_OTF 0x02
/* [RW] 0=disable LNB power, enable loopthrough
1=enable LNB power, disable loopthrough */
#define LNBP21_EN 0x04
/* [RW] 0=low voltage (13/14V, vert pol)
1=high voltage (18/19V,horiz pol) */
#define LNBP21_VSEL 0x08
/* [RW] increase LNB voltage by 1V:
0=13/18V; 1=14/19V */
#define LNBP21_LLC 0x10
/* [RW] 0=tone controlled by DSQIN pin
1=tone enable, disable DSQIN */
#define LNBP21_TEN 0x20
/* [RW] current limit select:
0:Iout=500-650mA Isc=300mA
1:Iout=400-550mA Isc=200mA */
#define LNBP21_ISEL 0x40
/* [RW] short-circuit protect:
0=pulsed (dynamic) curr limiting
1=static curr limiting */
#define LNBP21_PCL 0x80
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
&& defined(MODULE))
/* override_set and override_clear control which
system register bits (above) to always set & clear */
extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear);
#else
static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set,
u8 override_clear)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

1735
frontends/mxl5xx.c Normal file

File diff suppressed because it is too large Load Diff

39
frontends/mxl5xx.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _MXL5XX_H_
#define _MXL5XX_H_
#include <linux/types.h>
#include <linux/i2c.h>
struct mxl5xx_cfg {
u8 adr;
u8 type;
u32 cap;
u32 clk;
u32 ts_clk;
u8 *fw;
u32 fw_len;
int (*fw_read)(void *priv, u8 *buf, u32 len);
void *fw_priv;
};
#if defined(CONFIG_DVB_MXL5XX) || \
(defined(CONFIG_DVB_MXL5XX_MODULE) && defined(MODULE))
extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner);
#else
static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

819
frontends/mxl5xx_defs.h Normal file
View File

@ -0,0 +1,819 @@
/*
* Defines for the Maxlinear MX58x family of tuners/demods
*
* Copyright (C) 2014 Digital Devices GmbH
*
* based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*/
typedef enum
{
MXL_DISABLE = 0,
MXL_ENABLE = 1,
MXL_FALSE = 0,
MXL_TRUE = 1,
MXL_INVALID = 0,
MXL_VALID = 1,
MXL_NO = 0,
MXL_YES = 1,
MXL_OFF = 0,
MXL_ON = 1
} MXL_BOOL_E;
// Firmware-Host Command IDs
typedef enum
{
//--Device command IDs--
MXL_HYDRA_DEV_NO_OP_CMD = 0, //No OP
MXL_HYDRA_DEV_SET_POWER_MODE_CMD = 1,
MXL_HYDRA_DEV_SET_OVERWRITE_DEF_CMD = 2,
// Host-used CMD, not used by firmware
MXL_HYDRA_DEV_FIRMWARE_DOWNLOAD_CMD = 3,
// Additional CONTROL types from DTV
MXL_HYDRA_DEV_SET_BROADCAST_PID_STB_ID_CMD = 4,
MXL_HYDRA_DEV_GET_PMM_SLEEP_CMD = 5,
//--Tuner command IDs--
MXL_HYDRA_TUNER_TUNE_CMD = 6,
MXL_HYDRA_TUNER_GET_STATUS_CMD = 7,
//--Demod command IDs--
MXL_HYDRA_DEMOD_SET_PARAM_CMD = 8,
MXL_HYDRA_DEMOD_GET_STATUS_CMD = 9,
MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD = 10,
MXL_HYDRA_DEMOD_SET_PKT_NUM_CMD = 11,
MXL_HYDRA_DEMOD_SET_IQ_SOURCE_CMD = 12,
MXL_HYDRA_DEMOD_GET_IQ_DATA_CMD = 13,
MXL_HYDRA_DEMOD_GET_M68HC05_VER_CMD = 14,
MXL_HYDRA_DEMOD_SET_ERROR_COUNTER_MODE_CMD = 15,
//--- ABORT channel tune
MXL_HYDRA_ABORT_TUNE_CMD = 16, // Abort current tune command.
//--SWM/FSK command IDs--
MXL_HYDRA_FSK_RESET_CMD = 17,
MXL_HYDRA_FSK_MSG_CMD = 18,
MXL_HYDRA_FSK_SET_OP_MODE_CMD = 19,
//--DiSeqC command IDs--
MXL_HYDRA_DISEQC_MSG_CMD = 20,
MXL_HYDRA_DISEQC_COPY_MSG_TO_MAILBOX = 21,
MXL_HYDRA_DISEQC_CFG_MSG_CMD = 22,
//--- FFT Debug Command IDs--
MXL_HYDRA_REQ_FFT_SPECTRUM_CMD = 23,
// -- Demod scramblle code
MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD = 24,
//---For host to know how many commands in total---
MXL_HYDRA_LAST_HOST_CMD = 25,
MXL_HYDRA_DEMOD_INTR_TYPE_CMD = 47,
MXL_HYDRA_DEV_INTR_CLEAR_CMD = 48,
MXL_HYDRA_TUNER_SPECTRUM_REQ_CMD = 53,
MXL_HYDRA_TUNER_ACTIVATE_CMD = 55,
MXL_HYDRA_DEV_CFG_POWER_MODE_CMD = 56,
MXL_HYDRA_DEV_XTAL_CAP_CMD = 57,
MXL_HYDRA_DEV_CFG_SKU_CMD = 58,
MXL_HYDRA_TUNER_SPECTRUM_MIN_GAIN_CMD = 59,
MXL_HYDRA_DISEQC_CONT_TONE_CFG = 60,
MXL_HYDRA_DEV_RF_WAKE_UP_CMD = 61,
MXL_HYDRA_DEMOD_CFG_EQ_CTRL_PARAM_CMD = 62,
MXL_HYDRA_DEMOD_FREQ_OFFSET_SEARCH_RANGE_CMD = 63,
MXL_HYDRA_DEV_REQ_PWR_FROM_ADCRSSI_CMD = 64,
MXL_XCPU_PID_FLT_CFG_CMD = 65,
MXL_XCPU_SHMEM_TEST_CMD = 66,
MXL_XCPU_ABORT_TUNE_CMD = 67,
MXL_XCPU_CHAN_TUNE_CMD = 68,
MXL_XCPU_FLT_BOND_HDRS_CMD = 69,
MXL_HYDRA_DEV_BROADCAST_WAKE_UP_CMD = 70,
MXL_HYDRA_FSK_CFG_FSK_FREQ_CMD = 71,
MXL_HYDRA_FSK_POWER_DOWN_CMD = 72,
MXL_XCPU_CLEAR_CB_STATS_CMD = 73,
MXL_XCPU_CHAN_BOND_RESTART_CMD = 74
} MXL_HYDRA_HOST_CMD_ID_E;
#define MXL_ENABLE_BIG_ENDIAN (0)
#define MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH 248
#define MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN (248)
#define MXL_HYDRA_CAP_MIN 10
#define MXL_HYDRA_CAP_MAX 33
#define MXL_HYDRA_PLID_REG_READ 0xFB // Read register PLID
#define MXL_HYDRA_PLID_REG_WRITE 0xFC // Write register PLID
#define MXL_HYDRA_PLID_CMD_READ 0xFD // Command Read PLID
#define MXL_HYDRA_PLID_CMD_WRITE 0xFE // Command Write PLID
#define MXL_HYDRA_REG_SIZE_IN_BYTES 4 // Hydra register size in bytes
#define MXL_HYDRA_I2C_HDR_SIZE (2 * sizeof(u8)) // PLID + LEN(0xFF)
#define MXL_HYDRA_CMD_HEADER_SIZE (MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE)
#define MXL_HYDRA_SKU_ID_581 0
#define MXL_HYDRA_SKU_ID_584 1
#define MXL_HYDRA_SKU_ID_585 2
#define MXL_HYDRA_SKU_ID_544 3
#define MXL_HYDRA_SKU_ID_561 4
#define MXL_HYDRA_SKU_ID_582 5
#define MXL_HYDRA_SKU_ID_568 6
// macro for register write data buffer size (PLID + LEN (0xFF) + RegAddr + RegData)
#define MXL_HYDRA_REG_WRITE_LEN (MXL_HYDRA_I2C_HDR_SIZE + (2 * MXL_HYDRA_REG_SIZE_IN_BYTES))
// maro to extract a single byte from 4-byte(32-bit) data
#define GET_BYTE(x,n) (((x) >> (8*(n))) & 0xFF)
#define MAX_CMD_DATA 512
#define MXL_GET_REG_MASK_32(lsbLoc,numOfBits) ((0xFFFFFFFF >> (32 - (numOfBits))) << (lsbLoc))
#define GET_REG_FIELD_DATA(fieldName, dataPtr) read_by_mnemonic(state, fieldName, dataPtr);
#define SET_REG_FIELD_DATA(fieldName, data) update_by_mnemonic(state, fieldName, data);
#define FW_DL_SIGN (0xDEADBEEF)
#define MBIN_FORMAT_VERSION '1'
#define MBIN_FILE_HEADER_ID 'M'
#define MBIN_SEGMENT_HEADER_ID 'S'
#define MBIN_MAX_FILE_LENGTH (1<<23)
typedef struct
{
u8 id;
u8 fmtVersion;
u8 headerLen;
u8 numSegments;
u8 entryAddress[4];
u8 imageSize24[3];
u8 imageChecksum;
u8 reserved[4];
} MBIN_FILE_HEADER_T;
typedef struct
{
MBIN_FILE_HEADER_T header;
u8 data[1];
} MBIN_FILE_T;
typedef struct
{
u8 id;
u8 len24[3];
u8 address[4];
} MBIN_SEGMENT_HEADER_T;
typedef struct
{
MBIN_SEGMENT_HEADER_T header;
u8 data[1];
} MBIN_SEGMENT_T;
typedef enum { MXL_CMD_WRITE = 0, MXL_CMD_READ} MXL_CMD_TYPE_E;
#define BUILD_HYDRA_CMD(cmdID, reqType, size, dataPtr, cmdBuff) \
do { \
cmdBuff[0] = ((reqType == MXL_CMD_WRITE) ? MXL_HYDRA_PLID_CMD_WRITE : MXL_HYDRA_PLID_CMD_READ); \
cmdBuff[1] = (size > 251) ? 0xff : (u8) (size + 4); \
cmdBuff[2] = size; \
cmdBuff[3] = cmdID; \
cmdBuff[4] = 0x00; \
cmdBuff[5] = 0x00; \
convert_endian(MXL_ENABLE_BIG_ENDIAN, size, (u8 *)dataPtr); \
memcpy((void *)&cmdBuff[6], dataPtr, size); \
} while(0) //;
typedef struct {
u32 regAddr;
u8 lsbPos;
u8 numOfBits;
} MXL_REG_FIELD_T;
typedef struct {
u32 dataSize;
u8 data[MAX_CMD_DATA];
} MXL_DEV_CMD_DATA_T;
typedef enum
{
MXL_HYDRA_SKU_TYPE_MIN = 0x00,
MXL_HYDRA_SKU_TYPE_581 = 0x00,
MXL_HYDRA_SKU_TYPE_584 = 0x01,
MXL_HYDRA_SKU_TYPE_585 = 0x02,
MXL_HYDRA_SKU_TYPE_544 = 0x03,
MXL_HYDRA_SKU_TYPE_561 = 0x04,
MXL_HYDRA_SKU_TYPE_5xx = 0x05,
MXL_HYDRA_SKU_TYPE_5yy = 0x06,
MXL_HYDRA_SKU_TYPE_511 = 0x07,
MXL_HYDRA_SKU_TYPE_561_DE = 0x08,
MXL_HYDRA_SKU_TYPE_582 = 0x09,
MXL_HYDRA_SKU_TYPE_541 = 0x0A,
MXL_HYDRA_SKU_TYPE_568 = 0x0B,
MXL_HYDRA_SKU_TYPE_542 = 0x0C,
MXL_HYDRA_SKU_TYPE_MAX = 0x0D,
} MXL_HYDRA_SKU_TYPE_E;
typedef struct
{
MXL_HYDRA_SKU_TYPE_E skuType;
} MXL_HYDRA_SKU_COMMAND_T;
typedef enum
{
MXL_HYDRA_DEMOD_ID_0 = 0,
MXL_HYDRA_DEMOD_ID_1,
MXL_HYDRA_DEMOD_ID_2,
MXL_HYDRA_DEMOD_ID_3,
MXL_HYDRA_DEMOD_ID_4,
MXL_HYDRA_DEMOD_ID_5,
MXL_HYDRA_DEMOD_ID_6,
MXL_HYDRA_DEMOD_ID_7,
MXL_HYDRA_DEMOD_MAX
} MXL_HYDRA_DEMOD_ID_E;
#define MXL_DEMOD_SCRAMBLE_SEQ_LEN 12
#define MAX_STEP_SIZE_24_XTAL_102_05_KHZ 195
#define MAX_STEP_SIZE_24_XTAL_204_10_KHZ 215
#define MAX_STEP_SIZE_24_XTAL_306_15_KHZ 203
#define MAX_STEP_SIZE_24_XTAL_408_20_KHZ 177
#define MAX_STEP_SIZE_27_XTAL_102_05_KHZ 195
#define MAX_STEP_SIZE_27_XTAL_204_10_KHZ 215
#define MAX_STEP_SIZE_27_XTAL_306_15_KHZ 203
#define MAX_STEP_SIZE_27_XTAL_408_20_KHZ 177
#define MXL_HYDRA_SPECTRUM_MIN_FREQ_KHZ 300000
#define MXL_HYDRA_SPECTRUM_MAX_FREQ_KHZ 2350000
typedef enum
{
DMD_STANDARD_ADDR = 0,
DMD_SPECTRUM_INVERSION_ADDR,
DMD_SPECTRUM_ROLL_OFF_ADDR,
DMD_SYMBOL_RATE_ADDR,
DMD_MODULATION_SCHEME_ADDR,
DMD_FEC_CODE_RATE_ADDR,
DMD_SNR_ADDR,
DMD_FREQ_OFFSET_ADDR,
DMD_CTL_FREQ_OFFSET_ADDR,
DMD_STR_FREQ_OFFSET_ADDR,
DMD_FTL_FREQ_OFFSET_ADDR,
DMD_STR_NBC_SYNC_LOCK_ADDR,
DMD_CYCLE_SLIP_COUNT_ADDR,
DMD_DISPLAY_IQ_ADDR,
DMD_DVBS2_CRC_ERRORS_ADDR,
DMD_DVBS2_PER_COUNT_ADDR,
DMD_DVBS2_PER_WINDOW_ADDR,
DMD_DVBS_CORR_RS_ERRORS_ADDR,
DMD_DVBS_UNCORR_RS_ERRORS_ADDR,
DMD_DVBS_BER_COUNT_ADDR,
DMD_DVBS_BER_WINDOW_ADDR,
DMD_TUNER_ID_ADDR,
DMD_DVBS2_PILOT_ON_OFF_ADDR,
DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR,
MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE,
} MXL_DEMOD_CHAN_PARAMS_OFFSET_E;
typedef enum
{
MXL_HYDRA_TUNER_ID_0 = 0,
MXL_HYDRA_TUNER_ID_1,
MXL_HYDRA_TUNER_ID_2,
MXL_HYDRA_TUNER_ID_3,
MXL_HYDRA_TUNER_MAX
} MXL_HYDRA_TUNER_ID_E;
typedef enum
{
MXL_HYDRA_DSS = 0,
MXL_HYDRA_DVBS,
MXL_HYDRA_DVBS2,
} MXL_HYDRA_BCAST_STD_E;
typedef enum
{
MXL_HYDRA_FEC_AUTO = 0,
MXL_HYDRA_FEC_1_2,
MXL_HYDRA_FEC_3_5,
MXL_HYDRA_FEC_2_3,
MXL_HYDRA_FEC_3_4,
MXL_HYDRA_FEC_4_5,
MXL_HYDRA_FEC_5_6,
MXL_HYDRA_FEC_6_7,
MXL_HYDRA_FEC_7_8,
MXL_HYDRA_FEC_8_9,
MXL_HYDRA_FEC_9_10,
} MXL_HYDRA_FEC_E;
typedef enum
{
MXL_HYDRA_MOD_AUTO = 0,
MXL_HYDRA_MOD_QPSK,
MXL_HYDRA_MOD_8PSK
} MXL_HYDRA_MODULATION_E;
typedef enum
{
MXL_HYDRA_SPECTRUM_AUTO = 0,
MXL_HYDRA_SPECTRUM_INVERTED,
MXL_HYDRA_SPECTRUM_NON_INVERTED,
} MXL_HYDRA_SPECTRUM_E;
typedef enum
{
MXL_HYDRA_ROLLOFF_AUTO = 0,
MXL_HYDRA_ROLLOFF_0_20,
MXL_HYDRA_ROLLOFF_0_25,
MXL_HYDRA_ROLLOFF_0_35
} MXL_HYDRA_ROLLOFF_E;
typedef enum
{
MXL_HYDRA_PILOTS_OFF = 0,
MXL_HYDRA_PILOTS_ON,
MXL_HYDRA_PILOTS_AUTO
} MXL_HYDRA_PILOTS_E;
typedef enum
{
MXL_HYDRA_FORMATTER = 0,
MXL_HYDRA_LEGACY_FEC,
MXL_HYDRA_FREQ_RECOVERY,
MXL_HYDRA_NBC,
MXL_HYDRA_CTL,
MXL_HYDRA_EQ,
} MXL_HYDRA_CONSTELLATION_SRC_E;
typedef struct
{
int agcLock; // AGC lock info
int fecLock; // Demod FEC block lock info
} MXL_HYDRA_DEMOD_LOCK_T;
typedef struct
{
u32 rsErrors; // RS decoder err counter
u32 berWindow; // Ber Windows
u32 berCount; // BER count
u32 berWindow_Iter1; // Ber Windows - post viterbi
u32 berCount_Iter1; // BER count - post viterbi
} MXL_HYDRA_DEMOD_STATUS_DVBS_T;
typedef struct
{
u32 rsErrors; // RS decoder err counter
u32 berWindow; // Ber Windows
u32 berCount; // BER count
} MXL_HYDRA_DEMOD_STATUS_DSS_T;
typedef struct
{
u32 crcErrors; // CRC error counter
u32 packetErrorCount; // Number of packet errors
u32 totalPackets; // Total packets
} MXL_HYDRA_DEMOD_STATUS_DVBS2_T;
typedef struct
{
MXL_HYDRA_BCAST_STD_E standardMask; // Standard DVB-S, DVB-S2 or DSS
union
{
MXL_HYDRA_DEMOD_STATUS_DVBS_T demodStatus_DVBS; // DVB-S demod status
MXL_HYDRA_DEMOD_STATUS_DVBS2_T demodStatus_DVBS2; // DVB-S2 demod status
MXL_HYDRA_DEMOD_STATUS_DSS_T demodStatus_DSS; // DSS demod status
} u;
} MXL_HYDRA_DEMOD_STATUS_T;
typedef struct
{
s32 carrierOffsetInHz; // CRL offset info
s32 symbolOffsetInSymbol; // SRL offset info
} MXL_HYDRA_DEMOD_SIG_OFFSET_INFO_T;
typedef struct
{
u8 scrambleSequence[MXL_DEMOD_SCRAMBLE_SEQ_LEN]; // scramble sequence
u32 scrambleCode; // scramble gold code
} MXL_HYDRA_DEMOD_SCRAMBLE_INFO_T;
typedef enum
{
MXL_HYDRA_STEP_SIZE_24_XTAL_102_05KHZ, // 102.05 KHz for 24 MHz XTAL
MXL_HYDRA_STEP_SIZE_24_XTAL_204_10KHZ, // 204.10 KHz for 24 MHz XTAL
MXL_HYDRA_STEP_SIZE_24_XTAL_306_15KHZ, // 306.15 KHz for 24 MHz XTAL
MXL_HYDRA_STEP_SIZE_24_XTAL_408_20KHZ, // 408.20 KHz for 24 MHz XTAL
MXL_HYDRA_STEP_SIZE_27_XTAL_102_05KHZ, // 102.05 KHz for 27 MHz XTAL
MXL_HYDRA_STEP_SIZE_27_XTAL_204_35KHZ, // 204.35 KHz for 27 MHz XTAL
MXL_HYDRA_STEP_SIZE_27_XTAL_306_52KHZ, // 306.52 KHz for 27 MHz XTAL
MXL_HYDRA_STEP_SIZE_27_XTAL_408_69KHZ, // 408.69 KHz for 27 MHz XTAL
} MXL_HYDRA_SPECTRUM_STEP_SIZE_E;
typedef enum
{
MXL_HYDRA_SPECTRUM_RESOLUTION_00_1_DB, // 0.1 dB
MXL_HYDRA_SPECTRUM_RESOLUTION_01_0_DB, // 1.0 dB
MXL_HYDRA_SPECTRUM_RESOLUTION_05_0_DB, // 5.0 dB
MXL_HYDRA_SPECTRUM_RESOLUTION_10_0_DB, // 10 dB
} MXL_HYDRA_SPECTRUM_RESOLUTION_E;
typedef enum
{
MXL_SPECTRUM_NO_ERROR,
MXL_SPECTRUM_INVALID_PARAMETER,
MXL_SPECTRUM_INVALID_STEP_SIZE,
MXL_SPECTRUM_BW_CANNOT_BE_COVERED,
MXL_SPECTRUM_DEMOD_BUSY,
MXL_SPECTRUM_TUNER_NOT_ENABLED,
} MXL_HYDRA_SPECTRUM_ERROR_CODE_E;
typedef struct
{
u32 tunerIndex; // TUNER Ctrl: one of MXL58x_TUNER_ID_E
u32 demodIndex; // DEMOD Ctrl: one of MXL58x_DEMOD_ID_E
MXL_HYDRA_SPECTRUM_STEP_SIZE_E stepSizeInKHz;
u32 startingFreqInkHz;
u32 totalSteps;
MXL_HYDRA_SPECTRUM_RESOLUTION_E spectrumDivision;
} MXL_HYDRA_SPECTRUM_REQ_T;
typedef enum
{
MXL_HYDRA_SEARCH_MAX_OFFSET = 0, // DMD searches for max freq offset (i.e. 5MHz)
MXL_HYDRA_SEARCH_BW_PLUS_ROLLOFF, // DMD searches for BW + ROLLOFF/2
} MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E;
typedef struct
{
u32 demodIndex;
MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E searchType;
} MXL58x_CFG_FREQ_OFF_SEARCH_RANGE_T;
// there are two slices
// slice0 - TS0, TS1, TS2 & TS3
// slice1 - TS4, TS5, TS6 & TS7
#define MXL_HYDRA_TS_SLICE_MAX 2
#define MAX_FIXED_PID_NUM 32
#define MXL_HYDRA_NCO_CLK 418 // 418 MHz
#define MXL_HYDRA_MAX_TS_CLOCK 139 // 139 MHz
#define MXL_HYDRA_TS_FIXED_PID_FILT_SIZE 32
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_DEFAULT 33 // Shared PID filter size in 1-1 mux mode
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_2_TO_1 66 // Shared PID filter size in 2-1 mux mode
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_4_TO_1 132 // Shared PID filter size in 4-1 mux mode
typedef enum
{
MXL_HYDRA_SOFTWARE_PID_BANK = 0,
MXL_HYDRA_HARDWARE_PID_BANK,
} MXL_HYDRA_PID_BANK_TYPE_E;
typedef enum
{
MXL_HYDRA_TS_MUX_PID_REMAP = 0,
MXL_HYDRA_TS_MUX_PREFIX_EXTRA_HEADER = 1,
} MXL_HYDRA_TS_MUX_MODE_E;
typedef enum
{
MXL_HYDRA_TS_MUX_DISABLE = 0, // No Mux ( 1 TSIF to 1 TSIF)
MXL_HYDRA_TS_MUX_2_TO_1, // Mux 2 TSIF to 1 TSIF
MXL_HYDRA_TS_MUX_4_TO_1, // Mux 4 TSIF to 1 TSIF
} MXL_HYDRA_TS_MUX_TYPE_E;
typedef enum
{
MXL_HYDRA_TS_GROUP_0_3 = 0, // TS group 0 to 3 (TS0, TS1, TS2 & TS3)
MXL_HYDRA_TS_GROUP_4_7, // TS group 0 to 3 (TS4, TS5, TS6 & TS7)
} MXL_HYDRA_TS_GROUP_E;
typedef enum
{
MXL_HYDRA_TS_PIDS_ALLOW_ALL = 0, // Allow all pids
MXL_HYDRA_TS_PIDS_DROP_ALL, // Drop all pids
MXL_HYDRA_TS_INVALIDATE_PID_FILTER, // Delete current PD filter in the device
} MXL_HYDRA_TS_PID_FLT_CTRL_E;
typedef enum
{
MXL_HYDRA_TS_PID_FIXED = 0,
MXL_HYDRA_TS_PID_REGULAR,
} MXL_HYDRA_TS_PID_TYPE_E;
typedef struct
{
u16 originalPid; // pid from TS
u16 remappedPid; // remapped pid
MXL_BOOL_E enable; // enable or disable pid
MXL_BOOL_E allowOrDrop; // allow or drop pid
MXL_BOOL_E enablePidRemap; // enable or disable pid remap
u8 bondId; // Bond ID in A0 always 0 - Only for 568 Sku
u8 destId; // Output port ID for the PID - Only for 568 Sku
} MXL_HYDRA_TS_PID_T;
typedef struct
{
MXL_BOOL_E enable;
u8 numByte;
u8 header[12];
} MXL_HYDRA_TS_MUX_PREFIX_HEADER_T;
typedef enum
{
MXL_HYDRA_PID_BANK_A = 0,
MXL_HYDRA_PID_BANK_B,
} MXL_HYDRA_PID_FILTER_BANK_E;
typedef enum
{
MXL_HYDRA_MPEG_SERIAL_MSB_1ST = 0,
MXL_HYDRA_MPEG_SERIAL_LSB_1ST,
MXL_HYDRA_MPEG_SYNC_WIDTH_BIT = 0,
MXL_HYDRA_MPEG_SYNC_WIDTH_BYTE
} MXL_HYDRA_MPEG_DATA_FMT_E;
typedef enum
{
MXL_HYDRA_MPEG_MODE_SERIAL_4_WIRE = 0, // MPEG 4 Wire serial mode
MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE, // MPEG 3 Wire serial mode
MXL_HYDRA_MPEG_MODE_SERIAL_2_WIRE, // MPEG 2 Wire serial mode
MXL_HYDRA_MPEG_MODE_PARALLEL // MPEG parallel mode - valid only for MxL581
} MXL_HYDRA_MPEG_MODE_E;
typedef enum
{
MXL_HYDRA_MPEG_CLK_CONTINUOUS = 0, // Continuous MPEG clock
MXL_HYDRA_MPEG_CLK_GAPPED, // Gapped (gated) MPEG clock
} MXL_HYDRA_MPEG_CLK_TYPE_E;
typedef enum
{
MXL_HYDRA_MPEG_ACTIVE_LOW = 0,
MXL_HYDRA_MPEG_ACTIVE_HIGH,
MXL_HYDRA_MPEG_CLK_NEGATIVE = 0,
MXL_HYDRA_MPEG_CLK_POSITIVE,
MXL_HYDRA_MPEG_CLK_IN_PHASE = 0,
MXL_HYDRA_MPEG_CLK_INVERTED,
} MXL_HYDRA_MPEG_CLK_FMT_E;
typedef enum
{
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG = 0,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_90_DEG,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_180_DEG,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_270_DEG
} MXL_HYDRA_MPEG_CLK_PHASE_E;
typedef enum
{
MXL_HYDRA_MPEG_ERR_REPLACE_SYNC = 0,
MXL_HYDRA_MPEG_ERR_REPLACE_VALID,
MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED
} MXL_HYDRA_MPEG_ERR_INDICATION_E;
typedef struct
{
int enable; // Enable or Disable MPEG OUT
MXL_HYDRA_MPEG_CLK_TYPE_E mpegClkType; // Continuous or gapped
MXL_HYDRA_MPEG_CLK_FMT_E mpegClkPol; // MPEG Clk polarity
u8 maxMpegClkRate; // Max MPEG Clk rate (0 – 104 MHz, 139 MHz)
MXL_HYDRA_MPEG_CLK_PHASE_E mpegClkPhase; // MPEG Clk phase
MXL_HYDRA_MPEG_DATA_FMT_E lsbOrMsbFirst; // LSB first or MSB first in TS transmission
MXL_HYDRA_MPEG_DATA_FMT_E mpegSyncPulseWidth; // MPEG SYNC pulse width (1-bit or 1-byte)
MXL_HYDRA_MPEG_CLK_FMT_E mpegValidPol; // MPEG VALID polarity
MXL_HYDRA_MPEG_CLK_FMT_E mpegSyncPol; // MPEG SYNC polarity
MXL_HYDRA_MPEG_MODE_E mpegMode; // config 4/3/2-wire serial or parallel TS out
MXL_HYDRA_MPEG_ERR_INDICATION_E mpegErrorIndication; // Enable or Disable MPEG error indication
} MXL_HYDRA_MPEGOUT_PARAM_T;
typedef enum
{
MXL_HYDRA_EXT_TS_IN_0 = 0,
MXL_HYDRA_EXT_TS_IN_1,
MXL_HYDRA_EXT_TS_IN_2,
MXL_HYDRA_EXT_TS_IN_3,
MXL_HYDRA_EXT_TS_IN_MAX
} MXL_HYDRA_EXT_TS_IN_ID_E;
typedef enum
{
MXL_HYDRA_TS_OUT_0 = 0,
MXL_HYDRA_TS_OUT_1,
MXL_HYDRA_TS_OUT_2,
MXL_HYDRA_TS_OUT_3,
MXL_HYDRA_TS_OUT_4,
MXL_HYDRA_TS_OUT_5,
MXL_HYDRA_TS_OUT_6,
MXL_HYDRA_TS_OUT_7,
MXL_HYDRA_TS_OUT_MAX
} MXL_HYDRA_TS_OUT_ID_E;
typedef enum
{
MXL_HYDRA_TS_DRIVE_STRENGTH_1x = 0,
MXL_HYDRA_TS_DRIVE_STRENGTH_2x,
MXL_HYDRA_TS_DRIVE_STRENGTH_3x,
MXL_HYDRA_TS_DRIVE_STRENGTH_4x,
MXL_HYDRA_TS_DRIVE_STRENGTH_5x,
MXL_HYDRA_TS_DRIVE_STRENGTH_6x,
MXL_HYDRA_TS_DRIVE_STRENGTH_7x,
MXL_HYDRA_TS_DRIVE_STRENGTH_8x
} MXL_HYDRA_TS_DRIVE_STRENGTH_E;
typedef enum
{
MXL_HYDRA_DEVICE_581 = 0,
MXL_HYDRA_DEVICE_584,
MXL_HYDRA_DEVICE_585,
MXL_HYDRA_DEVICE_544,
MXL_HYDRA_DEVICE_561,
MXL_HYDRA_DEVICE_TEST,
MXL_HYDRA_DEVICE_582,
MXL_HYDRA_DEVICE_541,
MXL_HYDRA_DEVICE_568,
MXL_HYDRA_DEVICE_542,
MXL_HYDRA_DEVICE_541S,
MXL_HYDRA_DEVICE_561S,
MXL_HYDRA_DEVICE_581S,
MXL_HYDRA_DEVICE_MAX
} MXL_HYDRA_DEVICE_E;
// Demod IQ data
typedef struct
{
u32 demodId;
u32 sourceOfIQ; // ==0, it means I/Q comes from Formatter
// ==1, Legacy FEC
// ==2, Frequency Recovery
// ==3, NBC
// ==4, CTL
// ==5, EQ
// ==6, FPGA
} MXL_HYDRA_DEMOD_IQ_SRC_T;
typedef struct
{
u32 demodId;
} MXL_HYDRA_DEMOD_ABORT_TUNE_T;
typedef struct
{
u8 tunerId;
u8 enable;
} MxL_HYDRA_TUNER_CMD;
// Demod Para for Channel Tune
typedef struct
{
u32 tunerIndex;
u32 demodIndex;
u32 frequencyInHz; // Frequency
u32 standard; // one of MXL_HYDRA_BCAST_STD_E
u32 spectrumInversion; // Input : Spectrum inversion.
u32 rollOff; /* rollOff (alpha) factor */
u32 symbolRateInHz; /* Symbol rate */
u32 pilots; /* TRUE = pilots enabled */
u32 modulationScheme; // Input : Modulation Scheme is one of MXL_HYDRA_MODULATION_E
u32 fecCodeRate; // Input : Forward error correction rate. Is one of MXL_HYDRA_FEC_E
u32 maxCarrierOffsetInMHz; // Maximum carrier freq offset in MHz. Same as freqSearchRangeKHz, but in unit of MHz.
} MXL_HYDRA_DEMOD_PARAM_T;
typedef struct
{
u32 demodIndex;
u8 scrambleSequence[12]; // scramble sequence
u32 scrambleCode; // scramble gold code
} MXL_HYDRA_DEMOD_SCRAMBLE_CODE_T;
typedef struct
{
u32 intrType;
u32 intrDurationInNanoSecs;
u32 intrMask;
} MXL_INTR_CFG_T;
typedef struct
{
u8 powerMode; // enumeration values are defined in MXL_HYDRA_PWR_MODE_E (device API.h)
} MxL_HYDRA_POWER_MODE_CMD;
typedef struct
{
u32 timeIntervalInSeconds; // in seconds
u32 tunerIndex;
s32 rssiThreshold;
} MXL_HYDRA_RF_WAKEUP_PARAM_T;
typedef struct
{
u32 tunerCount;
MXL_HYDRA_RF_WAKEUP_PARAM_T params;
} MXL_HYDRA_RF_WAKEUP_CFG_T;
typedef enum
{
MXL_HYDRA_AUX_CTRL_MODE_FSK = 0, // Select FSK controller
MXL_HYDRA_AUX_CTRL_MODE_DISEQC, // Select DiSEqC controller
} MXL_HYDRA_AUX_CTRL_MODE_E;
typedef enum
{
MXL_HYDRA_DISEQC_ENVELOPE_MODE = 0,
MXL_HYDRA_DISEQC_TONE_MODE,
} MXL_HYDRA_DISEQC_OPMODE_E;
typedef enum
{
MXL_HYDRA_DISEQC_1_X = 0, // Config DiSEqC 1.x mode
MXL_HYDRA_DISEQC_2_X, // Config DiSEqC 2.x mode
MXL_HYDRA_DISEQC_DISABLE // Disable DiSEqC
} MXL_HYDRA_DISEQC_VER_E;
typedef enum
{
MXL_HYDRA_DISEQC_CARRIER_FREQ_22KHZ= 0, // DiSEqC signal frequency of 22 KHz
MXL_HYDRA_DISEQC_CARRIER_FREQ_33KHZ, // DiSEqC signal frequency of 33 KHz
MXL_HYDRA_DISEQC_CARRIER_FREQ_44KHZ // DiSEqC signal frequency of 44 KHz
} MXL_HYDRA_DISEQC_CARRIER_FREQ_E;
typedef enum
{
MXL_HYDRA_DISEQC_ID_0 = 0,
MXL_HYDRA_DISEQC_ID_1,
MXL_HYDRA_DISEQC_ID_2,
MXL_HYDRA_DISEQC_ID_3
} MXL_HYDRA_DISEQC_ID_E;
typedef enum
{
MXL_HYDRA_FSK_CFG_TYPE_39KPBS = 0, // 39.0kbps
MXL_HYDRA_FSK_CFG_TYPE_39_017KPBS, // 39.017kbps
MXL_HYDRA_FSK_CFG_TYPE_115_2KPBS // 115.2kbps
} MXL_HYDRA_FSK_OP_MODE_E;
typedef struct
{
u32 diseqcId; // DSQ 0, 1, 2 or 3
u32 opMode; // Envelope mode (0) or internal tone mode (1)
u32 version; // 0: 1.0 , 1: 1.1 , 2: Disable
u32 centerFreq; // 0: 22KHz, 1: 33KHz and 2: 44 KHz
}MXL58x_DSQ_OP_MODE_T;
typedef struct
{
u32 diseqcId;
u32 contToneFlag; // 1: Enable , 0: Disable
} MXL_HYDRA_DISEQC_CFG_CONT_TONE_T;

941
frontends/mxl5xx_regs.h Normal file
View File

@ -0,0 +1,941 @@
/*
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
*
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* This program may alternatively be licensed under a proprietary license from
* MaxLinear, Inc.
*
* See terms and conditions defined in file 'LICENSE.txt', which is part of this
* source code package.
*/
#ifndef __MXL58X_REGISTERS_H__
#define __MXL58X_REGISTERS_H__
#ifdef __cplusplus
extern "C" {
#endif
#define HYDRA_INTR_STATUS_REG 0x80030008
#define HYDRA_INTR_MASK_REG 0x8003000C
#define HYDRA_CRYSTAL_SETTING 0x3FFFC5F0 // 0 - 24 MHz & 1 - 27 MHz
#define HYDRA_CRYSTAL_CAP 0x3FFFEDA4 // 0 - 24 MHz & 1 - 27 MHz
#define HYDRA_CPU_RESET_REG 0x8003003C
#define HYDRA_CPU_RESET_DATA 0x00000400
#define HYDRA_RESET_TRANSPORT_FIFO_REG 0x80030028
#define HYDRA_RESET_TRANSPORT_FIFO_DATA 0x00000000
#define HYDRA_RESET_BBAND_REG 0x80030024
#define HYDRA_RESET_BBAND_DATA 0x00000000
#define HYDRA_RESET_XBAR_REG 0x80030020
#define HYDRA_RESET_XBAR_DATA 0x00000000
#define HYDRA_MODULES_CLK_1_REG 0x80030014
#define HYDRA_DISABLE_CLK_1 0x00000000
#define HYDRA_MODULES_CLK_2_REG 0x8003001C
#define HYDRA_DISABLE_CLK_2 0x0000000B
#define HYDRA_PRCM_ROOT_CLK_REG 0x80030018
#define HYDRA_PRCM_ROOT_CLK_DISABLE 0x00000000
#define HYDRA_CPU_RESET_CHECK_REG 0x80030008
#define HYDRA_CPU_RESET_CHECK_OFFSET 0x40000000 // <bit 30>
#define HYDRA_SKU_ID_REG 0x90000190
#define FW_DL_SIGN_ADDR 0x3FFFEAE0
// Register to check if FW is running or not
#define HYDRA_HEAR_BEAT 0x3FFFEDDC
// Firmware version
#define HYDRA_FIRMWARE_VERSION 0x3FFFEDB8
#define HYDRA_FW_RC_VERSION 0x3FFFCFAC
// Firmware patch version
#define HYDRA_FIRMWARE_PATCH_VERSION 0x3FFFEDC2
// SOC operating temperature in C
#define HYDRA_TEMPARATURE 0x3FFFEDB4
// Demod & Tuner status registers
// Demod 0 status base address
#define HYDRA_DEMOD_0_BASE_ADDR 0x3FFFC64C
// Tuner 0 status base address
#define HYDRA_TUNER_0_BASE_ADDR 0x3FFFCE4C
#define POWER_FROM_ADCRSSI_READBACK 0x3FFFEB6C
// Macros to determine base address of respective demod or tuner
#define HYDRA_DMD_STATUS_OFFSET(demodID) ((demodID) * 0x100)
#define HYDRA_TUNER_STATUS_OFFSET(tunerID) ((tunerID) * 0x40)
// Demod status address offset from respective demod's base address
#define HYDRA_DMD_AGC_DIG_LEVEL_ADDR_OFFSET 0x3FFFC64C
#define HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET 0x3FFFC650
#define HYDRA_DMD_ACQ_STATUS_ADDR_OFFSET 0x3FFFC654
#define HYDRA_DMD_STANDARD_ADDR_OFFSET 0x3FFFC658
#define HYDRA_DMD_SPECTRUM_INVERSION_ADDR_OFFSET 0x3FFFC65C
#define HYDRA_DMD_SPECTRUM_ROLL_OFF_ADDR_OFFSET 0x3FFFC660
#define HYDRA_DMD_SYMBOL_RATE_ADDR_OFFSET 0x3FFFC664
#define HYDRA_DMD_MODULATION_SCHEME_ADDR_OFFSET 0x3FFFC668
#define HYDRA_DMD_FEC_CODE_RATE_ADDR_OFFSET 0x3FFFC66C
#define HYDRA_DMD_SNR_ADDR_OFFSET 0x3FFFC670
#define HYDRA_DMD_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC674
#define HYDRA_DMD_CTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC678
#define HYDRA_DMD_STR_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC67C
#define HYDRA_DMD_FTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC680
#define HYDRA_DMD_STR_NBC_SYNC_LOCK_ADDR_OFFSET 0x3FFFC684
#define HYDRA_DMD_CYCLE_SLIP_COUNT_ADDR_OFFSET 0x3FFFC688
#define HYDRA_DMD_DISPLAY_I_ADDR_OFFSET 0x3FFFC68C
#define HYDRA_DMD_DISPLAY_Q_ADDR_OFFSET 0x3FFFC68E
#define HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET 0x3FFFC690
#define HYDRA_DMD_DVBS2_PER_COUNT_ADDR_OFFSET 0x3FFFC694
#define HYDRA_DMD_DVBS2_PER_WINDOW_ADDR_OFFSET 0x3FFFC698
#define HYDRA_DMD_DVBS_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC69C
#define HYDRA_DMD_DVBS_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6A0
#define HYDRA_DMD_DVBS_BER_COUNT_ADDR_OFFSET 0x3FFFC6A4
#define HYDRA_DMD_DVBS_BER_WINDOW_ADDR_OFFSET 0x3FFFC6A8
// Debug-purpose DVB-S DMD 0
#define HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6C8 // corrected RS Errors: 1st iteration
#define HYDRA_DMD_DVBS_1ST_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6CC // uncorrected RS Errors: 1st iteration
#define HYDRA_DMD_DVBS_BER_COUNT_1ST_ADDR_OFFSET 0x3FFFC6D0
#define HYDRA_DMD_DVBS_BER_WINDOW_1ST_ADDR_OFFSET 0x3FFFC6D4
#define HYDRA_DMD_TUNER_ID_ADDR_OFFSET 0x3FFFC6AC
#define HYDRA_DMD_DVBS2_PILOT_ON_OFF_ADDR_OFFSET 0x3FFFC6B0
#define HYDRA_DMD_FREQ_SEARCH_RANGE_KHZ_ADDR_OFFSET 0x3FFFC6B4
#define HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET 0x3FFFC6B8
#define HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR 0x3FFFC704
#define HYDRA_DMD_STATUS_INPUT_POWER_ADDR 0x3FFFC708
// DVB-S new scaled_BER_count for a new BER API, see HYDRA-1343 "DVB-S post viterbi information"
#define DMD0_STATUS_DVBS_1ST_SCALED_BER_COUNT_ADDR 0x3FFFC710 // DMD 0: 1st iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR
#define DMD0_STATUS_DVBS_SCALED_BER_COUNT_ADDR 0x3FFFC714 // DMD 0: 2nd iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR
#define DMD0_SPECTRUM_MIN_GAIN_STATUS 0x3FFFC73C
#define DMD0_SPECTRUM_MIN_GAIN_WB_SAGC_VALUE 0x3FFFC740
#define DMD0_SPECTRUM_ MIN_GAIN_NB_SAGC_VALUE 0x3FFFC744
#define HYDRA_DMD_STATUS_END_ADDR_OFFSET 0x3FFFC748
// Tuner status address offset from respective tuners's base address
#define HYDRA_TUNER_DEMOD_ID_ADDR_OFFSET 0x3FFFCE4C
#define HYDRA_TUNER_AGC_LOCK_OFFSET 0x3FFFCE50
#define HYDRA_TUNER_SPECTRUM_STATUS_OFFSET 0x3FFFCE54
#define HYDRA_TUNER_SPECTRUM_BIN_SIZE_OFFSET 0x3FFFCE58
#define HYDRA_TUNER_SPECTRUM_ADDRESS_OFFSET 0x3FFFCE5C
#define HYDRA_TUNER_ENABLE_COMPLETE 0x3FFFEB78
#define HYDRA_DEMOD_STATUS_LOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_YES)
#define HYDRA_DEMOD_STATUS_UNLOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_NO)
#define HYDRA_TUNER_STATUS_LOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_YES)
#define HYDRA_TUNER_STATUS_UNLOCK(devId,tunerId) MxLWare_HYDRA_WriteRegister(devId,(HYDRA_TUNER_STATUS_LOCK_ADDR_OFFSET + HYDRA_TUNER_STATUS_OFFSET(tunerId)), MXL_NO)
#define HYDRA_VERSION 0x3FFFEDB8
#define HYDRA_DEMOD0_VERSION 0x3FFFEDBC
#define HYDRA_DEMOD1_VERSION 0x3FFFEDC0
#define HYDRA_DEMOD2_VERSION 0x3FFFEDC4
#define HYDRA_DEMOD3_VERSION 0x3FFFEDC8
#define HYDRA_DEMOD4_VERSION 0x3FFFEDCC
#define HYDRA_DEMOD5_VERSION 0x3FFFEDD0
#define HYDRA_DEMOD6_VERSION 0x3FFFEDD4
#define HYDRA_DEMOD7_VERSION 0x3FFFEDD8
#define HYDRA_HEAR_BEAT 0x3FFFEDDC
#define HYDRA_SKU_MGMT 0x3FFFEBC0
#define MXL_HYDRA_FPGA_A_ADDRESS 0x91C00000
#define MXL_HYDRA_FPGA_B_ADDRESS 0x91D00000
// TS control base address
#define HYDRA_TS_CTRL_BASE_ADDR 0x90700000
#define MPEG_MUX_MODE_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08
#define MPEG_MUX_MODE_SLICE0_OFFSET (0),(2)
#define MPEG_MUX_MODE_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x08
#define MPEG_MUX_MODE_SLICE1_OFFSET (2),(2)
#define PID_BANK_SEL_SLICE0_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190
#define PID_BANK_SEL_SLICE1_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0
#define SW_REGULAR_PID_SW_BANK_OFFSET 0,1
#define SW_FIXED_PID_SW_BANK_OFFSET 1,1
#define HW_REGULAR_PID_BANK_OFFSET 8,4
#define HW_FIXED_PID_BANK_OFFSET 4,4
#define MPEG_CLK_GATED_REG HYDRA_TS_CTRL_BASE_ADDR + 0x20
#define MPEG_CLK_GATED_OFFSET 0,1
#define MPEG_CLK_ALWAYS_ON_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1D4
#define MPEG_CLK_ALWAYS_ON_OFFSET 0,1
#define HYDRA_REGULAR_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190
#define HYDRA_REGULAR_PID_BAN K_A_OFFSET 0,1
#define HYDRA_FIXED_PID_BANK_A_REG HYDRA_TS_CTRL_BASE_ADDR + 0x190
#define HYDRA_FIXED_PID_BANK_A_OFFSET 1,1
#define HYDRA_REGULAR_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0
#define HYDRA_REGULAR_PID_BANK_B_OFFSET 0,1
#define HYDRA_FIXED_PID_BANK_B_REG HYDRA_TS_CTRL_BASE_ADDR + 0x1B0
#define HYDRA_FIXED_PID_BANK_B_OFFSET 1,1
#define FIXED_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x9000
#define FIXED_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x9100
#define FIXED_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x9200
#define FIXED_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x9300
#define FIXED_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xB000
#define FIXED_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xB100
#define FIXED_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xB200
#define FIXED_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xB300
#define REGULAR_PID_TBL_REG_ADDRESS_0 HYDRA_TS_CTRL_BASE_ADDR + 0x8000
#define REGULAR_PID_TBL_REG_ADDRESS_1 HYDRA_TS_CTRL_BASE_ADDR + 0x8200
#define REGULAR_PID_TBL_REG_ADDRESS_2 HYDRA_TS_CTRL_BASE_ADDR + 0x8400
#define REGULAR_PID_TBL_REG_ADDRESS_3 HYDRA_TS_CTRL_BASE_ADDR + 0x8600
#define REGULAR_PID_TBL_REG_ADDRESS_4 HYDRA_TS_CTRL_BASE_ADDR + 0xA000
#define REGULAR_PID_TBL_REG_ADDRESS_5 HYDRA_TS_CTRL_BASE_ADDR + 0xA200
#define REGULAR_PID_TBL_REG_ADDRESS_6 HYDRA_TS_CTRL_BASE_ADDR + 0xA400
#define REGULAR_PID_TBL_REG_ADDRESS_7 HYDRA_TS_CTRL_BASE_ADDR + 0xA600
#define PID_VALID_OFFSET 0,1
#define PID_DROP_OFFSET 1,1
#define PID_REMAP_ENABLE_OFFSET 2,1
#define PID_VALUE_OFFSET 4,13
#define PID_MASK_OFFSET 19,13
#define REGULAR_PID_REMAP_VALUE_OFFSET 0,13
#define FIXED_PID_REMAP_VALUE_OFFSET 0,16
#define PID_DEMODID_OFFSET 16,3
///////////////////////////////////////////////
#if 0
#define AFE_REG_D2A_TA_ADC_CLK_OUT_FLIP 0x90200004,12,1
#define AFE_REG_D2A_TA_RFFE_LNACAPLOAD_1P8 0x90200028,24,4
#define AFE_REG_D2A_TA_RFFE_RF1_EN_1P8 0x90200028,5,1
#define AFE_REG_D2A_TA_RFFE_SPARE_1P8 0x90200028,8,8
#define AFE_REG_D2A_TB_ADC_CLK_OUT_FLIP 0x9020000C,23,1
#define AFE_REG_D2A_TB_RFFE_LNACAPLOAD_1P8 0x90200030,16,4
#define AFE_REG_D2A_TB_RFFE_RF1_EN_1P8 0x9020002C,21,1
#define AFE_REG_D2A_TB_RFFE_SPARE_1P8 0x90200030,0,8
#define AFE_REG_D2A_TC_ADC_CLK_OUT_FLIP 0x90200018,7,1
#define AFE_REG_D2A_TC_RFFE_LNACAPLOAD_1P8 0x90200038,2,4
#define AFE_REG_D2A_TC_RFFE_RF1_EN_1P8 0x90200034,14,1
#define AFE_REG_D2A_TC_RFFE_SPARE_1P8 0x90200034,17,8
#define AFE_REG_D2A_TD_ADC_CLK_OUT_FLIP 0x90200020,18,1
#define AFE_REG_D2A_TD_RFFE_LNACAPLOAD_1P8 0x9020003C,17,4
#define AFE_REG_D2A_TD_RFFE_RF1_EN_1P8 0x90200038,29,1
#define AFE_REG_D2A_TD_RFFE_SPARE_1P8 0x9020003C,1,8
#endif
#define AFE_REG_D2A_XTAL_EN_CLKOUT_1P8 0x90200054,23,1
#define PAD_MUX_TS0_IN_CLK_PINMUX_SEL 0x90000018,0,3
#define PAD_MUX_TS0_IN_DATA_PINMUX_SEL 0x90000018,4,3
#define PAD_MUX_TS1_IN_CLK_PINMUX_SEL 0x90000018,8,3
#define PAD_MUX_TS1_IN_DATA_PINMUX_SEL 0x90000018,12,3
#define PAD_MUX_TS2_IN_CLK_PINMUX_SEL 0x90000018,16,3
#define PAD_MUX_TS2_IN_DATA_PINMUX_SEL 0x90000018,20,3
#define PAD_MUX_TS3_IN_CLK_PINMUX_SEL 0x90000018,24,3
#define PAD_MUX_TS3_IN_DATA_PINMUX_SEL 0x90000018,28,3
#define PAD_MUX_GPIO_00_SYNC_BASEADDR 0x90000188
#define PAD_MUX_GPIO_01_SYNC_IN PAD_MUX_GPIO_00_SYNC_BASEADDR,1,1
#define PRCM_AFE_SOC_ID 0x80030004,24,8
#define PAD_MUX_UART_RX_C_PINMUX_BASEADDR 0x9000001C
#define PAD_MUX_UART_RX_C_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,0,3
#define PAD_MUX_UART_RX_D_PINMUX_SEL PAD_MUX_UART_RX_C_PINMUX_BASEADDR,4,3
#define PAD_MUX_BOND_OPTION 0x90000190,0,3
#define PAD_MUX_DIGIO_01_PINMUX_SEL 0x9000016C,4,3
#define PAD_MUX_DIGIO_02_PINMUX_SEL 0x9000016C,8,3
#define PAD_MUX_DIGIO_03_PINMUX_SEL 0x9000016C,12,3
#define PAD_MUX_DIGIO_04_PINMUX_SEL 0x9000016C,16,3
#define PAD_MUX_DIGIO_05_PINMUX_SEL 0x9000016C,20,3
#define PAD_MUX_DIGIO_06_PINMUX_SEL 0x9000016C,24,3
#define PAD_MUX_DIGIO_07_PINMUX_SEL 0x9000016C,28,3
#define PAD_MUX_DIGIO_08_PINMUX_SEL 0x90000170,0,3
#define PAD_MUX_DIGIO_09_PINMUX_SEL 0x90000170,4,3
#define PAD_MUX_DIGIO_10_PINMUX_SEL 0x90000170,8,3
#define PAD_MUX_DIGIO_11_PINMUX_SEL 0x90000170,12,3
#define PAD_MUX_DIGIO_12_PINMUX_SEL 0x90000170,16,3
#define PAD_MUX_DIGIO_13_PINMUX_SEL 0x90000170,20,3
#define PAD_MUX_DIGIO_14_PINMUX_SEL 0x90000170,24,3
#define PAD_MUX_DIGIO_15_PINMUX_SEL 0x90000170,28,3
#define PAD_MUX_DIGIO_16_PINMUX_SEL 0x90000174,0,3
#define PAD_MUX_DIGIO_17_PINMUX_SEL 0x90000174,4,3
#define PAD_MUX_DIGIO_18_PINMUX_SEL 0x90000174,8,3
#define PAD_MUX_DIGIO_19_PINMUX_SEL 0x90000174,12,3
#define PAD_MUX_DIGIO_20_PINMUX_SEL 0x90000174,16,3
#define PAD_MUX_DIGIO_21_PINMUX_SEL 0x90000174,20,3
#define PAD_MUX_DIGIO_22_PINMUX_SEL 0x90000174,24,3
#define PAD_MUX_DIGIO_23_PINMUX_SEL 0x90000174,28,3
#define PAD_MUX_DIGIO_24_PINMUX_SEL 0x90000178,0,3
#define PAD_MUX_DIGIO_25_PINMUX_SEL 0x90000178,4,3
#define PAD_MUX_DIGIO_26_PINMUX_SEL 0x90000178,8,3
#define PAD_MUX_DIGIO_27_PINMUX_SEL 0x90000178,12,3
#define PAD_MUX_DIGIO_28_PINMUX_SEL 0x90000178,16,3
#define PAD_MUX_DIGIO_29_PINMUX_SEL 0x90000178,20,3
#define PAD_MUX_DIGIO_30_PINMUX_SEL 0x90000178,24,3
#define PAD_MUX_DIGIO_31_PINMUX_SEL 0x90000178,28,3
#define PAD_MUX_DIGIO_32_PINMUX_SEL 0x9000017C,0,3
#define PAD_MUX_DIGIO_33_PINMUX_SEL 0x9000017C,4,3
#define PAD_MUX_DIGIO_34_PINMUX_SEL 0x9000017C,8,3
#define PAD_MUX_EJTAG_TCK_PINMUX_SEL 0x90000020,0,3
#define PAD_MUX_EJTAG_TDI_PINMUX_SEL 0x90000020,8,3
#define PAD_MUX_EJTAG_TMS_PINMUX_SEL 0x90000020,4,3
#define PAD_MUX_EJTAG_TRSTN_PINMUX_SEL 0x90000020,12,3
#define PAD_MUX_PAD_DRV_DIGIO_00 0x90000194,0,3
#define PAD_MUX_PAD_DRV_DIGIO_05 0x90000194,20,3
#define PAD_MUX_PAD_DRV_DIGIO_06 0x90000194,24,3
#define PAD_MUX_PAD_DRV_DIGIO_11 0x90000198,12,3
#define PAD_MUX_PAD_DRV_DIGIO_12 0x90000198,16,3
#define PAD_MUX_PAD_DRV_DIGIO_13 0x90000198,20,3
#define PAD_MUX_PAD_DRV_DIGIO_14 0x90000198,24,3
#define PAD_MUX_PAD_DRV_DIGIO_16 0x9000019C,0,3
#define PAD_MUX_PAD_DRV_DIGIO_17 0x9000019C,4,3
#define PAD_MUX_PAD_DRV_DIGIO_18 0x9000019C,8,3
#define PAD_MUX_PAD_DRV_DIGIO_22 0x9000019C,24,3
#define PAD_MUX_PAD_DRV_DIGIO_23 0x9000019C,28,3
#define PAD_MUX_PAD_DRV_DIGIO_24 0x900001A0,0,3
#define PAD_MUX_PAD_DRV_DIGIO_25 0x900001A0,4,3
#define PAD_MUX_PAD_DRV_DIGIO_29 0x900001A0,20,3
#define PAD_MUX_PAD_DRV_DIGIO_30 0x900001A0,24,3
#define PAD_MUX_PAD_DRV_DIGIO_31 0x900001A0,28,3
#define PRCM_AFE_REG_CLOCK_ENABLE 0x80030014,9,1
#define PRCM_CHIP_VERSION 0x80030000,12,4
#define PRCM_AFE_CHIP_MMSK_VER 0x80030004,8,8
#define PRCM_PRCM_AFE_REG_SOFT_RST_N 0x8003003C,12,1
#define PRCM_PRCM_CPU_SOFT_RST_N 0x8003003C,0,1
#define PRCM_PRCM_DIGRF_APB_DATA_BB0 0x80030074,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB1 0x80030078,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB2 0x8003007C,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB3 0x80030080,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB4 0x80030084,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB5 0x80030088,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB6 0x8003008C,0,20
#define PRCM_PRCM_DIGRF_APB_DATA_BB7 0x80030090,0,20
#define PRCM_PRCM_DIGRF_CAPT_DONE 0x80030070,24,8
#define PRCM_PRCM_DIGRF_START_CAPT 0x80030064,2,1
#define PRCM_PRCM_PAD_MUX_SOFT_RST_N 0x8003003C,11,1
#define PRCM_PRCM_XPT_PARALLEL_FIFO_RST_N 0x80030028,20,1
#define XPT_APPEND_BYTES0 0x90700008,4,2
#define XPT_APPEND_BYTES1 0x90700008,6,2
#define XPT_CLOCK_POLARITY0 0x90700010,16,1
#define XPT_CLOCK_POLARITY1 0x90700010,17,1
#define XPT_CLOCK_POLARITY2 0x90700010,18,1
#define XPT_CLOCK_POLARITY3 0x90700010,19,1
#define XPT_CLOCK_POLARITY4 0x90700010,20,1
#define XPT_CLOCK_POLARITY5 0x90700010,21,1
#define XPT_CLOCK_POLARITY6 0x90700010,22,1
#define XPT_CLOCK_POLARITY7 0x90700010,23,1
#define XPT_DSS_DVB_ENCAP_EN0 0x90700000,16,1
#define XPT_DSS_DVB_ENCAP_EN1 0x90700000,17,1
#define XPT_DSS_DVB_ENCAP_EN2 0x90700000,18,1
#define XPT_DSS_DVB_ENCAP_EN3 0x90700000,19,1
#define XPT_DSS_DVB_ENCAP_EN4 0x90700000,20,1
#define XPT_DSS_DVB_ENCAP_EN5 0x90700000,21,1
#define XPT_DSS_DVB_ENCAP_EN6 0x90700000,22,1
#define XPT_DSS_DVB_ENCAP_EN7 0x90700000,23,1
#define XPT_DVB_MATCH_BYTE 0x9070017C,16,8
#define XPT_DVB_PACKET_SIZE0 0x90700180,0,8
#define XPT_DVB_PACKET_SIZE1 0x90700180,8,8
#define XPT_DVB_PACKET_SIZE2 0x90700180,16,8
#define XPT_DVB_PACKET_SIZE3 0x90700180,24,8
#define XPT_ENABLE_DVB_INPUT0 0x90700178,0,1
#define XPT_ENABLE_DVB_INPUT1 0x90700178,1,1
#define XPT_ENABLE_DVB_INPUT2 0x90700178,2,1
#define XPT_ENABLE_DVB_INPUT3 0x90700178,3,1
#define XPT_ENABLE_INPUT0 0x90700000,0,1
#define XPT_ENABLE_INPUT1 0x90700000,1,1
#define XPT_ENABLE_INPUT2 0x90700000,2,1
#define XPT_ENABLE_INPUT3 0x90700000,3,1
#define XPT_ENABLE_INPUT4 0x90700000,4,1
#define XPT_ENABLE_INPUT5 0x90700000,5,1
#define XPT_ENABLE_INPUT6 0x90700000,6,1
#define XPT_ENABLE_INPUT7 0x90700000,7,1
#define XPT_ENABLE_OUTPUT0 0x9070000C,0,1
#define XPT_ENABLE_OUTPUT1 0x9070000C,1,1
#define XPT_ENABLE_OUTPUT2 0x9070000C,2,1
#define XPT_ENABLE_OUTPUT3 0x9070000C,3,1
#define XPT_ENABLE_OUTPUT4 0x9070000C,4,1
#define XPT_ENABLE_OUTPUT5 0x9070000C,5,1
#define XPT_ENABLE_OUTPUT6 0x9070000C,6,1
#define XPT_ENABLE_OUTPUT7 0x9070000C,7,1
#define XPT_ENABLE_PARALLEL_OUTPUT 0x90700010,27,1
#define XPT_ENABLE_PCR_COUNT 0x90700184,1,1
#define XPT_ERROR_REPLACE_SYNC0 0x9070000C,24,1
#define XPT_ERROR_REPLACE_SYNC1 0x9070000C,25,1
#define XPT_ERROR_REPLACE_SYNC2 0x9070000C,26,1
#define XPT_ERROR_REPLACE_SYNC3 0x9070000C,27,1
#define XPT_ERROR_REPLACE_SYNC4 0x9070000C,28,1
#define XPT_ERROR_REPLACE_SYNC5 0x9070000C,29,1
#define XPT_ERROR_REPLACE_SYNC6 0x9070000C,30,1
#define XPT_ERROR_REPLACE_SYNC7 0x9070000C,31,1
#define XPT_ERROR_REPLACE_VALID0 0x90700014,8,1
#define XPT_ERROR_REPLACE_VALID1 0x90700014,9,1
#define XPT_ERROR_REPLACE_VALID2 0x90700014,10,1
#define XPT_ERROR_REPLACE_VALID3 0x90700014,11,1
#define XPT_ERROR_REPLACE_VALID4 0x90700014,12,1
#define XPT_ERROR_REPLACE_VALID5 0x90700014,13,1
#define XPT_ERROR_REPLACE_VALID6 0x90700014,14,1
#define XPT_ERROR_REPLACE_VALID7 0x90700014,15,1
#define XPT_INP0_MERGE_HDR0 0x90700058,0,32
#define XPT_INP0_MERGE_HDR1 0x9070005C,0,32
#define XPT_INP0_MERGE_HDR2 0x90700060,0,32
#define XPT_INP1_MERGE_HDR0 0x90700064,0,32
#define XPT_INP1_MERGE_HDR1 0x90700068,0,32
#define XPT_INP1_MERGE_HDR2 0x9070006C,0,32
#define XPT_INP2_MERGE_HDR0 0x90700070,0,32
#define XPT_INP2_MERGE_HDR1 0x90700074,0,32
#define XPT_INP2_MERGE_HDR2 0x90700078,0,32
#define XPT_INP3_MERGE_HDR0 0x9070007C,0,32
#define XPT_INP3_MERGE_HDR1 0x90700080,0,32
#define XPT_INP3_MERGE_HDR2 0x90700084,0,32
#define XPT_INP4_MERGE_HDR0 0x90700088,0,32
#define XPT_INP4_MERGE_HDR1 0x9070008C,0,32
#define XPT_INP4_MERGE_HDR2 0x90700090,0,32
#define XPT_INP5_MERGE_HDR0 0x90700094,0,32
#define XPT_INP5_MERGE_HDR1 0x90700098,0,32
#define XPT_INP5_MERGE_HDR2 0x9070009C,0,32
#define XPT_INP6_MERGE_HDR0 0x907000A0,0,32
#define XPT_INP6_MERGE_HDR1 0x907000A4,0,32
#define XPT_INP6_MERGE_HDR2 0x907000A8,0,32
#define XPT_INP7_MERGE_HDR0 0x907000AC,0,32
#define XPT_INP7_MERGE_HDR1 0x907000B0,0,32
#define XPT_INP7_MERGE_HDR2 0x907000B4,0,32
#define XPT_INP_MODE_DSS0 0x90700000,8,1
#define XPT_INP_MODE_DSS1 0x90700000,9,1
#define XPT_INP_MODE_DSS2 0x90700000,10,1
#define XPT_INP_MODE_DSS3 0x90700000,11,1
#define XPT_INP_MODE_DSS4 0x90700000,12,1
#define XPT_INP_MODE_DSS5 0x90700000,13,1
#define XPT_INP_MODE_DSS6 0x90700000,14,1
#define XPT_INP_MODE_DSS7 0x90700000,15,1
#define XPT_KNOWN_PID_MUX_SELECT0 0x90700190,8,4
#define XPT_KNOWN_PID_MUX_SELECT1 0x907001B0,8,4
#define XPT_LSB_FIRST0 0x9070000C,16,1
#define XPT_LSB_FIRST1 0x9070000C,17,1
#define XPT_LSB_FIRST2 0x9070000C,18,1
#define XPT_LSB_FIRST3 0x9070000C,19,1
#define XPT_LSB_FIRST4 0x9070000C,20,1
#define XPT_LSB_FIRST5 0x9070000C,21,1
#define XPT_LSB_FIRST6 0x9070000C,22,1
#define XPT_LSB_FIRST7 0x9070000C,23,1
#define XPT_MODE_27MHZ 0x90700184,0,1
#define XPT_NCO_COUNT_MIN 0x90700044,16,8
#define XPT_OUTPUT_MODE_DSS0 0x9070000C,8,1
#define XPT_OUTPUT_MODE_DSS1 0x9070000C,9,1
#define XPT_OUTPUT_MODE_DSS2 0x9070000C,10,1
#define XPT_OUTPUT_MODE_DSS3 0x9070000C,11,1
#define XPT_OUTPUT_MODE_DSS4 0x9070000C,12,1
#define XPT_OUTPUT_MODE_DSS5 0x9070000C,13,1
#define XPT_OUTPUT_MODE_DSS6 0x9070000C,14,1
#define XPT_OUTPUT_MODE_DSS7 0x9070000C,15,1
#define XPT_OUTPUT_MODE_MUXGATING0 0x90700020,0,1
#define XPT_OUTPUT_MODE_MUXGATING1 0x90700020,1,1
#define XPT_OUTPUT_MODE_MUXGATING2 0x90700020,2,1
#define XPT_OUTPUT_MODE_MUXGATING3 0x90700020,3,1
#define XPT_OUTPUT_MODE_MUXGATING4 0x90700020,4,1
#define XPT_OUTPUT_MODE_MUXGATING5 0x90700020,5,1
#define XPT_OUTPUT_MODE_MUXGATING6 0x90700020,6,1
#define XPT_OUTPUT_MODE_MUXGATING7 0x90700020,7,1
#define XPT_OUTPUT_MUXSELECT0 0x9070001C,0,3
#define XPT_OUTPUT_MUXSELECT1 0x9070001C,4,3
#define XPT_OUTPUT_MUXSELECT2 0x9070001C,8,3
#define XPT_OUTPUT_MUXSELECT3 0x9070001C,12,3
#define XPT_OUTPUT_MUXSELECT4 0x9070001C,16,3
#define XPT_OUTPUT_MUXSELECT5 0x9070001C,20,3
#define XPT_PCR_RTS_CORRECTION_ENABLE 0x90700008,14,1
#define XPT_PID_DEFAULT_DROP0 0x90700190,12,1
#define XPT_PID_DEFAULT_DROP1 0x90700190,13,1
#define XPT_PID_DEFAULT_DROP2 0x90700190,14,1
#define XPT_PID_DEFAULT_DROP3 0x90700190,15,1
#define XPT_PID_DEFAULT_DROP4 0x907001B0,12,1
#define XPT_PID_DEFAULT_DROP5 0x907001B0,13,1
#define XPT_PID_DEFAULT_DROP6 0x907001B0,14,1
#define XPT_PID_DEFAULT_DROP7 0x907001B0,15,1
#define XPT_PID_MUX_SELECT0 0x90700190,4,4
#define XPT_PID_MUX_SELECT1 0x907001B0,4,4
#define XPT_STREAM_MUXMODE0 0x90700008,0,2
#define XPT_STREAM_MUXMODE1 0x90700008,2,2
#define XPT_SYNC_FULL_BYTE0 0x90700010,0,1
#define XPT_SYNC_FULL_BYTE1 0x90700010,1,1
#define XPT_SYNC_FULL_BYTE2 0x90700010,2,1
#define XPT_SYNC_FULL_BYTE3 0x90700010,3,1
#define XPT_SYNC_FULL_BYTE4 0x90700010,4,1
#define XPT_SYNC_FULL_BYTE5 0x90700010,5,1
#define XPT_SYNC_FULL_BYTE6 0x90700010,6,1
#define XPT_SYNC_FULL_BYTE7 0x90700010,7,1
#define XPT_SYNC_LOCK_THRESHOLD 0x9070017C,0,8
#define XPT_SYNC_MISS_THRESHOLD 0x9070017C,8,8
#define XPT_SYNC_POLARITY0 0x90700010,8,1
#define XPT_SYNC_POLARITY1 0x90700010,9,1
#define XPT_SYNC_POLARITY2 0x90700010,10,1
#define XPT_SYNC_POLARITY3 0x90700010,11,1
#define XPT_SYNC_POLARITY4 0x90700010,12,1
#define XPT_SYNC_POLARITY5 0x90700010,13,1
#define XPT_SYNC_POLARITY6 0x90700010,14,1
#define XPT_SYNC_POLARITY7 0x90700010,15,1
#define XPT_TS_CLK_OUT_EN0 0x907001D4,0,1
#define XPT_TS_CLK_OUT_EN1 0x907001D4,1,1
#define XPT_TS_CLK_OUT_EN2 0x907001D4,2,1
#define XPT_TS_CLK_OUT_EN3 0x907001D4,3,1
#define XPT_TS_CLK_OUT_EN4 0x907001D4,4,1
#define XPT_TS_CLK_OUT_EN5 0x907001D4,5,1
#define XPT_TS_CLK_OUT_EN6 0x907001D4,6,1
#define XPT_TS_CLK_OUT_EN7 0x907001D4,7,1
#define XPT_TS_CLK_OUT_EN_PARALLEL 0x907001D4,8,1
#define XPT_TS_CLK_PHASE0 0x90700018,0,3
#define XPT_TS_CLK_PHASE1 0x90700018,4,3
#define XPT_TS_CLK_PHASE2 0x90700018,8,3
#define XPT_TS_CLK_PHASE3 0x90700018,12,3
#define XPT_TS_CLK_PHASE4 0x90700018,16,3
#define XPT_TS_CLK_PHASE5 0x90700018,20,3
#define XPT_TS_CLK_PHASE6 0x90700018,24,3
#define XPT_TS_CLK_PHASE7 0x90700018,28,3
#define XPT_VALID_POLARITY0 0x90700014,0,1
#define XPT_VALID_POLARITY1 0x90700014,1,1
#define XPT_VALID_POLARITY2 0x90700014,2,1
#define XPT_VALID_POLARITY3 0x90700014,3,1
#define XPT_VALID_POLARITY4 0x90700014,4,1
#define XPT_VALID_POLARITY5 0x90700014,5,1
#define XPT_VALID_POLARITY6 0x90700014,6,1
#define XPT_VALID_POLARITY7 0x90700014,7,1
#define XPT_ZERO_FILL_COUNT 0x90700008,8,6
#define XPT_PACKET_GAP_MIN_BASEADDR 0x90700044
#define XPT_PACKET_GAP_MIN_TIMER XPT_PACKET_GAP_MIN_BASEADDR,0,16
#define XPT_NCO_COUNT_MIN0 XPT_PACKET_GAP_MIN_BASEADDR,16,8
#define XPT_NCO_COUNT_BASEADDR 0x90700238
#define XPT_NCO_COUNT_MIN1 XPT_NCO_COUNT_BASEADDR,0,8
#define XPT_NCO_COUNT_MIN2 XPT_NCO_COUNT_BASEADDR,8,8
#define XPT_NCO_COUNT_MIN3 XPT_NCO_COUNT_BASEADDR,16,8
#define XPT_NCO_COUNT_MIN4 XPT_NCO_COUNT_BASEADDR,24,8
#define XPT_NCO_COUNT_BASEADDR1 0x9070023C
#define XPT_NCO_COUNT_MIN5 XPT_NCO_COUNT_BASEADDR1,0,8
#define XPT_NCO_COUNT_MIN6 XPT_NCO_COUNT_BASEADDR1,8,8
#define XPT_NCO_COUNT_MIN7 XPT_NCO_COUNT_BASEADDR1,16,8
// V2 DigRF status register
#define BB0_DIGRF_CAPT_DONE 0x908000CC,0,1
#define PRCM_PRCM_CHIP_ID 0x80030000,0,12
#define XPT_PID_BASEADDR 0x90708000
#define XPT_PID_VALID0 XPT_PID_BASEADDR,0,1
#define XPT_PID_DROP0 XPT_PID_BASEADDR,1,1
#define XPT_PID_REMAP0 XPT_PID_BASEADDR,2,1
#define XPT_PID_VALUE0 XPT_PID_BASEADDR,4,13
#define XPT_PID_MASK0 XPT_PID_BASEADDR,19,13
#define XPT_PID_REMAP_BASEADDR 0x90708004
#define XPT_PID_REMAP_VALUE0 XPT_PID_REMAP_BASEADDR,0,13
#define XPT_PID_PORT_ID0 XPT_PID_REMAP_BASEADDR,16,3
#define XPT_KNOWN_PID_BASEADDR 0x90709000
#define XPT_KNOWN_PID_VALID0 XPT_KNOWN_PID_BASEADDR,0,1
#define XPT_KNOWN_PID_DROP0 XPT_KNOWN_PID_BASEADDR,1,1
#define XPT_KNOWN_PID_REMAP0 XPT_KNOWN_PID_BASEADDR,2,1
#define XPT_KNOWN_PID_REMAP_VALUE0 XPT_KNOWN_PID_BASEADDR,16,13
#define XPT_PID_BASEADDR1 0x9070A000
#define XPT_PID_VALID1 XPT_PID_BASEADDR1,0,1
#define XPT_PID_DROP1 XPT_PID_BASEADDR1,1,1
#define XPT_PID_REMAP1 XPT_PID_BASEADDR1,2,1
#define XPT_PID_VALUE1 XPT_PID_BASEADDR1,4,13
#define XPT_PID_MASK1 XPT_PID_BASEADDR1,19,13
#define XPT_PID_REMAP_BASEADDR1 0x9070A004
#define XPT_PID_REMAP_VALUE1 XPT_PID_REMAP_BASEADDR1,0,13
#define XPT_KNOWN_PID_BASEADDR1 0x9070B000
#define XPT_KNOWN_PID_VALID1 XPT_KNOWN_PID_BASEADDR1,0,1
#define XPT_KNOWN_PID_DROP1 XPT_KNOWN_PID_BASEADDR1,1,1
#define XPT_KNOWN_PID_REMAP1 XPT_KNOWN_PID_BASEADDR1,2,1
#define XPT_KNOWN_PID_REMAP_VALUE1 XPT_KNOWN_PID_BASEADDR1,16,13
#define XPT_BERT_LOCK_BASEADDR 0x907000B8
#define XPT_BERT_LOCK_THRESHOLD XPT_BERT_LOCK_BASEADDR,0,8
#define XPT_BERT_LOCK_WINDOW XPT_BERT_LOCK_BASEADDR,8,8
#define XPT_BERT_BASEADDR 0x907000BC
#define XPT_BERT_ENABLE0 XPT_BERT_BASEADDR,0,1
#define XPT_BERT_ENABLE1 XPT_BERT_BASEADDR,1,1
#define XPT_BERT_ENABLE2 XPT_BERT_BASEADDR,2,1
#define XPT_BERT_ENABLE3 XPT_BERT_BASEADDR,3,1
#define XPT_BERT_ENABLE4 XPT_BERT_BASEADDR,4,1
#define XPT_BERT_ENABLE5 XPT_BERT_BASEADDR,5,1
#define XPT_BERT_ENABLE6 XPT_BERT_BASEADDR,6,1
#define XPT_BERT_ENABLE7 XPT_BERT_BASEADDR,7,1
#define XPT_BERT_SEQUENCE_PN23_0 XPT_BERT_BASEADDR,8,1
#define XPT_BERT_SEQUENCE_PN23_1 XPT_BERT_BASEADDR,9,1
#define XPT_BERT_SEQUENCE_PN23_2 XPT_BERT_BASEADDR,10,1
#define XPT_BERT_SEQUENCE_PN23_3 XPT_BERT_BASEADDR,11,1
#define XPT_BERT_SEQUENCE_PN23_4 XPT_BERT_BASEADDR,12,1
#define XPT_BERT_SEQUENCE_PN23_5 XPT_BERT_BASEADDR,13,1
#define XPT_BERT_SEQUENCE_PN23_6 XPT_BERT_BASEADDR,14,1
#define XPT_BERT_SEQUENCE_PN23_7 XPT_BERT_BASEADDR,15,1
#define XPT_LOCK_RESYNC0 XPT_BERT_BASEADDR,16,1
#define XPT_LOCK_RESYNC1 XPT_BERT_BASEADDR,17,1
#define XPT_LOCK_RESYNC2 XPT_BERT_BASEADDR,18,1
#define XPT_LOCK_RESYNC3 XPT_BERT_BASEADDR,19,1
#define XPT_LOCK_RESYNC4 XPT_BERT_BASEADDR,20,1
#define XPT_LOCK_RESYNC5 XPT_BERT_BASEADDR,21,1
#define XPT_LOCK_RESYNC6 XPT_BERT_BASEADDR,22,1
#define XPT_LOCK_RESYNC7 XPT_BERT_BASEADDR,23,1
#define XPT_BERT_DATA_POLARITY0 XPT_BERT_BASEADDR,24,1
#define XPT_BERT_DATA_POLARITY1 XPT_BERT_BASEADDR,25,1
#define XPT_BERT_DATA_POLARITY2 XPT_BERT_BASEADDR,26,1
#define XPT_BERT_DATA_POLARITY3 XPT_BERT_BASEADDR,27,1
#define XPT_BERT_DATA_POLARITY4 XPT_BERT_BASEADDR,28,1
#define XPT_BERT_DATA_POLARITY5 XPT_BERT_BASEADDR,29,1
#define XPT_BERT_DATA_POLARITY6 XPT_BERT_BASEADDR,30,1
#define XPT_BERT_DATA_POLARITY7 XPT_BERT_BASEADDR,31,1
#define XPT_BERT_INVERT_BASEADDR 0x907000C0
#define XPT_BERT_INVERT_DATA0 XPT_BERT_INVERT_BASEADDR,0,1
#define XPT_BERT_INVERT_DATA1 XPT_BERT_INVERT_BASEADDR,1,1
#define XPT_BERT_INVERT_DATA2 XPT_BERT_INVERT_BASEADDR,2,1
#define XPT_BERT_INVERT_DATA3 XPT_BERT_INVERT_BASEADDR,3,1
#define XPT_BERT_INVERT_DATA4 XPT_BERT_INVERT_BASEADDR,4,1
#define XPT_BERT_INVERT_DATA5 XPT_BERT_INVERT_BASEADDR,5,1
#define XPT_BERT_INVERT_DATA6 XPT_BERT_INVERT_BASEADDR,6,1
#define XPT_BERT_INVERT_DATA7 XPT_BERT_INVERT_BASEADDR,7,1
#define XPT_BERT_INVERT_SEQUENCE0 XPT_BERT_INVERT_BASEADDR,8,1
#define XPT_BERT_INVERT_SEQUENCE1 XPT_BERT_INVERT_BASEADDR,9,1
#define XPT_BERT_INVERT_SEQUENCE2 XPT_BERT_INVERT_BASEADDR,10,1
#define XPT_BERT_INVERT_SEQUENCE3 XPT_BERT_INVERT_BASEADDR,11,1
#define XPT_BERT_INVERT_SEQUENCE4 XPT_BERT_INVERT_BASEADDR,12,1
#define XPT_BERT_INVERT_SEQUENCE5 XPT_BERT_INVERT_BASEADDR,13,1
#define XPT_BERT_INVERT_SEQUENCE6 XPT_BERT_INVERT_BASEADDR,14,1
#define XPT_BERT_INVERT_SEQUENCE7 XPT_BERT_INVERT_BASEADDR,15,1
#define XPT_BERT_OUTPUT_POLARITY0 XPT_BERT_INVERT_BASEADDR,16,1
#define XPT_BERT_OUTPUT_POLARITY1 XPT_BERT_INVERT_BASEADDR,17,1
#define XPT_BERT_OUTPUT_POLARITY2 XPT_BERT_INVERT_BASEADDR,18,1
#define XPT_BERT_OUTPUT_POLARITY3 XPT_BERT_INVERT_BASEADDR,19,1
#define XPT_BERT_OUTPUT_POLARITY4 XPT_BERT_INVERT_BASEADDR,20,1
#define XPT_BERT_OUTPUT_POLARITY5 XPT_BERT_INVERT_BASEADDR,21,1
#define XPT_BERT_OUTPUT_POLARITY6 XPT_BERT_INVERT_BASEADDR,22,1
#define XPT_BERT_OUTPUT_POLARITY7 XPT_BERT_INVERT_BASEADDR,23,1
#define XPT_BERT_HEADER_BASEADDR 0x907000C4
#define XPT_BERT_HEADER_MODE0 XPT_BERT_HEADER_BASEADDR,0,2
#define XPT_BERT_HEADER_MODE1 XPT_BERT_HEADER_BASEADDR,2,2
#define XPT_BERT_HEADER_MODE2 XPT_BERT_HEADER_BASEADDR,4,2
#define XPT_BERT_HEADER_MODE3 XPT_BERT_HEADER_BASEADDR,6,2
#define XPT_BERT_HEADER_MODE4 XPT_BERT_HEADER_BASEADDR,8,2
#define XPT_BERT_HEADER_MODE5 XPT_BERT_HEADER_BASEADDR,10,2
#define XPT_BERT_HEADER_MODE6 XPT_BERT_HEADER_BASEADDR,12,2
#define XPT_BERT_HEADER_MODE7 XPT_BERT_HEADER_BASEADDR,14,2
#define XPT_BERT_BASEADDR1 0x907000C8
#define XPT_BERT_LOCKED0 XPT_BERT_BASEADDR1,0,1
#define XPT_BERT_LOCKED1 XPT_BERT_BASEADDR1,1,1
#define XPT_BERT_LOCKED2 XPT_BERT_BASEADDR1,2,1
#define XPT_BERT_LOCKED3 XPT_BERT_BASEADDR1,3,1
#define XPT_BERT_LOCKED4 XPT_BERT_BASEADDR1,4,1
#define XPT_BERT_LOCKED5 XPT_BERT_BASEADDR1,5,1
#define XPT_BERT_LOCKED6 XPT_BERT_BASEADDR1,6,1
#define XPT_BERT_LOCKED7 XPT_BERT_BASEADDR1,7,1
#define XPT_BERT_BIT_COUNT_SAT0 XPT_BERT_BASEADDR1,8,1
#define XPT_BERT_BIT_COUNT_SAT1 XPT_BERT_BASEADDR1,9,1
#define XPT_BERT_BIT_COUNT_SAT2 XPT_BERT_BASEADDR1,10,1
#define XPT_BERT_BIT_COUNT_SAT3 XPT_BERT_BASEADDR1,11,1
#define XPT_BERT_BIT_COUNT_SAT4 XPT_BERT_BASEADDR1,12,1
#define XPT_BERT_BIT_COUNT_SAT5 XPT_BERT_BASEADDR1,13,1
#define XPT_BERT_BIT_COUNT_SAT6 XPT_BERT_BASEADDR1,14,1
#define XPT_BERT_BIT_COUNT_SAT7 XPT_BERT_BASEADDR1,15,1
#define XPT_BERT_BIT_COUNT0_BASEADDR 0x907000CC
#define XPT_BERT_BIT_COUNT0_LO XPT_BERT_BIT_COUNT0_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT0_BASEADDR1 0x907000D0
#define XPT_BERT_BIT_COUNT0_HI XPT_BERT_BIT_COUNT0_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT1_BASEADDR 0x907000D4
#define XPT_BERT_BIT_COUNT1_LO XPT_BERT_BIT_COUNT1_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT1_BASEADDR1 0x907000D8
#define XPT_BERT_BIT_COUNT1_HI XPT_BERT_BIT_COUNT1_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT2_BASEADDR 0x907000DC
#define XPT_BERT_BIT_COUNT2_LO XPT_BERT_BIT_COUNT2_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT2_BASEADDR1 0x907000E0
#define XPT_BERT_BIT_COUNT2_HI XPT_BERT_BIT_COUNT2_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT3_BASEADDR 0x907000E4
#define XPT_BERT_BIT_COUNT3_LO XPT_BERT_BIT_COUNT3_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT3_BASEADDR1 0x907000E8
#define XPT_BERT_BIT_COUNT3_HI XPT_BERT_BIT_COUNT3_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT4_BASEADDR 0x907000EC
#define XPT_BERT_BIT_COUNT4_LO XPT_BERT_BIT_COUNT4_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT4_BASEADDR1 0x907000F0
#define XPT_BERT_BIT_COUNT4_HI XPT_BERT_BIT_COUNT4_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT5_BASEADDR 0x907000F4
#define XPT_BERT_BIT_COUNT5_LO XPT_BERT_BIT_COUNT5_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT5_BASEADDR1 0x907000F8
#define XPT_BERT_BIT_COUNT5_HI XPT_BERT_BIT_COUNT5_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT6_BASEADDR 0x907000FC
#define XPT_BERT_BIT_COUNT6_LO XPT_BERT_BIT_COUNT6_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT6_BASEADDR1 0x90700100
#define XPT_BERT_BIT_COUNT6_HI XPT_BERT_BIT_COUNT6_BASEADDR1,0,18
#define XPT_BERT_BIT_COUNT7_BASEADDR 0x90700104
#define XPT_BERT_BIT_COUNT7_LO XPT_BERT_BIT_COUNT7_BASEADDR,0,32
#define XPT_BERT_BIT_COUNT7_BASEADDR1 0x90700108
#define XPT_BERT_BIT_COUNT7_HI XPT_BERT_BIT_COUNT7_BASEADDR1,0,18
#define XPT_BERT_ERR_COUNT0_BASEADDR 0x9070010C
#define XPT_BERT_ERR_COUNT0_LO XPT_BERT_ERR_COUNT0_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT0_BASEADDR1 0x90700110
#define XPT_BERT_ERR_COUNT0_HI XPT_BERT_ERR_COUNT0_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT1_BASEADDR 0x90700114
#define XPT_BERT_ERR_COUNT1_LO XPT_BERT_ERR_COUNT1_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT1_BASEADDR1 0x90700118
#define XPT_BERT_ERR_COUNT1_HI XPT_BERT_ERR_COUNT1_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT2_BASEADDR 0x9070011C
#define XPT_BERT_ERR_COUNT2_LO XPT_BERT_ERR_COUNT2_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT2_BASEADDR1 0x90700120
#define XPT_BERT_ERR_COUNT2_HI XPT_BERT_ERR_COUNT2_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT3_BASEADDR 0x90700124
#define XPT_BERT_ERR_COUNT3_LO XPT_BERT_ERR_COUNT3_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT3_BASEADDR1 0x90700128
#define XPT_BERT_ERR_COUNT3_HI XPT_BERT_ERR_COUNT3_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT4_BASEADDR 0x9070012C
#define XPT_BERT_ERR_COUNT4_LO XPT_BERT_ERR_COUNT4_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT4_BASEADDR1 0x90700130
#define XPT_BERT_ERR_COUNT4_HI XPT_BERT_ERR_COUNT4_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT5_BASEADDR 0x90700134
#define XPT_BERT_ERR_COUNT5_LO XPT_BERT_ERR_COUNT5_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT5_BASEADDR1 0x90700138
#define XPT_BERT_ERR_COUNT5_HI XPT_BERT_ERR_COUNT5_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT6_BASEADDR 0x9070013C
#define XPT_BERT_ERR_COUNT6_LO XPT_BERT_ERR_COUNT6_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT6_BASEADDR1 0x90700140
#define XPT_BERT_ERR_COUNT6_HI XPT_BERT_ERR_COUNT6_BASEADDR1,0,8
#define XPT_BERT_ERR_COUNT7_BASEADDR 0x90700144
#define XPT_BERT_ERR_COUNT7_LO XPT_BERT_ERR_COUNT7_BASEADDR,0,32
#define XPT_BERT_ERR_COUNT7_BASEADDR1 0x90700148
#define XPT_BERT_ERR_COUNT7_HI XPT_BERT_ERR_COUNT7_BASEADDR1,0,8
#define XPT_BERT_ERROR_BASEADDR 0x9070014C
#define XPT_BERT_ERROR_INSERT XPT_BERT_ERROR_BASEADDR,0,24
#define XPT_BERT_ANALYZER_BASEADDR 0x90700150
#define XPT_BERT_ANALYZER_ENABLE XPT_BERT_ANALYZER_BASEADDR,0,1
#define XPT_BERT_ANALYZER_PORT XPT_BERT_ANALYZER_BASEADDR,4,3
#define XPT_BERT_ANALYZER_ERR_THRES XPT_BERT_ANALYZER_BASEADDR,15,17
#define XPT_BERT_ANALYZER_BASEADDR1 0x90700154
#define XPT_BERT_ANALYZER_START XPT_BERT_ANALYZER_BASEADDR1,0,32
#define XPT_BERT_ANALYZER_BASEADDR2 0x90700158
#define XPT_BERT_ANALYZER_TSTAMP0 XPT_BERT_ANALYZER_BASEADDR2,0,32
#define XPT_BERT_ANALYZER_BASEADDR3 0x9070015C
#define XPT_BERT_ANALYZER_TSTAMP1 XPT_BERT_ANALYZER_BASEADDR3,0,32
#define XPT_BERT_ANALYZER_BASEADDR4 0x90700160
#define XPT_BERT_ANALYZER_TSTAMP2 XPT_BERT_ANALYZER_BASEADDR4,0,32
#define XPT_BERT_ANALYZER_BASEADDR5 0x90700164
#define XPT_BERT_ANALYZER_TSTAMP3 XPT_BERT_ANALYZER_BASEADDR5,0,32
#define XPT_BERT_ANALYZER_BASEADDR6 0x90700168
#define XPT_BERT_ANALYZER_TSTAMP4 XPT_BERT_ANALYZER_BASEADDR6,0,32
#define XPT_BERT_ANALYZER_BASEADDR7 0x9070016C
#define XPT_BERT_ANALYZER_TSTAMP5 XPT_BERT_ANALYZER_BASEADDR7,0,32
#define XPT_BERT_ANALYZER_BASEADDR8 0x90700170
#define XPT_BERT_ANALYZER_TSTAMP6 XPT_BERT_ANALYZER_BASEADDR8,0,32
#define XPT_BERT_ANALYZER_BASEADDR9 0x90700174
#define XPT_BERT_ANALYZER_TSTAMP7 XPT_BERT_ANALYZER_BASEADDR9,0,32
#define XPT_DMD0_BASEADDR 0x9070024C
#define XPT_DMD0_SEL XPT_DMD0_BASEADDR,0,3
#define XPT_DMD1_SEL XPT_DMD0_BASEADDR,4,3
#define XPT_DMD2_SEL XPT_DMD0_BASEADDR,8,3
#define XPT_DMD3_SEL XPT_DMD0_BASEADDR,12,3
#define XPT_DMD4_SEL XPT_DMD0_BASEADDR,16,3
#define XPT_DMD5_SEL XPT_DMD0_BASEADDR,20,3
#define XPT_DMD6_SEL XPT_DMD0_BASEADDR,24,3
#define XPT_DMD7_SEL XPT_DMD0_BASEADDR,28,3
// V2 AGC Gain Freeze & step
#define DBG_ENABLE_DISABLE_AGC (0x3FFFCF60) // 1: DISABLE, 0:ENABLE
#define WB_DFE0_DFE_FB_RF1_BASEADDR 0x903004A4
#define WB_DFE0_DFE_FB_RF1_BO WB_DFE0_DFE_FB_RF1_BASEADDR,0,3
#define WB_DFE0_DFE_FB_RF2_BO WB_DFE0_DFE_FB_RF1_BASEADDR,4,4
#define WB_DFE0_DFE_FB_LNA_BO WB_DFE0_DFE_FB_RF1_BASEADDR,8,2
#define WB_DFE1_DFE_FB_RF1_BASEADDR 0x904004A4
#define WB_DFE1_DFE_FB_RF1_BO WB_DFE1_DFE_FB_RF1_BASEADDR,0,3
#define WB_DFE1_DFE_FB_RF2_BO WB_DFE1_DFE_FB_RF1_BASEADDR,4,4
#define WB_DFE1_DFE_FB_LNA_BO WB_DFE1_DFE_FB_RF1_BASEADDR,8,2
#define WB_DFE2_DFE_FB_RF1_BASEADDR 0x905004A4
#define WB_DFE2_DFE_FB_RF1_BO WB_DFE2_DFE_FB_RF1_BASEADDR,0,3
#define WB_DFE2_DFE_FB_RF2_BO WB_DFE2_DFE_FB_RF1_BASEADDR,4,4
#define WB_DFE2_DFE_FB_LNA_BO WB_DFE2_DFE_FB_RF1_BASEADDR,8,2
#define WB_DFE3_DFE_FB_RF1_BASEADDR 0x906004A4
#define WB_DFE3_DFE_FB_RF1_BO WB_DFE3_DFE_FB_RF1_BASEADDR,0,3
#define WB_DFE3_DFE_FB_RF2_BO WB_DFE3_DFE_FB_RF1_BASEADDR,4,4
#define WB_DFE3_DFE_FB_LNA_BO WB_DFE3_DFE_FB_RF1_BASEADDR,8,2
#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR 0x90200104
#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,0,1
#define AFE_REG_D2A_TA_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,1,1
#define AFE_REG_D2A_TB_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,2,1
#define AFE_REG_D2A_TB_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,3,1
#define AFE_REG_D2A_TC_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,4,1
#define AFE_REG_D2A_TC_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,5,1
#define AFE_REG_D2A_TD_RFFE_LNA_BO_1P8_2 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,6,1
#define AFE_REG_D2A_TD_RFFE_RF1_BO_1P8_3 AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR,7,1
#define AFE_REG_AFE_REG_SPARE_BASEADDR 0x902000A0
#define AFE_REG_D2A_TA_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR,13,5
#define AFE_REG_AFE_REG_SPARE_BASEADDR1 0x902000B4
#define AFE_REG_D2A_TB_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR1,13,5
#define AFE_REG_AFE_REG_SPARE_BASEADDR2 0x902000C4
#define AFE_REG_D2A_TC_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR2,13,5
#define AFE_REG_AFE_REG_SPARE_BASEADDR3 0x902000D4
#define AFE_REG_D2A_TD_RFFE_RF1_CAP_1P8 AFE_REG_AFE_REG_SPARE_BASEADDR3,13,5
#define WB_DFE0_DFE_FB_AGC_BASEADDR 0x90300498
#define WB_DFE0_DFE_FB_AGC_APPLY WB_DFE0_DFE_FB_AGC_BASEADDR,0,1
#define WB_DFE1_DFE_FB_AGC_BASEADDR 0x90400498
#define WB_DFE1_DFE_FB_AGC_APPLY WB_DFE1_DFE_FB_AGC_BASEADDR,0,1
#define WB_DFE2_DFE_FB_AGC_BASEADDR 0x90500498
#define WB_DFE2_DFE_FB_AGC_APPLY WB_DFE2_DFE_FB_AGC_BASEADDR,0,1
#define WB_DFE3_DFE_FB_AGC_BASEADDR 0x90600498
#define WB_DFE3_DFE_FB_AGC_APPLY WB_DFE3_DFE_FB_AGC_BASEADDR,0,1
#define WDT_WD_INT_BASEADDR 0x8002000C
#define WDT_WD_INT_STATUS WDT_WD_INT_BASEADDR,0,1
#define FSK_TX_FTM_BASEADDR 0x80090000
#define FSK_TX_FTM_OE FSK_TX_FTM_BASEADDR,12,1
#define FSK_TX_FTM_TX_EN FSK_TX_FTM_BASEADDR,10,1
#define FSK_TX_FTM_FORCE_CARRIER_ON FSK_TX_FTM_BASEADDR,1,1
#define FSK_TX_FTM_FORCE_MARK_SPACE FSK_TX_FTM_BASEADDR,0,1
#define FSK_TX_FTM_TX_CNT_BASEADDR 0x80090018
#define FSK_TX_FTM_TX_CNT_INT FSK_TX_FTM_TX_CNT_BASEADDR,8,4
#define FSK_TX_FTM_TX_INT_EN FSK_TX_FTM_TX_CNT_BASEADDR,4,1
#define FSK_TX_FTM_TX_INT_SRC_SEL FSK_TX_FTM_TX_CNT_BASEADDR,0,2
#define AFE_REG_D2A_FSK_BIAS_BASEADDR 0x90200040
#define AFE_REG_D2A_FSK_BIAS_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,0,1
#define AFE_REG_D2A_FSK_TEST_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,10,1
#define AFE_REG_D2A_FSK_TEST_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,11,4
#define AFE_REG_D2A_FSK_TERM_INT_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,15,1
#define AFE_REG_D2A_FSK_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,16,1
#define AFE_REG_D2A_FSK_REG_EN_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,17,1
#define AFE_REG_D2A_FSK_REG_EN_LKG_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,18,1
#define AFE_REG_D2A_FSK_REG_AMP_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,19,3
#define AFE_REG_D2A_FSK_REG_TEST_CTRL_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,22,2
#define AFE_REG_D2A_DSQ_RX_MODE AFE_REG_D2A_FSK_BIAS_BASEADDR,24,1
#define AFE_REG_D2A_DSQ_RX_EN AFE_REG_D2A_FSK_BIAS_BASEADDR,25,1
#define AFE_REG_D2A_DSQ_HYST AFE_REG_D2A_FSK_BIAS_BASEADDR,26,2
#define AFE_REG_D2A_DSQ_RESETB_1P8 AFE_REG_D2A_FSK_BIAS_BASEADDR,28,1
#define AFE_REG_D2A_FSK_CLKRX_ENA AFE_REG_D2A_FSK_BIAS_BASEADDR,29,1
#define DMD_TEI_BASEADDR 0x3FFFEBE0
#define DMD_TEI_ENA DMD_TEI_BASEADDR,0,1
#define xpt_shm_input_control0 0x90700270,0,8
#define xpt_shm_input_control1 0x90700270,8,8
#define xpt_shm_input_control2 0x90700270,16,8
#define xpt_shm_input_control3 0x90700270,24,8
#define xpt_shm_input_control4 0x90700274,0,8
#define xpt_shm_input_control5 0x90700274,8,8
#define xpt_shm_input_control6 0x90700274,16,8
#define xpt_shm_input_control7 0x90700274,24,8
#define xpt_shm_output_control0 0x90700278,0,8
#define xpt_shm_output_control1 0x90700278,8,8
#define xpt_shm_output_control2 0x90700278,16,8
#define xpt_shm_output_control3 0x90700278,24,8
#define xpt_shm_output_control4 0x9070027C,0,8
#define xpt_shm_output_control5 0x9070027C,8,8
#define xpt_shm_output_control6 0x9070027C,16,8
#define xpt_shm_output_control7 0x9070027C,24,8
#define xpt_mode_27mhz 0x90700184,0,1
#define xpt_enable_pcr_count 0x90700184,1,1
#define xcpu_ctrl_003c_reg 0x9072003C,0,4
#ifdef __cplusplus
}
#endif
#endif //__MXL58X_REGISTERS_H__

3472
frontends/stv0367.c Normal file

File diff suppressed because it is too large Load Diff

89
frontends/stv0367.h Normal file
View File

@ -0,0 +1,89 @@
/*
* stv0367.h
*
* Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
*
* Copyright (C) ST Microelectronics.
* Copyright (C) 2010,2011 NetUP Inc.
* Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef STV0367_H
#define STV0367_H
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
enum stv0367_ts_mode {
STV0367_OUTPUTMODE_DEFAULT,
STV0367_SERIAL_PUNCT_CLOCK,
STV0367_SERIAL_CONT_CLOCK,
STV0367_PARALLEL_PUNCT_CLOCK,
STV0367_DVBCI_CLOCK
};
enum stv0367_clk_pol {
STV0367_CLOCKPOLARITY_DEFAULT,
STV0367_RISINGEDGE_CLOCK,
STV0367_FALLINGEDGE_CLOCK
};
struct stv0367_config {
u8 demod_address;
u32 xtal;
u32 if_khz;/*4500*/
int if_iq_mode;
int ts_mode;
int clk_pol;
};
enum stv0367_ter_if_iq_mode {
FE_TER_NORMAL_IF_TUNER = 0,
FE_TER_LONGPATH_IF_TUNER = 1,
FE_TER_IQ_TUNER = 2
};
#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
&& defined(MODULE))
extern struct
dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
struct i2c_adapter *i2c);
extern struct
dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
struct i2c_adapter *i2c);
#else
static inline struct
dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct
dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

191
frontends/stv0367_priv.h Normal file
View File

@ -0,0 +1,191 @@
/*
* stv0367_priv.h
*
* Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
*
* Copyright (C) ST Microelectronics.
* Copyright (C) 2010,2011 NetUP Inc.
* Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Common driver error constants */
#ifndef STV0367_PRIV_H
#define STV0367_PRIV_H
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif
#ifndef NULL
#define NULL 0
#endif
/* MACRO definitions */
#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
#define INRANGE(X, Y, Z) \
((((X) <= (Y)) && ((Y) <= (Z))) || \
(((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0)
#ifndef MAKEWORD
#define MAKEWORD(X, Y) (((X) << 8) + (Y))
#endif
#define LSB(X) (((X) & 0xff))
#define MSB(Y) (((Y) >> 8) & 0xff)
#define MMSB(Y)(((Y) >> 16) & 0xff)
enum stv0367_ter_signal_type {
FE_TER_NOAGC = 0,
FE_TER_AGCOK = 5,
FE_TER_NOTPS = 6,
FE_TER_TPSOK = 7,
FE_TER_NOSYMBOL = 8,
FE_TER_BAD_CPQ = 9,
FE_TER_PRFOUNDOK = 10,
FE_TER_NOPRFOUND = 11,
FE_TER_LOCKOK = 12,
FE_TER_NOLOCK = 13,
FE_TER_SYMBOLOK = 15,
FE_TER_CPAMPOK = 16,
FE_TER_NOCPAMP = 17,
FE_TER_SWNOK = 18
};
enum stv0367_ter_bw {
FE_TER_CHAN_BW_6M = 6,
FE_TER_CHAN_BW_7M = 7,
FE_TER_CHAN_BW_8M = 8
};
#if 0
enum FE_TER_Rate_TPS {
FE_TER_TPS_1_2 = 0,
FE_TER_TPS_2_3 = 1,
FE_TER_TPS_3_4 = 2,
FE_TER_TPS_5_6 = 3,
FE_TER_TPS_7_8 = 4
};
#endif
enum stv0367_ter_mode {
FE_TER_MODE_2K,
FE_TER_MODE_8K,
FE_TER_MODE_4K
};
#if 0
enum FE_TER_Hierarchy_Alpha {
FE_TER_HIER_ALPHA_NONE, /* Regular modulation */
FE_TER_HIER_ALPHA_1, /* Hierarchical modulation a = 1*/
FE_TER_HIER_ALPHA_2, /* Hierarchical modulation a = 2*/
FE_TER_HIER_ALPHA_4 /* Hierarchical modulation a = 4*/
};
#endif
enum stv0367_ter_hierarchy {
FE_TER_HIER_NONE, /*Hierarchy None*/
FE_TER_HIER_LOW_PRIO, /*Hierarchy : Low Priority*/
FE_TER_HIER_HIGH_PRIO, /*Hierarchy : High Priority*/
FE_TER_HIER_PRIO_ANY /*Hierarchy :Any*/
};
#if 0
enum fe_stv0367_ter_spec {
FE_TER_INVERSION_NONE = 0,
FE_TER_INVERSION = 1,
FE_TER_INVERSION_AUTO = 2,
FE_TER_INVERSION_UNK = 4
};
#endif
#if 0
enum FE_TER_FECRate {
FE_TER_FEC_NONE = 0x00, /* no FEC rate specified */
FE_TER_FEC_ALL = 0xFF, /* Logical OR of all FECs */
FE_TER_FEC_1_2 = 1,
FE_TER_FEC_2_3 = (1 << 1),
FE_TER_FEC_3_4 = (1 << 2),
FE_TER_FEC_4_5 = (1 << 3),
FE_TER_FEC_5_6 = (1 << 4),
FE_TER_FEC_6_7 = (1 << 5),
FE_TER_FEC_7_8 = (1 << 6),
FE_TER_FEC_8_9 = (1 << 7)
};
enum FE_TER_Rate {
FE_TER_FE_1_2 = 0,
FE_TER_FE_2_3 = 1,
FE_TER_FE_3_4 = 2,
FE_TER_FE_5_6 = 3,
FE_TER_FE_6_7 = 4,
FE_TER_FE_7_8 = 5
};
#endif
enum stv0367_ter_force {
FE_TER_FORCENONE = 0,
FE_TER_FORCE_M_G = 1
};
enum stv0367cab_mod {
FE_CAB_MOD_QAM4,
FE_CAB_MOD_QAM16,
FE_CAB_MOD_QAM32,
FE_CAB_MOD_QAM64,
FE_CAB_MOD_QAM128,
FE_CAB_MOD_QAM256,
FE_CAB_MOD_QAM512,
FE_CAB_MOD_QAM1024
};
#if 0
enum {
FE_CAB_FEC_A = 1, /* J83 Annex A */
FE_CAB_FEC_B = (1 << 1),/* J83 Annex B */
FE_CAB_FEC_C = (1 << 2) /* J83 Annex C */
} FE_CAB_FECType_t;
#endif
struct stv0367_cab_signal_info {
int locked;
u32 frequency; /* kHz */
u32 symbol_rate; /* Mbds */
enum stv0367cab_mod modulation;
fe_spectral_inversion_t spect_inv;
s32 Power_dBmx10; /* Power of the RF signal (dBm x 10) */
u32 CN_dBx10; /* Carrier to noise ratio (dB x 10) */
u32 BER; /* Bit error rate (x 10000000) */
};
enum stv0367_cab_signal_type {
FE_CAB_NOTUNER,
FE_CAB_NOAGC,
FE_CAB_NOSIGNAL,
FE_CAB_NOTIMING,
FE_CAB_TIMINGOK,
FE_CAB_NOCARRIER,
FE_CAB_CARRIEROK,
FE_CAB_NOBLIND,
FE_CAB_BLINDOK,
FE_CAB_NODEMOD,
FE_CAB_DEMODOK,
FE_CAB_DATAOK
};
#endif

3614
frontends/stv0367_regs.h Normal file

File diff suppressed because it is too large Load Diff

2161
frontends/stv0367dd.c Normal file

File diff suppressed because it is too large Load Diff

18
frontends/stv0367dd.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _STV0367DD_H_
#define _STV0367DD_H_
#include <linux/types.h>
#include <linux/i2c.h>
struct stv0367_cfg {
u8 adr;
u32 xtal;
u8 parallel;
u8 cont_clock;
};
extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
struct stv0367_cfg *cfg,
struct dvb_frontend **fe_t);
#endif

3431
frontends/stv0367dd_regs.h Normal file

File diff suppressed because it is too large Load Diff

4936
frontends/stv090x.c Normal file

File diff suppressed because it is too large Load Diff

134
frontends/stv090x.h Normal file
View File

@ -0,0 +1,134 @@
/*
STV0900/0903 Multistandard Broadcast Frontend driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __STV090x_H
#define __STV090x_H
enum stv090x_demodulator {
STV090x_DEMODULATOR_0 = 1,
STV090x_DEMODULATOR_1
};
enum stv090x_device {
STV0903 = 0,
STV0900,
};
enum stv090x_mode {
STV090x_DUAL = 0,
STV090x_SINGLE
};
enum stv090x_tsmode {
STV090x_TSMODE_SERIAL_PUNCTURED = 1,
STV090x_TSMODE_SERIAL_CONTINUOUS,
STV090x_TSMODE_PARALLEL_PUNCTURED,
STV090x_TSMODE_DVBCI
};
enum stv090x_clkmode {
STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
};
enum stv090x_i2crpt {
STV090x_RPTLEVEL_256 = 0,
STV090x_RPTLEVEL_128 = 1,
STV090x_RPTLEVEL_64 = 2,
STV090x_RPTLEVEL_32 = 3,
STV090x_RPTLEVEL_16 = 4,
STV090x_RPTLEVEL_8 = 5,
STV090x_RPTLEVEL_4 = 6,
STV090x_RPTLEVEL_2 = 7,
};
enum stv090x_adc_range {
STV090x_ADC_2Vpp = 0,
STV090x_ADC_1Vpp = 1
};
struct stv090x_config {
enum stv090x_device device;
enum stv090x_mode demod_mode;
enum stv090x_clkmode clk_mode;
u32 xtal; /* default: 8000000 */
u8 address; /* default: 0x68 */
u8 ts1_mode;
u8 ts2_mode;
u32 ts1_clk;
u32 ts2_clk;
u8 ts1_tei : 1;
u8 ts2_tei : 1;
enum stv090x_i2crpt repeater_level;
u8 tuner_bbgain; /* default: 10db */
enum stv090x_adc_range adc1_range; /* default: 2Vpp */
enum stv090x_adc_range adc2_range; /* default: 2Vpp */
bool diseqc_envelope_mode;
int (*tuner_init) (struct dvb_frontend *fe);
int (*tuner_sleep) (struct dvb_frontend *fe);
int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
};
#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod);
/* dir = 0 -> output, dir = 1 -> input/open-drain */
extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
u8 dir, u8 value, u8 xor_value);
#else
static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
u8 opd, u8 value, u8 xor_value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
#endif /* CONFIG_DVB_STV090x */
#endif /* __STV090x_H */

279
frontends/stv090x_priv.h Normal file
View File

@ -0,0 +1,279 @@
/*
STV0900/0903 Multistandard Broadcast Frontend driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __STV090x_PRIV_H
#define __STV090x_PRIV_H
#include "dvb_frontend.h"
#define FE_ERROR 0
#define FE_NOTICE 1
#define FE_INFO 2
#define FE_DEBUG 3
#define FE_DEBUGREG 4
#define dprintk(__y, __z, format, arg...) do { \
if (__z) { \
if ((verbose > FE_ERROR) && (verbose > __y)) \
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_NOTICE) && (verbose > __y)) \
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_INFO) && (verbose > __y)) \
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_DEBUG) && (verbose > __y)) \
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (verbose > __y) \
printk(format, ##arg); \
} \
} while (0)
#define STV090x_READ_DEMOD(__state, __reg) (( \
(__state)->demod == STV090x_DEMODULATOR_1) ? \
stv090x_read_reg(__state, STV090x_P2_##__reg) : \
stv090x_read_reg(__state, STV090x_P1_##__reg))
#define STV090x_WRITE_DEMOD(__state, __reg, __data) (( \
(__state)->demod == STV090x_DEMODULATOR_1) ? \
stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
#define STV090x_ADDR_OFFST(__state, __x) (( \
(__state->demod) == STV090x_DEMODULATOR_1) ? \
STV090x_P1_##__x : \
STV090x_P2_##__x)
#define STV090x_SETFIELD(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
STV090x_OFFST_##bitf))) | \
(val << STV090x_OFFST_##bitf))
#define STV090x_GETFIELD(val, bitf) ((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
#define STV090x_SETFIELD_Px(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
STV090x_OFFST_Px_##bitf))) | \
(val << STV090x_OFFST_Px_##bitf))
#define STV090x_GETFIELD_Px(val, bitf) ((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
#define MAKEWORD16(__a, __b) (((__a) << 8) | (__b))
#define MSB(__x) ((__x >> 8) & 0xff)
#define LSB(__x) (__x & 0xff)
#define STV090x_IQPOWER_THRESHOLD 30
#define STV090x_SEARCH_AGC2_TH_CUT20 700
#define STV090x_SEARCH_AGC2_TH_CUT30 1400
#define STV090x_SEARCH_AGC2_TH(__ver) \
((__ver <= 0x20) ? \
STV090x_SEARCH_AGC2_TH_CUT20 : \
STV090x_SEARCH_AGC2_TH_CUT30)
enum stv090x_signal_state {
STV090x_NOAGC1,
STV090x_NOCARRIER,
STV090x_NODATA,
STV090x_DATAOK,
STV090x_RANGEOK,
STV090x_OUTOFRANGE
};
enum stv090x_fec {
STV090x_PR12 = 0,
STV090x_PR23,
STV090x_PR34,
STV090x_PR45,
STV090x_PR56,
STV090x_PR67,
STV090x_PR78,
STV090x_PR89,
STV090x_PR910,
STV090x_PRERR
};
enum stv090x_modulation {
STV090x_QPSK,
STV090x_8PSK,
STV090x_16APSK,
STV090x_32APSK,
STV090x_UNKNOWN
};
enum stv090x_frame {
STV090x_LONG_FRAME,
STV090x_SHORT_FRAME
};
enum stv090x_pilot {
STV090x_PILOTS_OFF,
STV090x_PILOTS_ON
};
enum stv090x_rolloff {
STV090x_RO_35,
STV090x_RO_25,
STV090x_RO_20
};
enum stv090x_inversion {
STV090x_IQ_AUTO,
STV090x_IQ_NORMAL,
STV090x_IQ_SWAP
};
enum stv090x_modcod {
STV090x_DUMMY_PLF = 0,
STV090x_QPSK_14,
STV090x_QPSK_13,
STV090x_QPSK_25,
STV090x_QPSK_12,
STV090x_QPSK_35,
STV090x_QPSK_23,
STV090x_QPSK_34,
STV090x_QPSK_45,
STV090x_QPSK_56,
STV090x_QPSK_89,
STV090x_QPSK_910,
STV090x_8PSK_35,
STV090x_8PSK_23,
STV090x_8PSK_34,
STV090x_8PSK_56,
STV090x_8PSK_89,
STV090x_8PSK_910,
STV090x_16APSK_23,
STV090x_16APSK_34,
STV090x_16APSK_45,
STV090x_16APSK_56,
STV090x_16APSK_89,
STV090x_16APSK_910,
STV090x_32APSK_34,
STV090x_32APSK_45,
STV090x_32APSK_56,
STV090x_32APSK_89,
STV090x_32APSK_910,
STV090x_MODCODE_UNKNOWN
};
enum stv090x_search {
STV090x_SEARCH_DSS = 0,
STV090x_SEARCH_DVBS1,
STV090x_SEARCH_DVBS2,
STV090x_SEARCH_AUTO
};
enum stv090x_algo {
STV090x_BLIND_SEARCH,
STV090x_COLD_SEARCH,
STV090x_WARM_SEARCH
};
enum stv090x_delsys {
STV090x_ERROR = 0,
STV090x_DVBS1 = 1,
STV090x_DVBS2,
STV090x_DSS
};
struct stv090x_long_frame_crloop {
enum stv090x_modcod modcod;
u8 crl_pilots_on_2;
u8 crl_pilots_off_2;
u8 crl_pilots_on_5;
u8 crl_pilots_off_5;
u8 crl_pilots_on_10;
u8 crl_pilots_off_10;
u8 crl_pilots_on_20;
u8 crl_pilots_off_20;
u8 crl_pilots_on_30;
u8 crl_pilots_off_30;
};
struct stv090x_short_frame_crloop {
enum stv090x_modulation modulation;
u8 crl_2; /* SR < 3M */
u8 crl_5; /* 3 < SR <= 7M */
u8 crl_10; /* 7 < SR <= 15M */
u8 crl_20; /* 10 < SR <= 25M */
u8 crl_30; /* 10 < SR <= 45M */
};
struct stv090x_reg {
u16 addr;
u8 data;
};
struct stv090x_tab {
s32 real;
s32 read;
};
struct stv090x_internal {
struct i2c_adapter *i2c_adap;
u8 i2c_addr;
struct mutex demod_lock; /* Lock access to shared register */
struct mutex tuner_lock; /* Lock access to tuners */
s32 mclk; /* Masterclock Divider factor */
u32 dev_ver;
int num_used;
};
struct stv090x_state {
enum stv090x_device device;
enum stv090x_demodulator demod;
enum stv090x_mode demod_mode;
struct stv090x_internal *internal;
struct i2c_adapter *i2c;
const struct stv090x_config *config;
struct dvb_frontend frontend;
u32 *verbose; /* Cached module verbosity */
enum stv090x_delsys delsys;
enum stv090x_fec fec;
enum stv090x_modulation modulation;
enum stv090x_modcod modcod;
enum stv090x_search search_mode;
enum stv090x_frame frame_len;
enum stv090x_pilot pilots;
enum stv090x_rolloff rolloff;
enum stv090x_inversion inversion;
enum stv090x_algo algo;
u32 frequency;
u32 srate;
s32 tuner_bw;
s32 search_range;
s32 DemodTimeout;
s32 FecTimeout;
};
#endif /* __STV090x_PRIV_H */

2371
frontends/stv090x_reg.h Normal file

File diff suppressed because it is too large Load Diff

1406
frontends/stv0910.c Normal file

File diff suppressed because it is too large Load Diff

31
frontends/stv0910.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _STV0910_H_
#define _STV0910_H_
#include <linux/types.h>
#include <linux/i2c.h>
struct stv0910_cfg {
u32 clk;
u8 adr;
u8 parallel;
u8 rptlvl;
};
#if defined(CONFIG_DVB_STV0910) || \
(defined(CONFIG_DVB_STV0910_MODULE) && defined(MODULE))
extern struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
struct stv0910_cfg *cfg, int nr);
#else
static inline struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
struct stv0910_cfg *cfg,
int nr)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

3998
frontends/stv0910_regs.h Normal file

File diff suppressed because it is too large Load Diff

405
frontends/stv6110x.c Normal file
View File

@ -0,0 +1,405 @@
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "dvb_frontend.h"
#include "stv6110x_reg.h"
#include "stv6110x.h"
#include "stv6110x_priv.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Set Verbosity level");
static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
{
int ret;
const struct stv6110x_config *config = stv6110x->config;
u8 b0[] = { reg };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
{ .addr = config->addr, .flags = 0, .buf = b0, .len = 1 },
{ .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
};
ret = i2c_transfer(stv6110x->i2c, msg, 2);
if (ret != 2) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EREMOTEIO;
}
*data = b1[0];
return 0;
}
static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
{
int ret;
const struct stv6110x_config *config = stv6110x->config;
u8 buf[len + 1];
struct i2c_msg msg = {
.addr = config->addr,
.flags = 0,
.buf = buf,
.len = len + 1
};
if (start + len > 8)
return -EINVAL;
buf[0] = start;
memcpy(&buf[1], data, len);
ret = i2c_transfer(stv6110x->i2c, &msg, 1);
if (ret != 1) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EREMOTEIO;
}
return 0;
}
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
{
return stv6110x_write_regs(stv6110x, reg, &data, 1);
}
static int stv6110x_init(struct dvb_frontend *fe)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
int ret;
ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
ARRAY_SIZE(stv6110x->regs));
if (ret < 0) {
dprintk(FE_ERROR, 1, "Initialization failed");
return -1;
}
return 0;
}
static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
u32 rDiv, divider;
s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
u8 i;
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
if (frequency <= 1023000) {
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 40;
} else if (frequency <= 1300000) {
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 40;
} else if (frequency <= 2046000) {
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 20;
} else {
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 20;
}
for (rDiv = 0; rDiv <= 3; rDiv++) {
pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal))))
rDivOpt = rDiv;
pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt);
}
divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
divider = (divider + 5) / 10;
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
/* VCO Auto calibration */
STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
break;
msleep(1);
}
return 0;
}
static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
*frequency >>= 2;
return 0;
}
static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
u32 halfbw;
u8 i;
halfbw = bandwidth >> 1;
if (halfbw > 36000000)
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
else if (halfbw < 5000000)
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
else
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
break;
msleep(1);
}
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
return 0;
}
static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
return 0;
}
static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
/* setup divider */
switch (refclock) {
default:
case 1:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
break;
case 2:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
break;
case 4:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
break;
case 8:
case 0:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
break;
}
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
int ret;
switch (mode) {
case TUNER_SLEEP:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
break;
case TUNER_WAKE:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
break;
}
ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
if (ret < 0) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EIO;
}
return 0;
}
static int stv6110x_sleep(struct dvb_frontend *fe)
{
if (fe->tuner_priv)
return stv6110x_set_mode(fe, TUNER_SLEEP);
return 0;
}
static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
*status = TUNER_PHASELOCKED;
else
*status = 0;
return 0;
}
static int stv6110x_release(struct dvb_frontend *fe)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
fe->tuner_priv = NULL;
kfree(stv6110x);
return 0;
}
static struct dvb_tuner_ops stv6110x_ops = {
.info = {
.name = "STV6110(A) Silicon Tuner",
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_step = 0,
},
.release = stv6110x_release
};
static struct stv6110x_devctl stv6110x_ctl = {
.tuner_init = stv6110x_init,
.tuner_sleep = stv6110x_sleep,
.tuner_set_mode = stv6110x_set_mode,
.tuner_set_frequency = stv6110x_set_frequency,
.tuner_get_frequency = stv6110x_get_frequency,
.tuner_set_bandwidth = stv6110x_set_bandwidth,
.tuner_get_bandwidth = stv6110x_get_bandwidth,
.tuner_set_bbgain = stv6110x_set_bbgain,
.tuner_get_bbgain = stv6110x_get_bbgain,
.tuner_set_refclk = stv6110x_set_refclock,
.tuner_get_status = stv6110x_get_status,
};
struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c)
{
struct stv6110x_state *stv6110x;
u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
if (!stv6110x)
return NULL;
stv6110x->i2c = i2c;
stv6110x->config = config;
stv6110x->devctl = &stv6110x_ctl;
memcpy(stv6110x->regs, default_regs, 8);
/* setup divider */
switch (stv6110x->config->clk_div) {
default:
case 1:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
break;
case 2:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
break;
case 4:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
break;
case 8:
case 0:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
break;
}
fe->tuner_priv = stv6110x;
fe->ops.tuner_ops = stv6110x_ops;
printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
return stv6110x->devctl;
}
EXPORT_SYMBOL(stv6110x_attach);
MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV6110x Silicon tuner");
MODULE_LICENSE("GPL");

73
frontends/stv6110x.h Normal file
View File

@ -0,0 +1,73 @@
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __STV6110x_H
#define __STV6110x_H
struct stv6110x_config {
u8 addr;
u32 refclk;
u8 clk_div; /* divisor value for the output clock */
};
enum tuner_mode {
TUNER_SLEEP = 1,
TUNER_WAKE,
};
enum tuner_status {
TUNER_PHASELOCKED = 1,
};
struct stv6110x_devctl {
int (*tuner_init) (struct dvb_frontend *fe);
int (*tuner_sleep) (struct dvb_frontend *fe);
int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
};
#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c);
#else
static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_STV6110x */
#endif /* __STV6110x_H */

76
frontends/stv6110x_priv.h Normal file
View File

@ -0,0 +1,76 @@
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __STV6110x_PRIV_H
#define __STV6110x_PRIV_H
#define FE_ERROR 0
#define FE_NOTICE 1
#define FE_INFO 2
#define FE_DEBUG 3
#define FE_DEBUGREG 4
#define dprintk(__y, __z, format, arg...) do { \
if (__z) { \
if ((verbose > FE_ERROR) && (verbose > __y)) \
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_NOTICE) && (verbose > __y)) \
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_INFO) && (verbose > __y)) \
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_DEBUG) && (verbose > __y)) \
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (verbose > __y) \
printk(format, ##arg); \
} \
} while (0)
#define STV6110x_SETFIELD(mask, bitf, val) \
(mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) << \
STV6110x_OFFST_##bitf))) | \
(val << STV6110x_OFFST_##bitf))
#define STV6110x_GETFIELD(bitf, val) \
((val >> STV6110x_OFFST_##bitf) & \
((1 << STV6110x_WIDTH_##bitf) - 1))
#define MAKEWORD16(a, b) (((a) << 8) | (b))
#define LSB(x) ((x & 0xff))
#define MSB(y) ((y >> 8) & 0xff)
#define TRIALS 10
#define R_DIV(__div) (1 << (__div + 1))
#define REFCLOCK_kHz (stv6110x->config->refclk / 1000)
#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000)
struct stv6110x_state {
struct i2c_adapter *i2c;
const struct stv6110x_config *config;
u8 regs[8];
struct stv6110x_devctl *devctl;
};
#endif /* __STV6110x_PRIV_H */

Some files were not shown because too many files have changed in this diff Show More