103 Commits

Author SHA1 Message Date
mvoelkel
bb191aa5d7 Merge branch 'internal' 2016-08-04 01:00:35 +02:00
Ralph Metzler
38f0e9611e new release 2016-08-03 13:49:17 +02:00
Ralph Metzler
4ed35e1de5 support temperatures on V2 modulator boards 2016-08-02 21:22:18 +02:00
Ralph Metzler
1567d804b1 set vga according to ouputs 2016-08-02 21:08:40 +02:00
Ralph Metzler
8c82d0166c first support for V2 modulator cards 2016-07-31 21:41:03 +02:00
Ralph Metzler
5c7b55490a remoce debugging message 2016-07-31 21:40:56 +02:00
Ralph Metzler
e2db17b04e always interpret pls code as gold code 2016-07-31 21:40:22 +02:00
Ralph Metzler
a1221c6e4e always interpret pls code as gold code 2016-07-31 21:39:20 +02:00
Ralph Metzler
86d9ce8f11 support new API signal strength and SNR
support get_frontend()
start support for BER
2016-07-07 22:42:12 +02:00
mvoelkel
f2091a50df Revert "adapt to latest windows driver version"
This reverts commit 6b73faeee5.
2016-07-07 17:47:34 +02:00
Ralph Metzler
131aaf361e support new API signal strength and SNR
support get_frontend()
start support for BER
2016-07-04 18:59:33 +02:00
mvoelkel
c929aea04d Signalstrength conversion dBµV to dBm 2016-06-29 17:20:28 +02:00
Ralph Metzler
16c0834b78 support other CI speeds 2016-06-27 23:01:21 +02:00
Ralph Metzler
50fee67d49 cleanup 2016-06-16 18:11:18 +02:00
Ralph Metzler
9d0400d81a - implement fixes from current kernel driver
- add support for pls
2016-06-16 18:10:25 +02:00
Ralph Metzler
6f071763c3 cleanup and set default numerator/denominator 2016-06-16 18:09:40 +02:00
Ralph Metzler
98bdb95193 remove unneeded p 2016-06-16 18:09:16 +02:00
Ralph Metzler
2c8fcc1df5 change physical layer scrambling API to DTV_PLS and support old API
mixed with DTV_STREAM_ID
2016-06-16 15:42:18 +02:00
Ralph Metzler
805a3ffeed add speed calculation (not used yet) 2016-06-16 15:40:24 +02:00
Ralph Metzler
ffdcd91a06 start to add some more information on ci speed settings 2016-06-16 15:39:40 +02:00
Ralph Metzler
b36a6392cc fix get_frontend callbacks 2016-06-16 15:38:58 +02:00
Ralph Metzler
0d27002a17 missing increment of buf for CI device reads 2016-06-10 09:45:21 +02:00
Ralph Metzler
094e1f3e1f add some options for device, adapter and read/write lengths 2016-06-10 09:44:50 +02:00
Ralph Metzler
2d71c946d3 compile fixes 2016-06-10 09:44:04 +02:00
Ralph Metzler
39ce49dbd8 fix pci-compat include for newer kernels 2016-06-10 09:43:04 +02:00
Ralph Metzler
8908df8098 add support for DVB-S2 scrambling code and ISI 2016-06-08 12:13:16 +02:00
Ralph Metzler
421adf6872 cleanup 2016-06-08 12:12:32 +02:00
Ralph Metzler
154794ac51 add support to read unique ids 2016-06-08 12:11:08 +02:00
Ralph Metzler
6b73faeee5 adapt to latest windows driver version 2016-06-01 15:25:16 +02:00
Ralph Metzler
80e0750c71 adapt to latest windows driver version 2016-05-31 17:01:46 +02:00
Ralph Metzler
65f9f56cfe prepare for llowing different buffer number/sizes 2016-05-31 17:01:08 +02:00
Ralph Metzler
53c32d47e0 prepare for new redirect 2016-05-31 16:53:04 +02:00
Ralph Metzler
4db55036f3 add transmission mode 64K 2016-05-31 16:51:52 +02:00
Ralph Metzler
eda007e71a more T2 statistics info 2016-05-31 16:46:02 +02:00
Ralph Metzler
6975dfdd5a cosmetics 2016-05-31 16:45:34 +02:00
Ralph Metzler
0c6336292e new version of stv0910 register defines 2016-05-31 16:45:06 +02:00
Ralph Metzler
a456f8d5d9 add card, link and port number to i2c name 2016-05-10 12:01:14 +02:00
mvoelkel
a8d5d5b50d stv0910 fixed typo in get frequency offset 2016-05-10 11:49:09 +02:00
Ralph Metzler
d988c8562b use link 0 offsets for dma interrupts 2016-05-06 12:32:25 +02:00
Ralph Metzler
aaf5707c45 use regmap offset for input enable 2016-05-06 00:55:41 +02:00
Ralph Metzler
1e9b7dc5cc fix port_num loops for dma on link
remove debugging
2016-05-05 00:15:02 +02:00
Ralph Metzler
40edadad3d octopro testing 2016-05-03 22:05:29 +02:00
Ralph Metzler
535ffa6ca6 show tuning offset 2016-05-03 22:05:18 +02:00
Ralph Metzler
1b0df5fcfa octopro fixes 2016-05-02 16:27:32 +02:00
Ralph Metzler
5633c2f79d increase port and output max 2016-04-24 21:44:01 +02:00
mvoelkel
74f172a4fe Fixed octopro i2c regmap 2016-04-21 21:48:26 +02:00
Ralph Metzler
cc6209af33 typo fixes
pci bus master fix
2016-04-21 20:11:09 +02:00
Ralph Metzler
de16096894 add new maps for dma and i/o 2016-04-20 16:27:56 +02:00
Ralph Metzler
a4062a1582 add mdio regmap 2016-04-17 19:43:54 +02:00
Ralph Metzler
d180cb70e2 octopro fixes 2016-04-15 23:53:20 +02:00
Ralph Metzler
30ca8e9962 another fix for irq handler v2 2016-04-15 22:51:50 +02:00
Ralph Metzler
4591bab46b irq v2 fixes
add no_init option to prevent most devices initializations
2016-04-15 22:45:55 +02:00
Ralph Metzler
3c6028f485 wrong interrupt status offsets 2016-04-15 19:17:00 +02:00
Ralph Metzler
6a49ab08ab add octopro entry 2016-04-15 19:16:04 +02:00
Ralph Metzler
8f30246ff1 first support for v2 irq core 2016-04-15 18:08:51 +02:00
Ralph Metzler
92d8b37839 q 2016-04-13 22:19:10 +02:00
Ralph Metzler
66c912d874 change pr_info to pr_debug for status debugging messages 2016-04-13 22:19:10 +02:00
Ralph Metzler
0b4d6d807a MSI fixes
- ack only the status bits belonging to corresponding interrupt handler
- set msi 2 instead of 1
2016-04-13 22:19:10 +02:00
mvoelkel
c4133d98c1 Merge branch 'master' into internal 2016-04-13 21:43:40 +02:00
mvoelkel
f111d6e097 Merge pull request #1 from herrnst/up/dos2unix
frontends: convert line endings from windows to unix format
2016-04-13 21:21:37 +02:00
Daniel Scheller
7860d623e8 frontends: convert line endings from windows to unix format 2016-04-13 18:33:29 +02:00
Ralph Metzler
ab25eeefdf use library log function 2016-04-12 12:19:14 +02:00
Ralph Metzler
64f21d8f99 allow higher transer speed for stv0910 2016-04-12 12:19:14 +02:00
mvoelkel
faee02e446 set version 0.9.23 2016-04-11 18:26:36 +02:00
mvoelkel
6d80791077 increase transportstream speed on stv0910 2016-04-11 18:26:21 +02:00
Ralph Metzler
1d3bb91eb8 cleanup 2016-04-11 18:26:07 +02:00
Ralph Metzler
c18503fcad fix stv0910 strength and snr values 2016-04-11 18:25:29 +02:00
Ralph Metzler
906efafd5e correct signal strength 2016-04-11 18:25:07 +02:00
Ralph Metzler
b479d9cdc2 remove conflict 2016-04-11 18:24:56 +02:00
Ralph Metzler
6038e87250 DOS line endings ?!?!!? WTF 2016-04-11 18:24:43 +02:00
Ralph Metzler
1b0e822b07 more status API support 2016-04-11 18:24:32 +02:00
Ralph Metzler
cdaf838cb1 add license support 2016-04-11 18:24:21 +02:00
Ralph Metzler
19fd6f1b26 comment out custom header code 2016-04-11 18:23:43 +02:00
Ralph Metzler
472cacb0c4 first support for new status API 2016-04-11 18:23:28 +02:00
mvoelkel
fa66a70a35 ddtest,ddflash: added Spansion S25FL132K,S25FL164K 2016-04-11 18:22:47 +02:00
mvoelkel
b5a44d581d Fallback for Max-A8 added 2016-04-11 18:22:37 +02:00
mvoelkel
e8eaf4660c Removed octoscan 2016-04-11 18:22:24 +02:00
mvoelkel
81966f8982 Add missing Max A8 variants 2016-04-11 18:22:11 +02:00
Ralph Metzler
dd540699c3 remove debugging message 2016-04-11 18:20:49 +02:00
Ralph Metzler
a8ed36fef2 cleanup 2016-04-11 18:20:13 +02:00
Ralph Metzler
9ab1b7f533 disable debug message 2016-04-11 18:19:31 +02:00
Ralph Metzler
197897731e NULL pointer cleanup 2016-04-11 18:17:20 +02:00
mvoelkel
781686c87d Set version number to 0.9.22 2016-01-13 16:58:01 +01:00
Ralph Metzler
b354113d15 disable auto DVB-S/S2 switching 2016-01-07 21:13:21 +01:00
Ralph Metzler
8d0bb02239 add octoscan 2016-01-07 21:12:53 +01:00
mvoelkel
7eb4ff762c Release 0.9.21 2015-12-11 16:10:07 +01:00
mvoelkel
16f0d291b1 Version 0.9.21 2015-12-11 16:06:24 +01:00
Ralph Metzler
829929a41f cine s2 v7 has TS lines crossed 2015-12-10 18:26:45 +01:00
Ralph Metzler
af746a02dd spelling error 2015-11-05 19:06:52 +01:00
Ralph Metzler
e83dedf6b4 First check for LNBHs on 0x0c/0x0d. 2015-10-22 14:55:55 +02:00
Ralph Metzler
9bcb9a2c9a Remove unused status variable. 2015-10-22 14:54:48 +02:00
Ralph Metzler
66be95a2b9 Missing return value. 2015-10-22 14:53:34 +02:00
Ralph Metzler
bb334ea229 Change handling of card type attribute. 2015-10-22 14:52:59 +02:00
Ralph Metzler
535683dfb6 Octopus CI single has two TABs. Handle both I2C busses. 2015-10-22 14:52:27 +02:00
Ralph Metzler
d10c83f16a Change handling of card type attribute. 2015-10-22 14:51:36 +02:00
Ralph Metzler
18481e2ea6 destroy attribute devices earlier to prevent accesses after I2C devices are already gone 2015-09-25 17:45:48 +02:00
Ralph Metzler
8402c7ab05 show temperature on sleep 2015-09-24 23:29:40 +02:00
Ralph Metzler
e2145682e2 block opening of ci device with O_RDWR 2015-09-24 23:29:09 +02:00
Ralph Metzler
1173454c93 add sleep function 2015-09-20 18:49:16 +02:00
Ralph Metzler
1aacccef7c add remote interrupt status to debug message 2015-09-20 01:50:39 +02:00
Ralph Metzler
dd78dae68b loop over remote link interrupt status to prevent race condition 2015-09-20 01:45:11 +02:00
Ralph Metzler
0393ab4db4 remove debugging messages 2015-09-19 22:20:35 +02:00
Ralph Metzler
29dc0f9e31 Initial support for Max C2T2-8 2015-09-17 18:54:25 +02:00
39 changed files with 43519 additions and 39480 deletions

View File

@@ -1,3 +1,6 @@
0.9.24 2016.08.03
- suport new V2 modulator cards
0.9.19c 2015.07.20
- MAX S8:
do not turn on diseqc and tuners on init

View File

@@ -9,6 +9,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <getopt.h>
uint32_t adapter = 0, device = 0, snum = 256, rnum = 256;
uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
@@ -68,24 +71,34 @@ void proc_buf(uint8_t *buf, uint32_t *d)
} else {
if (memcmp(ts+8, buf+8, 180))
printf("error\n");
if (!(c&0xffff))
printf("R %08x\n", c);
if (!(c&0xffff)) {
printf("R %08x\r", c);
fflush(0);
}
}
(*d)++;
}
void *get_ts(void *a)
{
uint8_t buf[188*1024];
uint8_t *buf;
int len, off;
int fdi=open("/dev/dvb/adapter2/ci0", O_RDONLY);
int fdi;
char fname[80];
uint32_t d=0;
buf = malloc(188*rnum);
if (!buf)
return NULL;
sprintf(fname, "/dev/dvb/adapter%u/ci%u", adapter, device);
fdi = open(fname, O_RDONLY);
while (1) {
len=read(fdi, buf, 188*1024);
memset(buf, 0, 188*rnum);
len=read(fdi, buf, 188*rnum);
if (len<0)
continue;
//printf("read %u\n", len);
if (buf[0]!=0x47) {
read(fdi, buf, 1);
continue;
@@ -96,20 +109,23 @@ void *get_ts(void *a)
}
}
#define SNUM 233
//671
void send(void)
int send(void)
{
uint8_t buf[188*SNUM], *cts;
uint8_t *buf, *cts;
int i;
uint32_t c=0;
int fdo;
char fname[80];
fdo=open("/dev/dvb/adapter2/ci0", O_WRONLY);
buf = malloc(188*snum);
if (!buf)
return -1;
sprintf(fname, "/dev/dvb/adapter%u/ci%u", adapter, device);
fdo=open(fname, O_WRONLY);
while (1) {
for (i=0; i<SNUM; i++) {
for (i=0; i<snum; i++) {
cts=buf+i*188;
memcpy(cts, ts, 188);
cts[4]=(c>>24);
@@ -122,15 +138,54 @@ void send(void)
//usleep(100000+0xffff&rand());
//usleep(1000);
}
write(fdo, buf, 188*SNUM);
write(fdo, buf, 188*snum);
}
}
int main()
int main(int argc, char **argv)
{
pthread_t th;
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"adapter", required_argument, 0, 'a'},
{"device", required_argument, 0, 'd'},
{"snum", required_argument, 0, 's'},
{"rnum", required_argument, 0, 'r'},
{"help", no_argument , 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"a:d:h",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 10);
break;
case 'a':
adapter = strtoul(optarg, NULL, 10);
break;
case 's':
snum = strtoul(optarg, NULL, 10);
break;
case 'r':
rnum = strtoul(optarg, NULL, 10);
break;
case 'h':
default:
break;
}
}
if (optind < argc) {
printf("Warning: unused arguments\n");
}
memset(ts+8, 180, 0x5a);
pthread_create(&th, NULL, get_ts, NULL);
usleep(10000);

View File

@@ -17,3 +17,4 @@ octonet: octonet.c
octokey: octokey.c
$(CC) -o octokey octokey.c

View File

@@ -91,6 +91,8 @@ enum {
SSTI_SST25VF032B = 3,
SSTI_SST25VF064C = 4,
SPANSION_S25FL116K = 5,
SPANSION_S25FL132K = 6,
SPANSION_S25FL164K = 7,
};
static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
@@ -393,6 +395,8 @@ static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxle
case SSTI_SST25VF064C:
return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off);
case SPANSION_S25FL116K:
case SPANSION_S25FL132K:
case SPANSION_S25FL164K:
return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off);
}
return -1;
@@ -467,6 +471,16 @@ static int flash_detect(struct ddflash *ddf)
printf("Flash: SPANSION S25FL116K 16 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x200000;
} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x16) {
ddf->flash_type = SPANSION_S25FL132K;
printf("Flash: SPANSION S25FL132K 32 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x400000;
} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x17) {
ddf->flash_type = SPANSION_S25FL164K;
printf("Flash: SPANSION S25FL164K 64 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x800000;
} else if (id[0] == 0x1F && id[1] == 0x28) {
ddf->flash_type = ATMEL_AT45DB642D;
printf("Flash: Atmel AT45DB642D 64 MBit\n");

View File

@@ -28,6 +28,8 @@ enum {
SSTI_SST25VF032B = 3,
SSTI_SST25VF064C = 4,
SPANSION_S25FL116K = 5,
SPANSION_S25FL132K = 6,
SPANSION_S25FL164K = 7,
};
struct SCommand
@@ -143,7 +145,6 @@ int ReadFlash(int ddb, int argc, char *argv[], uint32_t Flags)
}
int FlashDetect(int dev)
{
uint8_t Cmd = 0x9F;
@@ -161,6 +162,10 @@ int FlashDetect(int dev)
r = SSTI_SST25VF064C;
else if ( Id[0] == 0x01 && Id[1] == 0x40 && Id[2] == 0x15 )
r = SPANSION_S25FL116K;
else if ( Id[0] == 0x01 && Id[1] == 0x40 && Id[2] == 0x16 )
r = SPANSION_S25FL132K;
else if ( Id[0] == 0x01 && Id[1] == 0x40 && Id[2] == 0x17 )
r = SPANSION_S25FL164K;
else if ( Id[0] == 0x1F && Id[1] == 0x28)
r = ATMEL_AT45DB642D;
else
@@ -185,6 +190,12 @@ int FlashDetect(int dev)
case SPANSION_S25FL116K :
printf("Flash: SPANSION S25FL116K 16 MBit\n");
break;
case SPANSION_S25FL132K :
printf("Flash: SPANSION S25FL132K 32 MBit\n");
break;
case SPANSION_S25FL164K :
printf("Flash: SPANSION S25FL164K 64 MBit\n");
break;
}
return r;
}
@@ -753,7 +764,6 @@ uint32_t GetFPGA_ID(uint8_t * Buffer)
}
int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
{
uint8_t * Buffer = NULL;
@@ -776,6 +786,8 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SSTI_SST25VF032B: SectorSize = 4096; FlashSize = 0x400000; break;
case SSTI_SST25VF064C: SectorSize = 4096; FlashSize = 0x800000; break;
case SPANSION_S25FL116K: SectorSize = 4096; FlashSize = 0x200000; break;
case SPANSION_S25FL132K: SectorSize = 4096; FlashSize = 0x400000; break;
case SPANSION_S25FL164K: SectorSize = 4096; FlashSize = 0x800000; break;
}
if (SectorSize == 0)
return 0;
@@ -943,6 +955,8 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SSTI_SST25VF064C:
err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x3C); break;
case SPANSION_S25FL116K:
case SPANSION_S25FL132K:
case SPANSION_S25FL164K:
err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x1C); break;
}
@@ -1017,6 +1031,7 @@ int FlashVerify(int dev,int argc, char* argv[],uint32_t Flags)
read(fh,Buffer,fsize);
close(fh);
#if 0
if( BufferSize >= 0x10000 )
{
int i;
@@ -1028,6 +1043,7 @@ int FlashVerify(int dev,int argc, char* argv[],uint32_t Flags)
}
// Place our own header
}
#endif
if (flashread(dev, Buffer2, FlashOffset, BufferSize)<0) {
printf("Ioctl returns error\n");
free(Buffer);
@@ -1418,6 +1434,276 @@ int XO2Prog(int dev, int argc, char* argv[], uint32_t Flags)
return 0;
}
// -----------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------
#define LICENSE_CONTROL 0x1C
void GetId(int dev, uint8_t Id[])
{
int i;
for(i = 0; i < 4; i += 1) {
uint32_t tmp;
writereg(dev,LICENSE_CONTROL,0x00100000 + (i << 16));
readreg(dev,LICENSE_CONTROL,&tmp);
Id[i*2] = ((tmp >> 24) & 0xFF);
Id[i*2+1] = ((tmp >> 16) & 0xFF);
}
writereg(dev,LICENSE_CONTROL,0x00000000);
}
void GetLK(int dev, uint8_t LK[])
{
int i;
for (i = 0; i < 12; i += 1) {
uint32_t tmp;
writereg(dev, LICENSE_CONTROL,0x00140000 + (i << 16));
readreg(dev,LICENSE_CONTROL,&tmp);
LK[i*2] = ((tmp >> 24) & 0xFF);
LK[i*2+1] = ((tmp >> 16) & 0xFF);
}
writereg(dev, LICENSE_CONTROL, 0x00000000);
}
char *GetSerNbr(int dev)
{
char* SerNbr;
uint8_t Buffer[17];
uint32_t BytesReturned = 0;
uint32_t Start = 0x10;
int i;
memset(Buffer,0,sizeof(Buffer));
if (flashread(dev, Buffer, Start, sizeof(Buffer) - 1))
{
printf("Ioctl returns error\n");
return NULL;
}
if( Buffer[0] == 0xFF )
Buffer[0] = 0x00;
SerNbr = malloc(17);
memset(SerNbr, 0, sizeof(char) * 17);
for(i = 0; i < 17; i += 1) {
SerNbr[i] = (char) Buffer[i];
if( SerNbr[i] == 0 )
break;
}
return SerNbr;
}
int GetHex(char* s, uint32_t nBytes, uint8_t* Buffer)
{
int i;
if( strlen(s) < (nBytes * 2) ) return -1;
for (i = 0; i < nBytes; i += 1) {
char d0, d1;
d0 = s[i*2];
if( !isxdigit(d0) ) return -1;
d1 = s[i*2+1];
if( !isxdigit(d1) ) return -1;
Buffer[i] =(uint8_t) ((d0 > '9' ? d0 - 'A' + 10 : d0 - '0') << 4) | ((d1 > '9' ? d1 - 'A' + 10 : d1 - '0'));
}
return (nBytes * 2);
}
int lic_export(int dev, int argc, char* argv[], uint32_t Flags)
{
uint32_t HWVersion;
uint32_t DeviceID;
uint8_t Id[8];
uint8_t LK[24];
char *SerNbr;
FILE* fout = stdout;
int i;
GetId(dev,Id);
GetLK(dev,LK);
SerNbr = GetSerNbr(dev);
if( SerNbr == NULL )
return -1;
readreg(dev,0x00,&HWVersion);
readreg(dev,0x08,&DeviceID);
if( argc > 0 ) {
size_t n = strlen(argv[0]) + 8 + 16;
char *fname = malloc(n);
snprintf(fname, n-1, "%s_%s.lic",argv[0],SerNbr);
fout = fopen(fname,"w");
if( fout == NULL ) {
printf("Can't create outputfile\n");
return 0;
}
}
fprintf(fout,"VEN:%04X\n",DeviceID & 0xFFFF);
fprintf(fout,"DEV:%04X\n",(DeviceID >> 16) & 0xFFFF);
fprintf(fout,"VER:%08X\n",HWVersion);
fprintf(fout,"SERNBR:%s\n",SerNbr);
fprintf(fout,"ID:");
for (i = 0; i < 8; i += 1)
fprintf(fout,"%02X",Id[i]);
fprintf(fout,"\n");
fprintf(fout,"LK:");
for (i = 0; i < 24; i += 1)
fprintf(fout,"%02X",LK[i]);
fprintf(fout,"\n");
if( argc > 0 ) fclose(fout);
return 0;
}
int lic_import(int dev, int argc, char* argv[], uint32_t Flags)
{
uint8_t LicId[8];
uint8_t CardId[8];
char *SerNbr;
uint8_t *Buffer;
FILE* fin;
int Flash;
uint32_t FlashSize = 0;
int err = 0;
if( argc < 1 ) return -1;
GetId(dev, CardId);
SerNbr = GetSerNbr(dev);
if( SerNbr == NULL )
return -1;
Buffer = malloc(4096);
memset(Buffer, 0xFF, 4096);
fin = fopen(argv[0], "r");
if( fin == NULL )
{
printf("License file not found\n");
return -1;
}
memset(LicId,0,8);
while(1) {
char s[128];
if( fgets(s,sizeof(s)-1,fin) == NULL ) break;
fputs(s,stdout);
if (strncmp(s,"ID:",3) == 0 )
{
if( GetHex(&s[3],8,LicId) < 0 ) return -1;
}
if (strncmp(s,"LK:",3) == 0 )
{
if( GetHex(&s[3],24,Buffer) < 0 ) return -1;
}
}
fclose(fin);
if( memcmp(CardId,LicId,8) != 0 )
{
printf("Invalid ID\n");
free(Buffer);
return -1;
}
Dump(Buffer,0,24);
Flash = FlashDetect(dev);
switch(Flash) {
case SSTI_SST25VF064C: err = FlashWritePageMode(dev,0x7FE000,Buffer,4096,0x3C); break;
case SPANSION_S25FL116K: err = FlashWritePageMode(dev,0x1FE000,Buffer,4096,0x1C); break;
case SPANSION_S25FL132K: err = FlashWritePageMode(dev,0x3FE000,Buffer,4096,0x1C); break;
case SPANSION_S25FL164K: err = FlashWritePageMode(dev,0x7FE000,Buffer,4096,0x1C); break;
default:
printf("Unsupported Flash\n");
break;
}
free(Buffer);
return 0;
}
int lic_erase(int dev, int argc, char* argv[], uint32_t Flags)
{
uint8_t* Buffer = malloc(4096);
int Flash = FlashDetect(dev);
uint32_t FlashSize = 0;
int err = -1;
memset(Buffer, 0xFF, 4096);
switch(Flash)
{
case SSTI_SST25VF064C: err = FlashWritePageMode(dev,0x7FE000,Buffer,4096,0x3C); break;
case SPANSION_S25FL116K: err = FlashWritePageMode(dev,0x1FE000,Buffer,4096,0x1C); break;
case SPANSION_S25FL132K: err = FlashWritePageMode(dev,0x3FE000,Buffer,4096,0x1C); break;
case SPANSION_S25FL164K: err = FlashWritePageMode(dev,0x7FE000,Buffer,4096,0x1C); break;
default:
printf("Unsupported Flash\n");
break;
}
free(Buffer);
return err;
}
static int read_sfpd(int dev, uint8_t adr, uint8_t *val)
{
uint8_t cmd[5] = { 0x5a, 0, 0, adr, 00 };
int r;
r = FlashIO(dev, cmd, 5, val, 1);
if (r < 0)
return r;
return 0;
}
static int read_sst_id(int dev, uint8_t *id)
{
uint8_t cmd[2] = { 0x88, 0 };
uint8_t buf[9];
int r;
r = FlashIO(dev, cmd, 2, buf, 9);
if (r < 0)
return r;
memcpy(id, buf + 1, 8);
return 0;
}
int read_id(int dev, int argc, char* argv[], uint32_t Flags)
{
int Flash = FlashDetect(dev);
uint8_t Cmd;;
uint8_t Id[8];
uint32_t len, i, adr;
switch(Flash) {
case SPANSION_S25FL116K:
case SPANSION_S25FL132K:
case SPANSION_S25FL164K:
for (i = 0; i < 8; i++)
read_sfpd(dev, 0xf8 + i, &Id[i]);
len = 8;
break;
case SSTI_SST25VF064C:
read_sst_id(dev, Id);
len = 8;
break;
default:
printf("Unsupported Flash\n");
break;
}
printf("ID: ");
for (i = 0; i < 8; i++)
printf("%02x ", Id[i]);
printf("\n");
}
struct SCommand CommandTable[] =
{
@@ -1427,7 +1713,7 @@ struct SCommand CommandTable[] =
{ "register", GetSetRegister, 1, "Get/Set Register : reg <regname>|<[0x]regnum> [[0x]value(32)]" },
{ "flashread", ReadFlash, 1, "Read Flash : flashread <start> <count>" },
{ "flashio", FlashIO, 1, "Flash IO : flashio <write data>.. <read count>" },
{ "flashio", FlashIOC, 1, "Flash IO : flashio <write data>.. <read count>" },
{ "flashprog", FlashProg, 1, "Flash Programming : flashprog <FileName> [<address>]" },
{ "flashprog", FlashProg, 1, "Flash Programming : flashprog -SubVendorID <id>" },
{ "flashprog", FlashProg, 1, "Flash Programming : flashprog -Jump <address>" },
@@ -1438,6 +1724,11 @@ struct SCommand CommandTable[] =
{ "mdio", mdio, 1, "mdio : mdio <adr> <reg> [<value>]" },
{ "xo2prog", XO2Prog, 1, "DuoFlex Programming : xo2prog <FileName> [<BusNumber>]" },
{ "licimport", lic_import, 1, "License Import : licimport" },
{ "licexport", lic_export, 1, "License Export : licexport" },
{ "licerase", lic_erase, 1, "License Erase : licerase" },
{ "read_id", read_id, 1, "Read Unique ID : read_id" },
{ NULL,NULL,0 }
};

File diff suppressed because it is too large Load Diff

View File

@@ -122,10 +122,20 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
dev_err(dev->dev, "DDBridge IRS %08x\n", istat);
if (i2c->link) {
u32 listat =
ddbreadl(dev,
DDB_LINK_TAG(i2c->link) |
INTERRUPT_STATUS);
dev_err(dev->dev,
"DDBridge link %u IRS %08x\n",
i2c->link, listat);
}
if (istat & 1) {
ddbwritel(dev, istat & 1, INTERRUPT_ACK);
} else {
u32 mon = ddbreadl(dev, i2c->regs + I2C_MONITOR);
u32 mon = ddbreadl(dev,
i2c->regs + I2C_MONITOR);
dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n",
val, mon);
@@ -219,14 +229,15 @@ static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
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);
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
@@ -236,7 +247,9 @@ static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
adap->class = I2C_CLASS_TV_ANALOG;
#endif
#endif
strcpy(adap->name, "ddbridge");
/*strcpy(adap->name, "ddbridge");*/
snprintf(adap->name, I2C_NAME_SIZE, "ddbridge_%02x.%x.%x",
dev->nr, i2c->link, i);
adap->algo = &ddb_i2c_algo;
adap->algo_data = (void *)i2c;
adap->dev.parent = dev->dev;
@@ -246,7 +259,7 @@ static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c,
static int ddb_i2c_init(struct ddb *dev)
{
int stat = 0;
u32 i, j, num = 0, l;
u32 i, j, num = 0, l, base;
struct ddb_i2c *i2c;
struct i2c_adapter *adap;
struct ddb_regmap *regmap;
@@ -257,12 +270,13 @@ static int ddb_i2c_init(struct ddb *dev)
regmap = dev->link[l].info->regmap;
if (!regmap || !regmap->i2c)
continue;
base = regmap->irq_base_i2c;
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;
dev->handler_data[l][i + base] = (unsigned long) i2c;
dev->handler[l][i + base] = i2c_handler;
stat = ddb_i2c_add(dev, i2c, regmap, l, i, num);
if (stat)
break;

View File

@@ -28,6 +28,10 @@
#include <linux/dvb/mod.h>
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
inline s64 ConvertPCR(s64 a)
{
s32 ext;
@@ -72,6 +76,81 @@ inline s64 RoundPCRDown(s64 a)
return a & ~(HW_LSB_MASK - 1);
}
// Calculating KF, LF from Symbolrate
//
// Symbolrate is usually calculated as (M/N) * 10.24 MS/s
//
// Common Values for M,N
// J.83 Annex A,
// Euro Docsis 6.952 MS/s : M = 869, N = 1280
// 6.900 MS/s : M = 345, N = 512
// 6.875 MS/s : M = 1375, N = 2048
// 6.111 MS/s : M = 6111, N = 10240
// J.83 Annex B **
// QAM64 5.056941 : M = 401, N = 812
// QAM256 5.360537 : M = 78, N = 149
// J.83 Annex C **
// 5.309734 : M = 1889, N = 3643
//
// For the present hardware
// KF' = 256 * M
// LF' = 225 * N
// or
// KF' = Symbolrate in Hz
// LF' = 9000000
//
// KF = KF' / gcd(KF',LF')
// LF = LF' / gcd(KF',LF')
// Note: LF must not be a power of 2.
// Maximum value for KF,LF = 13421727 ( 0x7FFFFFF )
// ** using these M,N values will result in a small err (<5ppm)
// calculating KF,LF directly gives the exact normative result
// but with rather large KF,LF values
static inline u32 gcd(u32 u,u32 v)
{
int s = 0;
while (((u|v)&1) == 0) {
s += 1;
u >>= 1;
v >>= 1;
}
while ((u&1) == 0)
u >>= 1;
do {
while ( (v&1) == 0 ) v >>= 1;
if( u > v ) {
u32 t = v;
v = u;
u = t;
}
v = v - u;
} while(v != 0);
return u << s;
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static int mod_SendChannelCommand(struct ddb *dev, u32 Channel, u32 Command)
{
u32 ControlReg = ddbreadl(dev, CHANNEL_CONTROL(Channel));
ControlReg = (ControlReg & ~CHANNEL_CONTROL_CMD_MASK)|Command;
ddbwritel(dev, ControlReg, CHANNEL_CONTROL(Channel));
while(1) {
ControlReg = ddbreadl(dev, CHANNEL_CONTROL(Channel));
if (ControlReg == 0xFFFFFFFF)
return -EIO;
if((ControlReg & CHANNEL_CONTROL_CMD_STATUS) == 0)
break;
}
if (ControlReg & CHANNEL_CONTROL_ERROR_CMD)
return -EINVAL;
return 0;
}
static int mod_busy(struct ddb *dev, int chan)
{
u32 creg;
@@ -89,10 +168,12 @@ static int mod_busy(struct ddb *dev, int chan)
void ddbridge_mod_output_stop(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
struct mod_state *mod = &dev->mod[output->nr];
struct ddb_mod *mod = &dev->mod[output->nr];
mod->State = CM_IDLE;
mod->Control = 0;
if (dev->link[0].info->version == 2)
mod_SendChannelCommand(dev, output->nr, CHANNEL_CONTROL_CMD_FREE);
ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
#if 0
udelay(10);
@@ -108,7 +189,7 @@ static void mod_set_incs(struct ddb_output *output)
{
s64 pcr;
struct ddb *dev = output->port->dev;
struct mod_state *mod = &dev->mod[output->nr];
struct ddb_mod *mod = &dev->mod[output->nr];
pcr = ConvertPCR(mod->PCRIncrement);
ddbwritel(dev, pcr & 0xffffffff,
@@ -137,7 +218,9 @@ static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 };
void ddbridge_mod_output_start(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
struct mod_state *mod = &dev->mod[output->nr];
u32 Channel = output->nr;
struct ddb_mod *mod = &dev->mod[output->nr];
u32 Symbolrate = 6900000;
/*PCRIncrement = RoundPCR(PCRIncrement);*/
/*PCRDecrement = RoundPCR(PCRDecrement);*/
@@ -164,18 +247,55 @@ void ddbridge_mod_output_start(struct ddb_output *output)
udelay(10);
ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
pr_info("CHANNEL_BASE = %08x\n", CHANNEL_BASE);
pr_info("CHANNEL_CONTROL = %08x\n", CHANNEL_CONTROL(Channel));
if (dev->link[0].info->version == 2) {
u32 Output = ((dev->mod_base.frequency - 114000000)/8000000 + Channel) % 96;
u32 KF = Symbolrate;
u32 LF = 9000000UL;
u32 d = gcd(KF,LF);
u32 checkLF;
mod->modulation = QAM_256 - 1;
ddbwritel(dev, mod->modulation, CHANNEL_SETTINGS(Channel));
ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel));
KF = KF / d;
LF = LF / d;
while( (KF > KFLF_MAX) || (LF > KFLF_MAX) ) {
KF >>= 1;
LF >>= 1;
}
checkLF = LF;
while ((checkLF & 1) == 0)
checkLF >>= 1;
if (checkLF <= 1)
return -EINVAL;
pr_info("KF=%u LF=%u Output=%u mod=%u\n", KF, LF, Output, mod->modulation);
ddbwritel(dev, KF, CHANNEL_KF(Channel));
ddbwritel(dev, LF, CHANNEL_LF(Channel));
if (mod_SendChannelCommand(dev, Channel, CHANNEL_CONTROL_CMD_SETUP))
return -EINVAL;
mod->Control = CHANNEL_CONTROL_ENABLE_DVB;
} else {
/* QAM: 600 601 602 903 604 = 16 32 64 128 256 */
/* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */
ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr));
mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | CHANNEL_CONTROL_ENABLE_DVB);
}
mod_set_rateinc(dev, output->nr);
mod_set_incs(output);
mod->Control = (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB |
CHANNEL_CONTROL_ENABLE_SOURCE);
mod->Control |= CHANNEL_CONTROL_ENABLE_SOURCE;
ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
if (dev->link[0].info->version == 2)
if (mod_SendChannelCommand(dev, Channel, CHANNEL_CONTROL_CMD_UNMUTE))
return -EINVAL;
pr_info("mod_output_start %d.%d\n", dev->nr, output->nr);
}
@@ -183,6 +303,195 @@ void ddbridge_mod_output_start(struct ddb_output *output)
/****************************************************************************/
/****************************************************************************/
static int mod_write_max2871(struct ddb *dev, u32 val)
{
ddbwritel(dev, val, MAX2871_OUTDATA);
ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE, MAX2871_CONTROL);
while(1) {
u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL);
if (ControlReg == 0xFFFFFFFF)
return -EIO;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
break;
}
return 0;
}
static int mod_setup_max2871(struct ddb *dev)
{
int status = 0;
int i;
ddbwritel(dev, MAX2871_CONTROL_CE, MAX2871_CONTROL);
for (i = 0; i < 2; i++) {
status = mod_write_max2871(dev, 0x00440005);
if (status)
break;
status = mod_write_max2871(dev, 0x6199003C);
if (status)
break;
status = mod_write_max2871(dev, 0x000000CB);
if (status)
break;
status = mod_write_max2871(dev, 0x510061C2);
if (status)
break;
status = mod_write_max2871(dev, 0x600080A1);
if (status)
break;
status = mod_write_max2871(dev, 0x00730040);
if (status)
break;
msleep(30);
} while(0);
if (status == 0) {
u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL);
if ((ControlReg & MAX2871_CONTROL_LOCK) == 0)
status = -EIO;
}
return status;
}
static int mod_fsm_setup(struct ddb *dev, u32 FrequencyPlan, u32 MaxUsedChannels)
{
int status = 0;
u32 Capacity;
u32 tmp = ddbreadl(dev, FSM_STATUS);
if ((tmp & FSM_STATUS_READY) == 0) {
status = mod_setup_max2871(dev);
if (status)
return status;
ddbwritel(dev, FSM_CMD_RESET, FSM_CONTROL);
msleep(10);
tmp = ddbreadl(dev, FSM_STATUS);
if ((tmp & FSM_STATUS_READY) == 0)
return -1;
}
Capacity = ddbreadl(dev, FSM_CAPACITY);
if (((tmp & FSM_STATUS_QAMREADY) != 0) &&
((Capacity & FSM_CAPACITY_INUSE) != 0))
return -EBUSY;
ddbwritel(dev, FSM_CMD_SETUP, FSM_CONTROL);
msleep(10);
tmp = ddbreadl(dev, FSM_STATUS);
if ((tmp & FSM_STATUS_QAMREADY) == 0)
return -1;
if (MaxUsedChannels == 0)
MaxUsedChannels = (Capacity & FSM_CAPACITY_CUR) >> 16;
pr_info("max used chan = %u\n", MaxUsedChannels);
if (MaxUsedChannels <= 1 )
ddbwritel(dev, FSM_GAIN_N1, FSM_GAIN);
else if (MaxUsedChannels <= 2)
ddbwritel(dev, FSM_GAIN_N2, FSM_GAIN);
else if (MaxUsedChannels <= 4)
ddbwritel(dev, FSM_GAIN_N4, FSM_GAIN);
else if (MaxUsedChannels <= 8)
ddbwritel(dev, FSM_GAIN_N8, FSM_GAIN);
else if (MaxUsedChannels <= 16)
ddbwritel(dev, FSM_GAIN_N16, FSM_GAIN);
else if (MaxUsedChannels <= 24)
ddbwritel(dev, FSM_GAIN_N24, FSM_GAIN);
else
ddbwritel(dev, FSM_GAIN_N96, FSM_GAIN);
ddbwritel(dev, FSM_CONTROL_ENABLE, FSM_CONTROL);
return status;
}
static int mod_set_vga(struct ddb *dev, u32 Gain)
{
if( Gain > 255 )
return -EINVAL;
ddbwritel(dev, Gain, RF_VGA);
return 0;
}
static int mod_get_vga(struct ddb *dev, u32 *pGain)
{
*pGain = ddbreadl(dev, RF_VGA);
return 0;
}
static void mod_TemperatureMonitorSetFan(struct ddb *dev)
{
u32 tqam, pwm;
if ((ddbreadl(dev, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0) {
pr_info("Over temperature condition\n");
dev->mod_base.OverTemperatureError = 1;
}
tqam = (ddbreadl(dev, TEMPMON2_QAMCORE) >> 8) & 0xFF;
if (tqam & 0x80)
tqam = 0;
pwm = (ddbreadl(dev, TEMPMON_FANCONTROL) >> 8) & 0x0F;
if (pwm > 10)
pwm = 10;
if (tqam >= dev->mod_base.temp_tab[pwm]) {
while( pwm < 10 && tqam >= dev->mod_base.temp_tab[pwm + 1])
pwm += 1;
} else {
while( pwm > 1 && tqam < dev->mod_base.temp_tab[pwm - 2])
pwm -= 1;
}
ddbwritel(dev, (pwm << 8), TEMPMON_FANCONTROL);
}
static void mod_temp_handler(unsigned long data)
{
struct ddb *dev = (struct ddb *) data;
pr_info("mod_temp_handler\n");
spin_lock(&dev->mod_base.temp_lock);
mod_TemperatureMonitorSetFan(dev);
spin_unlock(&dev->mod_base.temp_lock);
}
static int mod_TemperatureMonitorInit(struct ddb *dev, int FirstTime) {
int status = 0;
spin_lock_irq(&dev->mod_base.temp_lock);
if (FirstTime) {
static u8 TemperatureTable[11] = {30,35,40,45,50,55,60,65,70,75,80};
memcpy(dev->mod_base.temp_tab, TemperatureTable, sizeof(TemperatureTable));
}
dev->handler[0][8] = mod_temp_handler;
dev->handler_data[0][8] = (unsigned long) dev;
ddbwritel(dev, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN |
TEMPMON_CONTROL_INTENABLE),
TEMPMON_CONTROL);
ddbwritel(dev, (3 << 8), TEMPMON_FANCONTROL);
dev->mod_base.OverTemperatureError =
((ddbreadl(dev, TEMPMON_CONTROL) & TEMPMON_CONTROL_OVERTEMP ) != 0);
if (dev->mod_base.OverTemperatureError) {
pr_info("Over temperature condition\n");
status = -1;
}
mod_TemperatureMonitorSetFan(dev);
spin_unlock_irq(&dev->mod_base.temp_lock);
return status;
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value)
{
u32 RegValue = 0;
@@ -804,7 +1113,7 @@ static int set_base_frequency(struct ddb *dev, u32 freq)
return mod_set_down(dev, down, 8, Ext);
}
static int mod_init(struct ddb *dev, u32 Frequency)
static int mod_init_1(struct ddb *dev, u32 Frequency)
{
int stat = 0;
u8 *buffer;
@@ -906,7 +1215,7 @@ void ddbridge_mod_rate_handler(unsigned long data)
struct ddb_output *output = (struct ddb_output *) data;
struct ddb_dma *dma = output->dma;
struct ddb *dev = output->port->dev;
struct mod_state *mod = &dev->mod[output->nr];
struct ddb_mod *mod = &dev->mod[output->nr];
u32 chan = output->nr;
u32 OutPacketCount;
@@ -965,7 +1274,8 @@ void ddbridge_mod_rate_handler(unsigned long data)
InPacketDiff/1000));
if (OutPacketDiff)
mod->rate_inc =
div_u64(mul, OutPacketDiff);
div_u64(mul,
OutPacketDiff);
else
mod->rate_inc = 0;
mod_set_rateinc(dev, output->nr);
@@ -975,7 +1285,8 @@ void ddbridge_mod_rate_handler(unsigned long data)
if (InPacketDiff)
mod->PCRDecrement =
div_u64(mod->PCRIncrement *
(u64) OutPacketDiff,
(u64)
OutPacketDiff,
InPacketDiff);
else
mod->PCRDecrement = 0;
@@ -1079,7 +1390,7 @@ void ddbridge_mod_rate_handler(unsigned long data)
PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement);
}
int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
static int mod_ioctl_1(struct file *file, unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev = file->private_data;
struct ddb_output *output = dvbdev->priv;
@@ -1144,7 +1455,114 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
return ret;
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static int mod_ioctl_2(struct file *file, unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev = file->private_data;
struct ddb_output *output = dvbdev->priv;
struct ddb *dev = output->port->dev;
/* unsigned long arg = (unsigned long) parg; */
int ret = 0;
switch (cmd) {
case DVB_MOD_SET:
{
struct dvb_mod_params *mp = parg;
pr_info("set base freq\n");
dev->mod_base.frequency = mp->base_frequency;
pr_info("set attenuator\n");
mod_set_attenuator(dev, mp->attenuator);
break;
}
case DVB_MOD_CHANNEL_SET:
{
struct dvb_mod_channel_params *cp = parg;
int res;
u32 ri;
pr_info("set modulation\n");
res = mod_set_modulation(dev, output->nr, cp->modulation);
if (res)
return res;
if (cp->input_bitrate > dev->mod[output->nr].obitrate)
return -EINVAL;
dev->mod[output->nr].ibitrate = cp->input_bitrate;
dev->mod[output->nr].pcr_correction = cp->pcr_correction;
pr_info("ibitrate %llu\n", dev->mod[output->nr].ibitrate);
pr_info("obitrate %llu\n", dev->mod[output->nr].obitrate);
if (cp->input_bitrate != 0) {
u64 d = dev->mod[output->nr].obitrate -
dev->mod[output->nr].ibitrate;
d = div64_u64(d, dev->mod[output->nr].obitrate >> 24);
if (d > 0xfffffe)
ri = 0xfffffe;
else
ri = d;
} else
ri = 0;
dev->mod[output->nr].rate_inc = ri;
pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n",
dev->mod[output->nr].ibitrate >> 32,
dev->mod[output->nr].obitrate >> 32,
ri);
break;
}
default:
ret = -EINVAL;
break;
}
return ret;
}
static int mod_init_2(struct ddb *dev, u32 Frequency)
{
int status;
int streams = dev->link[0].info->port_num;
dev->mod_base.frequency = Frequency;
mod_TemperatureMonitorInit(dev, 1);
status = mod_fsm_setup(dev, 0, 0);
if (streams <= 8)
mod_set_vga(dev, RF_VGA_GAIN_N8);
else if (streams <= 16)
mod_set_vga(dev, RF_VGA_GAIN_N16);
else
mod_set_vga(dev, RF_VGA_GAIN_N24);
mod_set_attenuator(dev, 0);
return 0;
}
int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev = file->private_data;
struct ddb_output *output = dvbdev->priv;
struct ddb *dev = output->port->dev;
if (dev->link[0].info->version <= 0)
return mod_ioctl_1(file, cmd, parg);
if (dev->link[0].info->version == 2)
return mod_ioctl_2(file, cmd, parg);
return -1;
}
int ddbridge_mod_init(struct ddb *dev)
{
return mod_init(dev, 722000000);
spin_lock_init(&dev->mod_base.temp_lock);
if (dev->link[0].info->version <= 1)
return mod_init_1(dev, 722000000);
if (dev->link[0].info->version == 2)
return mod_init_2(dev, 114000000);
return -1;
}

View File

@@ -198,10 +198,13 @@ static int ns_set_ci(struct dvbnss *nss, u8 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));
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_CONTROL(dev->port[ciport].output));
usleep_range(1, 5);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d, TS_OUTPUT_CONTROL(ciport));
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d,
TS_CONTROL(dev->port[ciport].output));
dns->fe = dev->port[ciport].input[0];
return 0;
}
@@ -443,7 +446,8 @@ static int ns_start(struct dvbnss *nss)
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);
/* 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;

View File

@@ -1,7 +1,7 @@
/*
* ddbridge-regs.h: Digital Devices PCIe bridge driver
*
* Copyright (C) 2010-2015 Digital Devices GmbH
* Copyright (C) 2010-2016 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
@@ -23,12 +23,11 @@
/* Register Definitions */
#define CUR_REGISTERMAP_VERSION 0x10003
#define CUR_REGISTERMAP_VERSION_CI 0x10000
#define CUR_REGISTERMAP_VERSION_MOD 0x10000
#define CUR_REGISTERMAP_VERSION_V1 0x00010001
#define CUR_REGISTERMAP_VERSION_V2 0x00020000
#define HARDWARE_VERSION 0x00
#define REGISTERMAP_VERSION 0x04
#define HARDWARE_VERSION 0x00000000
#define REGISTERMAP_VERSION 0x00000004
/* ------------------------------------------------------------------------- */
/* SPI Controller */
@@ -76,6 +75,8 @@
#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
#define INTERRUPT_ACK (INTERRUPT_BASE + 0x20)
#define INTERRUPT_ACK1 (INTERRUPT_BASE + 0x24)
#define INTERRUPT_ACK2 (INTERRUPT_BASE + 0x28)
#define INTMASK_CLOCKGEN (0x00000001)
#define INTMASK_TEMPMON (0x00000002)
@@ -105,6 +106,26 @@
#define INTMASK_TSOUTPUT4 (0x00080000)
#define INTERRUPT_V2_CONTROL (INTERRUPT_BASE + 0x00)
#define INTERRUPT_V2_ENABLE_1 (INTERRUPT_BASE + 0x04)
#define INTERRUPT_V2_ENABLE_2 (INTERRUPT_BASE + 0x08)
#define INTERRUPT_V2_ENABLE_3 (INTERRUPT_BASE + 0x0c)
#define INTERRUPT_V2_ENABLE_4 (INTERRUPT_BASE + 0x10)
#define INTERRUPT_V2_ENABLE_5 (INTERRUPT_BASE + 0x14)
#define INTERRUPT_V2_ENABLE_6 (INTERRUPT_BASE + 0x18)
#define INTERRUPT_V2_ENABLE_7 (INTERRUPT_BASE + 0x1c)
#define INTERRUPT_V2_STATUS (INTERRUPT_BASE + 0x20)
#define INTERRUPT_V2_STATUS_1 (INTERRUPT_BASE + 0x24)
#define INTERRUPT_V2_STATUS_2 (INTERRUPT_BASE + 0x28)
#define INTERRUPT_V2_STATUS_3 (INTERRUPT_BASE + 0x2c)
#define INTERRUPT_V2_STATUS_4 (INTERRUPT_BASE + 0x30)
#define INTERRUPT_V2_STATUS_5 (INTERRUPT_BASE + 0x34)
#define INTERRUPT_V2_STATUS_6 (INTERRUPT_BASE + 0x38)
#define INTERRUPT_V2_STATUS_7 (INTERRUPT_BASE + 0x3c)
/* Modulator registers */
@@ -128,23 +149,46 @@
/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */
#define TEMPMON_BASE (0xA0)
#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00)
#define TEMPMON_CONTROL_SCAN (0x00000001)
#define TEMPMON_CONTROL_AUTOSCAN (0x00000002)
#define TEMPMON_CONTROL_INTENABLE (0x00000004)
#define TEMPMON_CONTROL_OVERTEMP (0x00008000)
/* SHORT Temperature in <20>C x 256 */
#define TEMPMON_CORE (TEMPMON_BASE + 0x04)
#define TEMPMON_SENSOR0 (TEMPMON_BASE + 0x04)
#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08)
#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C)
#define TEMPMON_FANCONTROL (TEMPMON_BASE + 0x10)
#define TEMPMON_FANPWM (0x00000F00) // PWM speed in 10% steps
#define TEMPMON_FANTACHO (0x000000FF) // Rotations in 100/min steps
// V1 Temperature Monitor
// Temperature Monitor TEMPMON_CONTROL & 0x8000 == 0 : ( 2x LM75A @ 0x90,0x92 )
// Temperature Monitor TEMPMON_CONTROL & 0x8000 == 1 : ( 1x LM75A @ 0x90, 1x ADM1032 @ 0x9A )
#define TEMPMON1_CORE (TEMPMON_SENSOR0) // SHORT Temperature in <20>C x 256 (ADM1032 ext)
#define TEMPMON1_SENSOR1 (TEMPMON_BASE + 0x08) // SHORT Temperature in <20>C x 256 (LM75A 0x90)
#define TEMPMON1_SENSOR2 (TEMPMON_BASE + 0x0C) // SHORT Temperature in <20>C x 256 (LM75A 0x92 or ADM1032 Int)
// V2 Temperature Monitor 2 ADM1032
#define TEMPMON2_BOARD (TEMPMON_SENSOR0) // SHORT Temperature in <20>C x 256 (ADM1032 int)
#define TEMPMON2_FPGACORE (TEMPMON_SENSOR1) // SHORT Temperature in <20>C x 256 (ADM1032 ext)
#define TEMPMON2_QAMCORE (TEMPMON_SENSOR2) // SHORT Temperature in <20>C x 256 (ADM1032 ext)
/* ------------------------------------------------------------------------- */
/* 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)
@@ -173,26 +217,17 @@
#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_CONTROL(_io) (_io->regs + 0x00)
#define TS_CONTROL2(_io) (_io->regs + 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 DMA_BUFFER_CONTROL(_dma) (_dma->regs + 0x00)
#define DMA_BUFFER_ACK(_dma) (_dma->regs + 0x04)
#define DMA_BUFFER_CURRENT(_dma) (_dma->regs + 0x08)
#define DMA_BUFFER_SIZE(_dma) (_dma->regs + 0x0c)
/* ------------------------------------------------------------------------- */
@@ -263,6 +298,8 @@
#define CI_BLOCKIO_SEND_BUFFER(i) \
(CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE)
// V1
#define VCO1_BASE (0xC0)
#define VCO1_CONTROL (VCO1_BASE + 0x00)
#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */
@@ -293,6 +330,53 @@
/* Muxout from VCO (usually = Lock) */
#define VCO3_CONTROL_MUXOUT (0x00000004)
// V2
#define MAX2871_BASE (0xC0)
#define MAX2871_CONTROL (MAX2871_BASE + 0x00)
#define MAX2871_OUTDATA (MAX2871_BASE + 0x04) // 32 Bit
#define MAX2871_INDATA (MAX2871_BASE + 0x08) // 32 Bit
#define MAX2871_CONTROL_WRITE (0x00000001) // 1 = Trigger write, resets when done
#define MAX2871_CONTROL_CE (0x00000002) // 0 = Put VCO into power down
#define MAX2871_CONTROL_MUXOUT (0x00000004) // Muxout from VCO
#define MAX2871_CONTROL_LOCK (0x00000008) // Lock from VCO
#define FSM_BASE (0x200)
#define FSM_CONTROL (FSM_BASE + 0x00)
#define FSM_CONTROL_ENABLE (0x00000100)
#define FSM_CMD_MASK (0x00000087)
#define FSM_CMD_STATUS (0x00000080)
#define FSM_CMD_RESET (0x00000080)
#define FSM_CMD_POWERDOWN (0x00000081)
#define FSM_CMD_SETUP (0x00000082)
#define FSM_STATUS (FSM_BASE + 0x00)
#define FSM_STATUS_READY (0x00010000)
#define FSM_STATUS_QAMREADY (0x00020000)
#define FSM_CAPACITY (FSM_BASE + 0x04)
#define FSM_CAPACITY_MAX (0x3F000000)
#define FSM_CAPACITY_CUR (0x003F0000)
#define FSM_CAPACITY_INUSE (0x0000003F)
#define FSM_GAIN (FSM_BASE + 0x10)
#define FSM_GAINMASK (0x000000FF)
#define FSM_GAIN_N1 (0x000000FE)
#define FSM_GAIN_N2 (0x000000A1)
#define FSM_GAIN_N4 (0x00000066)
#define FSM_GAIN_N8 (0x00000048)
#define FSM_GAIN_N16 (0x0000002D)
#define FSM_GAIN_N24 (0x00000029)
#define FSM_GAIN_N96 (0x00000011)
// Attenuator/VGA
#define RF_ATTENUATOR (0xD8)
#define RF_ATTENUATOR (0xD8)
/* 0x00 = 0 dB
0x01 = 1 dB
@@ -300,6 +384,20 @@
0x1F = 31 dB
*/
#define RF_VGA (0xDC)
/* Only V2 */
/* 8 bit range 0 - 31.75 dB Gain */
/* VGA Gain for same output level as V1 Modulator */
#define RF_VGA_GAIN_N8 (85)
#define RF_VGA_GAIN_N16 (117)
#define RF_VGA_GAIN_N24 (122)
#define RF_VGA_GAIN_MAX (200)
/* V1 only */
#define RF_POWER (0xE0)
#define RF_POWER_BASE (0xE0)
#define RF_POWER_CONTROL (RF_POWER_BASE + 0x00)
@@ -343,7 +441,7 @@
#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010)
/* Modulator Base */
/* Modulator Base V1 */
#define MODULATOR_BASE (0x200)
#define MODULATOR_CONTROL (MODULATOR_BASE)
@@ -361,9 +459,11 @@
/* Modulator Channels */
#define CHANNEL_BASE (0x400)
#define CHANNEL_BASE dev->link[0].info->regmap->channel->base
#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00)
#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04)
#define CHANNEL_SETTINGS2(i) (CHANNEL_BASE + (i) * 64 + 0x08)
#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)
@@ -373,6 +473,8 @@
#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_KF(i) (CHANNEL_BASE + (i) * 64 + 0x30)
#define CHANNEL_LF(i) (CHANNEL_BASE + (i) * 64 + 0x34)
#define CHANNEL_CONTROL_RESET (0x00000001)
#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002)
@@ -381,8 +483,17 @@
#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010)
#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100)
#define CHANNEL_CONTROL_CMD_MASK (0x0000F000)
#define CHANNEL_CONTROL_CMD_STATUS (0x00008000)
#define CHANNEL_CONTROL_CMD_FREE (0x00008000)
#define CHANNEL_CONTROL_CMD_SETUP (0x00009000)
#define CHANNEL_CONTROL_CMD_MUTE (0x0000A000)
#define CHANNEL_CONTROL_CMD_UNMUTE (0x0000B000)
#define CHANNEL_CONTROL_RESET_ERROR (0x00010000)
#define CHANNEL_CONTROL_BUSY (0x01000000)
#define CHANNEL_CONTROL_ACTIVE (0x00400000)
#define CHANNEL_CONTROL_BUSY (0x00800000)
#define CHANNEL_CONTROL_ERROR_CMD (0x10000000)
#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000)
#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000)
#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000)
@@ -394,6 +505,14 @@
#define CHANNEL_SETTINGS_QAM128 (0x00000003)
#define CHANNEL_SETTINGS_QAM256 (0x00000004)
#define CHANNEL_SETTINGS2_OUTPUT_MASK (0x0000007F)
#define KFLF_MAX (0x07FFFFFFUL)
#define KF_INIT(Symbolrate) (Symbolrate)
#define LF_INIT(Symbolrate) (9000000UL)
#define MIN_SYMBOLRATE (1000000)
#define MAX_SYMBOLRATE (7100000)
/* OCTONET */

View File

@@ -24,7 +24,6 @@
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
/*#define DDB_ALT_DMA*/
#define DDB_USE_WORK
/*#define DDB_TEST_THREADED*/
@@ -58,19 +57,26 @@ static void ddb_unmap(struct ddb *dev)
vfree(dev);
}
static void __devexit ddb_remove(struct pci_dev *pdev)
static void __devexit ddb_irq_disable(struct ddb *dev)
{
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);
if (dev->link[0].info->regmap->irq_version == 2) {
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_3);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_4);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_5);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_6);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_7);
} else {
ddbwritel(dev, 0, INTERRUPT_ENABLE);
ddbwritel(dev, 0, MSI1_ENABLE);
}
}
static void __devexit ddb_irq_exit(struct ddb *dev)
{
ddb_irq_disable(dev);
if (dev->msi == 2)
free_irq(dev->pdev->irq + 1, dev);
free_irq(dev->pdev->irq, dev);
@@ -78,12 +84,25 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
if (dev->msi)
pci_disable_msi(dev->pdev);
#endif
}
static void __devexit ddb_remove(struct pci_dev *pdev)
{
struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
ddb_device_destroy(dev);
ddb_nsd_detach(dev);
ddb_ports_detach(dev);
ddb_i2c_release(dev);
if (dev->link[0].info->ns_num)
ddbwritel(dev, 0, ETHER_CONTROL);
ddb_irq_exit(dev);
ddb_ports_release(dev);
ddb_buffers_free(dev);
ddb_device_destroy(dev);
ddb_unmap(dev);
pci_set_drvdata(pdev, 0);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
}
@@ -92,16 +111,146 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
#define __devinitdata
#endif
static int __devinit ddb_irq_msi(struct ddb *dev, int nr)
{
int stat;
#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, nr);
if (stat >= 1) {
dev->msi = stat;
pr_info("DDBridge: using %d MSI interrupt(s)\n",
dev->msi);
} else
pr_info("DDBridge: MSI not available.\n");
#else
stat = pci_enable_msi_block(dev->pdev, nr);
if (stat == 0) {
dev->msi = nr;
pr_info("DDBridge: using %d MSI interrupts\n", nr);
} else if (stat == 1) {
stat = pci_enable_msi(dev->pdev);
dev->msi = 1;
}
if (stat < 0)
pr_info("DDBridge: MSI not available.\n");
#endif
}
return stat;
}
static int __devinit ddb_irq_init2(struct ddb *dev)
{
int stat;
int irq_flag = IRQF_SHARED;
pr_info("init type 2 IRQ hardware block\n");
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_1);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_2);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_3);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_4);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_5);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_6);
ddbwritel(dev, 0x00000000, INTERRUPT_V2_ENABLE_7);
ddb_irq_msi(dev, 1);
if (dev->msi)
irq_flag = 0;
stat = request_irq(dev->pdev->irq, irq_handler_v2,
irq_flag, "ddbridge", (void *) dev);
if (stat < 0)
return stat;
ddbwritel(dev, 0x0000ff7f, INTERRUPT_V2_CONTROL);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_1);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_2);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_3);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_4);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_5);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_6);
ddbwritel(dev, 0xffffffff, INTERRUPT_V2_ENABLE_7);
return stat;
}
static int __devinit ddb_irq_init(struct ddb *dev)
{
int stat;
int irq_flag = IRQF_SHARED;
if (dev->link[0].info->regmap->irq_version == 2)
return ddb_irq_init2(dev);
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);
ddb_irq_msi(dev, 2);
if (dev->msi)
irq_flag = 0;
if (dev->msi == 2) {
stat = request_irq(dev->pdev->irq, irq_handler0,
irq_flag, "ddbridge", (void *) dev);
if (stat < 0)
return stat;
stat = request_irq(dev->pdev->irq + 1, irq_handler1,
irq_flag, "ddbridge", (void *) dev);
if (stat < 0) {
free_irq(dev->pdev->irq, dev);
return stat;
}
} 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)
return stat;
}
/*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);
}
return stat;
}
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;
pci_set_master(pdev);
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
return -ENODEV;
dev = vzalloc(sizeof(struct ddb));
if (dev == NULL)
return -ENOMEM;
@@ -143,74 +292,8 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid, dev->link[0].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;
ddb_reset_ios(dev);
}
ddbwritel(dev, 0, DMA_BASE_READ);
if (dev->link[0].info->type != DDB_MOD)
@@ -221,22 +304,14 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
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);
}
stat = ddb_irq_init(dev);
if (stat < 0)
goto fail0;
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);
ddb_irq_disable(dev);
fail0:
pr_err("fail0\n");
if (dev->msi)
@@ -245,7 +320,7 @@ fail:
pr_err("fail\n");
ddb_unmap(dev);
pci_set_drvdata(pdev, 0);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return -1;
}
@@ -254,37 +329,6 @@ fail:
/****************************************************************************/
/****************************************************************************/
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",
@@ -358,6 +402,8 @@ static struct ddb_info ddb_v7 = {
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 2,
.board_control_2 = 4,
.ts_quirks = TS_QUIRK_REVERSED,
};
static struct ddb_info ddb_ctv7 = {
@@ -367,6 +413,7 @@ static struct ddb_info ddb_ctv7 = {
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 3,
.board_control_2 = 4,
};
static struct ddb_info ddb_satixS2v3 = {
@@ -390,7 +437,7 @@ static struct ddb_info ddb_cis = {
.name = "Digital Devices Octopus CI single",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x01,
.i2c_mask = 0x03,
};
static struct ddb_info ddb_ci_s2_pro = {
@@ -399,7 +446,8 @@ static struct ddb_info ddb_ci_s2_pro = {
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x01,
.board_control = 3,
.board_control = 2,
.board_control_2 = 4,
};
static struct ddb_info ddb_dvbct = {
@@ -412,15 +460,6 @@ static struct ddb_info ddb_dvbct = {
/****************************************************************************/
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",
@@ -429,13 +468,48 @@ static struct ddb_info ddb_mod = {
.temp_num = 1,
};
static struct ddb_info ddb_octopus_net = {
.type = DDB_OCTONET,
.name = "Digital Devices OctopusNet network DVB adapter",
.regmap = &octopus_net_map,
static struct ddb_info ddb_mod_fsm_24 = {
.type = DDB_MOD,
.version = 2,
.name = "Digital Devices DVB-C modulator FSM-24",
.regmap = &octopus_mod_2_map,
.port_num = 24,
.temp_num = 1,
};
static struct ddb_info ddb_mod_fsm_16 = {
.type = DDB_MOD,
.version = 2,
.name = "Digital Devices DVB-C modulator FSM-16",
.regmap = &octopus_mod_2_map,
.port_num = 16,
.temp_num = 1,
};
static struct ddb_info ddb_mod_fsm_8 = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C modulator FSM-8",
.version = 2,
.regmap = &octopus_mod_2_map,
.port_num = 8,
.temp_num = 1,
};
static struct ddb_info ddb_octopro_hdin = {
.type = DDB_OCTOPRO_HDIN,
.name = "Digital Devices OctopusNet Pro HDIN",
.regmap = &octopro_hdin_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.mdio_num = 1,
};
static struct ddb_info ddb_octopro = {
.type = DDB_OCTOPRO,
.name = "Digital Devices OctopusNet Pro",
.regmap = &octopro_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.ns_num = 12,
.mdio_num = 1,
};
@@ -467,18 +541,31 @@ static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
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, 0x0008, DDVID, 0x0034, ddb_ct_8),
DDB_ID(DDVID, 0x0008, DDVID, 0x0035, ddb_ct_8),
DDB_ID(DDVID, 0x0008, DDVID, 0x0036, ddb_ct_8),
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),
DDB_ID(DDVID, 0x0210, DDVID, 0x0001, ddb_mod_fsm_24),
DDB_ID(DDVID, 0x0210, DDVID, 0x0002, ddb_mod_fsm_16),
DDB_ID(DDVID, 0x0210, DDVID, 0x0003, ddb_mod_fsm_8),
/* testing on OctopusNet Pro */
DDB_ID(DDVID, 0x0320, PCI_ANY_ID, PCI_ANY_ID, ddb_octopro_hdin),
DDB_ID(DDVID, 0x0321, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0322, PCI_ANY_ID, PCI_ANY_ID, ddb_octopro),
DDB_ID(DDVID, 0x0323, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0328, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
DDB_ID(DDVID, 0x0329, PCI_ANY_ID, PCI_ANY_ID, ddb_octopro_hdin),
/* 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, 0x0008, 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),
@@ -500,7 +587,7 @@ static __init int module_init_ddbridge(void)
pr_info("Digital Devices PCIE bridge driver "
DDBRIDGE_VERSION
", Copyright (C) 2010-15 Digital Devices GmbH\n");
", Copyright (C) 2010-16 Digital Devices GmbH\n");
if (ddb_class_create() < 0)
return -1;
ddb_wq = create_workqueue("ddbridge");

View File

@@ -41,7 +41,7 @@
#include <linux/poll.h>
#include <linux/io.h>
#include <linux/pci.h>
//#include <linux/pci_ids.h>
/*#include <linux/pci_ids.h>*/
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/swab.h>
@@ -91,10 +91,10 @@
#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_I2C 32
#define DDB_MAX_PORT 32
#define DDB_MAX_INPUT 64
#define DDB_MAX_OUTPUT 32
#define DDB_MAX_LINK 4
#define DDB_LINK_SHIFT 28
@@ -106,25 +106,30 @@ struct ddb_regset {
u32 size;
};
struct ddb_ports {
u32 base;
u32 num;
u32 size;
};
struct ddb_regmap {
struct ddb_ports *bc;
u32 irq_version;
u32 irq_base_i2c;
u32 irq_base_idma;
u32 irq_base_odma;
u32 irq_base_gtl;
u32 irq_base_rate;
struct ddb_regset *i2c;
struct ddb_regset *i2c_buf;
struct ddb_regset *dma;
struct ddb_regset *dma_buf;
struct ddb_regset *idma;
struct ddb_regset *idma_buf;
struct ddb_regset *odma;
struct ddb_regset *odma_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 *ci;
//struct ddb_regset *pid_filter;
//struct ddb_regset *ns;
struct ddb_regset *gtl;
//struct ddb_regset *mdio;
};
struct ddb_ids {
@@ -140,13 +145,17 @@ struct ddb_ids {
};
struct ddb_info {
int type;
u32 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
#define DDB_OCTOPUS_MAX_CT 6
#define DDB_OCTOPRO 7
#define DDB_OCTOPRO_HDIN 8
u32 version;
char *name;
u32 i2c_mask;
u8 port_num;
@@ -154,10 +163,15 @@ struct ddb_info {
u8 fan_num;
u8 temp_num;
u8 temp_bus;
u8 board_control;
u32 board_control;
u32 board_control_2;
u8 ns_num;
u8 mdio_num;
u8 con_clock;
u8 con_clock; /* use a continuous clock */
u8 ts_quirks;
#define TS_QUIRK_SERIAL 1
#define TS_QUIRK_REVERSED 2
#define TS_QUIRK_NO_OUTPUT 4
struct ddb_regmap *regmap;
};
@@ -166,6 +180,15 @@ struct ddb_info {
#define DMA_MAX_BUFS 32 /* hardware table limit */
#ifdef SMALL_DMA_BUFS
#define INPUT_DMA_BUFS 32
#define INPUT_DMA_SIZE (32*47*21)
#define INPUT_DMA_IRQ_DIV 1
#define OUTPUT_DMA_BUFS 32
#define OUTPUT_DMA_SIZE (32*47*21)
#define OUTPUT_DMA_IRQ_DIV 1
#else
#define INPUT_DMA_BUFS 8
#define INPUT_DMA_SIZE (128*47*21)
#define INPUT_DMA_IRQ_DIV 1
@@ -173,19 +196,22 @@ struct ddb_info {
#define OUTPUT_DMA_BUFS 8
#define OUTPUT_DMA_SIZE (128*47*21)
#define OUTPUT_DMA_IRQ_DIV 1
#endif
struct ddb;
struct ddb_port;
struct ddb_dma {
void *io;
u32 nr;
u32 regs;
u32 bufregs;
dma_addr_t pbuf[DMA_MAX_BUFS];
u8 *vbuf[DMA_MAX_BUFS];
u32 num;
u32 size;
u32 div;
u32 bufreg;
u32 bufval;
#ifdef DDB_USE_WORK
struct work_struct work;
@@ -223,7 +249,8 @@ struct ddb_dvb {
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);
int (*diseqc_send_master_cmd)(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd);
};
struct ddb_ci {
@@ -236,6 +263,7 @@ struct ddb_ci {
struct ddb_io {
struct ddb_port *port;
u32 nr;
u32 regs;
struct ddb_dma *dma;
struct ddb_io *redo;
struct ddb_io *redi;
@@ -271,6 +299,7 @@ struct ddb_port {
#define DDB_PORT_LOOP 3
#define DDB_PORT_MOD 4
char *name;
char *type_name;
u32 type;
#define DDB_TUNER_NONE 0
#define DDB_TUNER_DVBS_ST 1
@@ -286,14 +315,15 @@ struct ddb_port {
#define DDB_TUNER_MXL5XX 11
#define DDB_CI_EXTERNAL_XO2 12
#define DDB_CI_EXTERNAL_XO2_B 13
#define DDB_TUNER_DVBS_STV0910_PR 14
#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
#define DDB_TUNER_XO2 32
#define DDB_TUNER_DVBS_STV0910 (DDB_TUNER_XO2 + 0)
#define DDB_TUNER_DVBCT2_SONY (DDB_TUNER_XO2 + 1)
#define DDB_TUNER_ISDBT_SONY (DDB_TUNER_XO2 + 2)
#define DDB_TUNER_DVBC2T2_SONY (DDB_TUNER_XO2 + 3)
#define DDB_TUNER_ATSC_ST (DDB_TUNER_XO2 + 4)
#define DDB_TUNER_DVBC2T2_ST (DDB_TUNER_XO2 + 5)
struct ddb_input *input[2];
struct ddb_output *output;
@@ -308,10 +338,21 @@ struct mod_base {
u32 frequency;
u32 flat_start;
u32 flat_end;
spinlock_t temp_lock;
int OverTemperatureError;
u8 temp_tab[11];
};
struct mod_state {
struct ddb_mod {
struct ddb_port *port;
u32 nr;
u32 regs;
u32 frequency;
u32 modulation;
u32 symbolrate;
u64 obitrate;
u64 ibitrate;
u32 pcr_correction;
@@ -405,10 +446,11 @@ struct ddb {
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];
struct ddb_dma idma[DDB_MAX_INPUT];
struct ddb_dma odma[DDB_MAX_OUTPUT];
void (*handler[128])(unsigned long);
unsigned long handler_data[128];
void (*handler[4][256])(unsigned long);
unsigned long handler_data[4][256];
struct device *ddb_dev;
u32 ddb_dev_users;
@@ -428,7 +470,7 @@ struct ddb {
u8 tsbuf[TS_CAPTURE_LEN];
struct mod_base mod_base;
struct mod_state mod[10];
struct ddb_mod mod[24];
};
static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
@@ -455,28 +497,30 @@ static inline u32 ddbreadl0(struct ddb_link *link, u32 adr)
static inline void gtlw(struct ddb_link *link)
{
u32 count = 0;
static u32 max = 0;
static u32 max;
while (1 & ddbreadl0(link, link->regs + 0x10)) {
if (++count == 1024) {
printk("LTO\n");
pr_info("LTO\n");
break;
}
}
if (count > max) {
max = count;
printk("TO=%u\n", max);
pr_info("TO=%u\n", max);
}
if (ddbreadl0(link, link->regs + 0x10) & 0x8000)
printk("link error\n");
pr_err("link error\n");
}
#else
static inline void gtlw(struct ddb_link *link)
{
while (1 & ddbreadl0(link, link->regs + 0x10));
while (1 & ddbreadl0(link, link->regs + 0x10))
;
}
#endif
#if 0
static u32 ddblreadl(struct ddb_link *link, u32 adr)
{
if (unlikely(link->nr)) {
@@ -510,6 +554,7 @@ static void ddblwritel(struct ddb_link *link, u32 val, u32 adr)
}
writel(val, (char *) (link->dev->regs + (adr)));
}
#endif
static u32 ddbreadl(struct ddb *dev, u32 adr)
{
@@ -705,6 +750,6 @@ 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.20"
#define DDBRIDGE_VERSION "0.9.24"
#endif

View File

@@ -1,7 +1,7 @@
/*
* octonet.c: Digital Devices network tuner driver
*
* Copyright (C) 2012-15 Digital Devices GmbH
* Copyright (C) 2012-16 Digital Devices GmbH
* Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
*
@@ -25,7 +25,11 @@
#include "ddbridge.h"
#include "ddbridge-regs.h"
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
#include <asm-generic/pci-dma-compat.h>
#else
#include <linux/pci-dma-compat.h>
#endif
static int adapter_alloc = 3;
module_param(adapter_alloc, int, 0444);
@@ -34,21 +38,13 @@ MODULE_PARM_DESC(adapter_alloc,
#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 = {
.irq_version = 1,
.irq_base_i2c = 0,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.input = &octopus_input,
.output = &octopus_output,
};
static struct ddb_regset octopus_gtl = {
@@ -58,8 +54,13 @@ static struct ddb_regset octopus_gtl = {
};
static struct ddb_regmap octopus_net_gtl = {
.irq_version = 1,
.irq_base_i2c = 0,
.irq_base_gtl = 10,
.i2c = &octopus_i2c,
.i2c_buf = &octopus_i2c_buf,
.input = &octopus_input,
.output = &octopus_output,
.gtl = &octopus_gtl,
};
@@ -113,16 +114,17 @@ static int __exit octonet_remove(struct platform_device *pdev)
dev = platform_get_drvdata(pdev);
ddb_device_destroy(dev);
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);
free_irq(platform_get_irq(dev->pfdev, 0), dev);
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;
@@ -133,7 +135,6 @@ 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)
@@ -176,15 +177,15 @@ static int __init octonet_probe(struct platform_device *pdev)
else
dev->link[0].info = &ddb_octonet_tbd;
pr_info("HW %08x REGMAP %08x\n", dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
pr_info("MAC %08x DEVID %08x\n", dev->link[0].ids.mac, dev->link[0].ids.devid);
pr_info("HW %08x REGMAP %08x\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
pr_info("MAC %08x DEVID %08x\n",
dev->link[0].ids.mac, dev->link[0].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);
ddb_reset_ios(dev);
irq = platform_get_irq(dev->pfdev, 0);
if (irq < 0)
@@ -233,7 +234,7 @@ static __init int init_octonet(void)
int res;
pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION
", Copyright (C) 2010-15 Digital Devices GmbH\n");
", Copyright (C) 2010-16 Digital Devices GmbH\n");
res = ddb_class_create();
if (res)
return res;

22
docs/ci
View File

@@ -1,3 +1,5 @@
- General Information
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.
@@ -26,6 +28,24 @@ use the new interface.
See docs/redirect for more info.
- Clock Speed
The normal clock speed for the TS output is 72 MHz wich is the standard
speed used for CI.
Packets are sent with an adjustable gap between the packets.
The gap size is (gap value * 2) + 4 or 0 if the gap is disabled.
So, the standard gap value of 4 leads to a gap of 12 bytes which means
that the effective data rate is (72*188)/200 = 67.68 MBits/s.
Depending on the hardware, the clock speed can be changed with the
ci_bitrate module parameter:
- Octopus CI, Octopus CI S2 Pro : supported
- old CI single flex modules: supported
- new dual CI flex module: not yet supported, use the standard 72000 kHz
Valid ranges for are from ... to 96000 KHz.

View File

@@ -955,6 +955,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
}
c->stream_id = NO_STREAM_ID_FILTER;
c->pls = NO_SCRAMBLING_CODE;
switch (c->delivery_system) {
case SYS_DVBS:
@@ -1031,6 +1032,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
_DTV_CMD(DTV_LNA, 1, 0),
_DTV_CMD(DTV_INPUT, 1, 0),
_DTV_CMD(DTV_PLS, 1, 0),
/* Get */
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
@@ -1462,6 +1464,10 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
tvp->u.buffer.len = 4;
break;
case DTV_PLS:
tvp->u.data = c->pls;
break;
/* Fill quality measures */
case DTV_STAT_SIGNAL_STRENGTH:
tvp->u.st = c->strength;
@@ -1901,6 +1907,10 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
r = fe->ops.set_input(fe, c->input);
break;
case DTV_PLS:
c->pls = tvp->u.data;
break;
default:
return -EINVAL;
}

View File

@@ -397,6 +397,7 @@ struct dtv_frontend_properties {
u32 lna;
s32 input;
u32 pls;
/* statistics data */
struct dtv_fe_stats strength;

View File

@@ -35,8 +35,11 @@
#include <asm/div64.h>
#include "dvb_frontend.h"
#include "dvb_math.h"
#include "cxd2843.h"
#define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1))
#define USE_ALGO 1
enum demod_type { CXD2843, CXD2837, CXD2838 };
@@ -329,7 +332,7 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c)
static int read_tps(struct cxd_state *state, u8 *tps)
{
if (state->last_status != 0x1f)
return 0;
return -1;
freeze_regst(state);
readregst_unlocked(state, 0x10, 0x2f, tps, 7);
@@ -337,6 +340,63 @@ static int read_tps(struct cxd_state *state, u8 *tps)
return 0;
}
/* Read DVBT2 OFDM Info */
/* OFDMInfo[0] [5] OFDM_MIXED */
/* OFDMInfo[0] [4] OFDM_MISO */
/* OFDMInfo[0] [2:0] OFDM_FFTSIZE[2:0] */
/* OFDMInfo[1] [6:4] OFDM_GI[2:0] */
/* OFDMInfo[1] [2:0] OFDM_PP[2:0] */
/* OFDMInfo[2] [4] OFDM_BWT_EXT */
/* OFDMInfo[2] [3:0] OFDM_PAPR[3:0] */
/* OFDMInfo[3] [3:0] OFDM_NDSYM[11:8] */
/* OFDMInfo[4] [7:0] OFDM_NDSYM[7:0] */
static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
{
if (state->last_status != 0x1f)
return -1;
freeze_regst(state);
readregst_unlocked(state, 0x20, 0x5c, ofdm, 5);
unfreeze_regst(state);
return 0;
}
/* Read DVBT2 QAM,
Data PLP
0 [7:0] L1POST_PLP_ID[7:0]
1 [2:0] L1POST_PLP_TYPE[2:0]
2 [4:0] L1POST_PLP_PAYLOAD_TYPE[4:0]
3 [0] L1POST_FF_FLAG
4 [2:0] L1POST_FIRST_RF_IDX[2:0]
5 [7:0] L1POST_FIRST_FRAME_IDX[7:0]
6 [7:0] L1POST_PLP_GROUP_ID[7:0]
7 [2:0] L1POST_PLP_COD[2:0]
8 [2:0] L1POST_PLP_MOD[2:0]
9 [0] L1POST_PLP_ROTATION
10 [1:0] L1POST_PLP_FEC_TYPE[1:0]
11 [1:0] L1POST_PLP_NUM_BLOCKS_MAX[9:8]
12 [7:0] L1POST_PLP_NUM_BLOCKS_MAX[7:0]
13 [7:0] L1POST_FRAME_INTERVAL[7:0]
14 [7:0] L1POST_TIME_IL_LENGTH[7:0]
15 [0] L1POST_TIME_IL_TYPE
16 [0] L1POST_IN_BAND_FLAG
17 [7:0] L1POST_RESERVED_1[15:8]
18 [7:0] L1POST_RESERVED_1[7:0]
19-37 same for common PLP
*/
static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp)
{
if (state->last_status != 0x1f)
return -1;
freeze_regst(state);
readregst_unlocked(state, 0x22, 0x54 + off, tlp, count);
unfreeze_regst(state);
return 0;
}
static void Active_to_Sleep(struct cxd_state *state)
{
if (state->state <= Sleep)
@@ -1008,6 +1068,15 @@ static void release(struct dvb_frontend *fe)
kfree(state);
}
static int sleep(struct dvb_frontend *fe)
{
struct cxd_state *state = fe->demodulator_priv;
Stop(state);
ShutDown(state);
return 0;
}
static int Start(struct cxd_state *state, u32 IntermediateFrequency)
{
enum demod_state newDemodState = Unknown;
@@ -1165,7 +1234,7 @@ static int set_parameters(struct dvb_frontend *fe)
fe->ops.tuner_ops.set_params(fe);
state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000;
if (fe->dtv_property_cache.stream_id == 0xffffffff) {
if (fe->dtv_property_cache.stream_id == NO_STREAM_ID_FILTER) {
state->DataSliceID = 0xffffffff;
state->plp = 0xffffffff;
} else {
@@ -1260,11 +1329,40 @@ static int get_tune_settings(struct dvb_frontend *fe,
}
}
static int read_snr(struct dvb_frontend *fe, u16 *snr);
static int get_stats(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u16 val;
s64 str;
if (fe->ops.tuner_ops.get_rf_strength)
fe->ops.tuner_ops.get_rf_strength(fe, &val);
else
val = 0;
str = 1000 * (s64) (s16) val;
str -= 108750;
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = str;
read_snr(fe, &val);
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 100 * (s64) (s16) val;
return 0;
}
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct cxd_state *state = fe->demodulator_priv;
u8 rdata;
get_stats(fe);
*status = 0;
switch (state->state) {
case ActiveC:
@@ -1277,6 +1375,12 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
if (rdata & 0x20)
*status |= 0x1f;
}
if (*status == 0x1f && state->FirstTimeLock) {
readregst(state, 0x40, 0x19, &rdata, 1);
rdata &= 0x07;
state->BERScaleMax = ( rdata < 2 ) ? 18 : 19;
state->FirstTimeLock = 0;
}
break;
case ActiveT:
readregst(state, 0x10, 0x10, &rdata, 1);
@@ -1287,6 +1391,16 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
if (rdata & 0x20)
*status |= 0x1f;
}
if (*status == 0x1f && state->FirstTimeLock) {
u8 tps[7];
read_tps(state, tps);
state->BERScaleMax =
(((tps[0] >> 6) & 0x03) < 2 ) ? 17 : 18;
if ((tps[0] & 7) < 2)
state->BERScaleMax--;
state->FirstTimeLock = 0;
}
break;
case ActiveT2:
readregst(state, 0x20, 0x10, &rdata, 1);
@@ -1333,6 +1447,12 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
if (rdata & 0x01)
*status |= 0x18;
}
if (*status == 0x1f && state->FirstTimeLock) {
/* readregst(state, 0x40, 0x19, &rdata, 1); */
/* rdata &= 0x07; */
/* state->BERScaleMax = ( rdata < 2 ) ? 18 : 19; */
state->FirstTimeLock = 0;
}
break;
default:
break;
@@ -1371,8 +1491,44 @@ static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d)
static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d)
{
u8 BERRegs[4];
u8 Scale;
u8 FECType;
u8 CodeRate;
static const u32 nBCHBitsLookup[2][8] = {
/* R1_2 R3_5 R2_3 R3_4 R4_5 R5_6 R1_3 R2_5 */
{7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480}, /* 16K FEC */
{32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920} /* 64k FEC */
};
*n = 0;
*d = 1;
freeze_regst(state);
readregst(state, 0x24, 0x40, BERRegs, 4);
readregst(state, 0x22, 0x5e, &FECType, 1);
readregst(state, 0x22, 0x5b, &CodeRate, 1);
FECType &= 0x03;
CodeRate &= 0x07;
unfreeze_regst(state);
if (FECType > 1)
return 0;
readregst(state, 0x20, 0x72, &Scale, 1);
Scale &= 0x0F;
if (BERRegs[0] & 0x01) {
state->LastBERNominator = (((u32) BERRegs[1] & 0x3F) << 16) |
(((u32) BERRegs[2]) << 8) | BERRegs[3];
state->LastBERDenominator = nBCHBitsLookup[FECType][CodeRate] << Scale;
if (state->LastBERNominator < 256 &&
Scale < state->BERScaleMax) {
writebitst(state, 0x20, 0x72, Scale + 1, 0x0F);
} else if (state->LastBERNominator > 512 && Scale > 8)
writebitst(state, 0x20, 0x72, Scale - 1, 0x0F);
}
*n = state->LastBERNominator;
*d = state->LastBERDenominator;
return 0;
}
@@ -1421,7 +1577,8 @@ static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d)
static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct cxd_state *state = fe->demodulator_priv;
u32 n, d;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 n = 0, d = 1;
int s = 0;
*ber = 0;
@@ -1447,6 +1604,14 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
if (s)
return s;
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = n;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = d;
if (d)
*ber = (n * 1000) / d;
return 0;
}
@@ -1459,57 +1624,63 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
return 0;
}
static s32 Log10x100(u32 x)
{
static u32 LookupTable[100] = {
101157945, 103514217, 105925373, 108392691, 110917482,
113501082, 116144861, 118850223, 121618600, 124451461,
127350308, 130316678, 133352143, 136458314, 139636836,
142889396, 146217717, 149623566, 153108746, 156675107,
160324539, 164058977, 167880402, 171790839, 175792361,
179887092, 184077200, 188364909, 192752491, 197242274,
201836636, 206538016, 211348904, 216271852, 221309471,
226464431, 231739465, 237137371, 242661010, 248313311,
254097271, 260015956, 266072506, 272270131, 278612117,
285101827, 291742701, 298538262, 305492111, 312607937,
319889511, 327340695, 334965439, 342767787, 350751874,
358921935, 367282300, 375837404, 384591782, 393550075,
402717034, 412097519, 421696503, 431519077, 441570447,
451855944, 462381021, 473151259, 484172368, 495450191,
506990708, 518800039, 530884444, 543250331, 555904257,
568852931, 582103218, 595662144, 609536897, 623734835,
638263486, 653130553, 668343918, 683911647, 699841996,
716143410, 732824533, 749894209, 767361489, 785235635,
803526122, 822242650, 841395142, 860993752, 881048873,
901571138, 922571427, 944060876, 966050879, 988553095,
};
s32 y;
int i;
if (x == 0)
return 0;
y = 800;
if (x >= 1000000000) {
x /= 10;
y += 100;
}
while (x < 100000000) {
x *= 10;
y -= 100;
}
i = 0;
while (i < 100 && x > LookupTable[i])
i += 1;
y += i;
return y;
}
#if 0
+NTSTATUS CCXD2843ER::GetT2PLPIds(DD_T2_PLPIDS* pT2_PLPIDS)
{
NTSTATUS status = STATUS_SUCCESS;
- *pReturned = 0;
+
if( m_DemodState != ActiveT2 ) return STATUS_NOT_IMPLEMENTED;
- if( m_LastLockStatus < TSLock || m_LastLockStatus == Unlock ) return status;
+ if( m_LastLockStatus < TSLock ) return status;
do
{
+ BYTE tmp;
+
CHK_ERROR(FreezeRegsT());
+ CHK_ERROR(ReadRegT(0x20,0x5C,&tmp)); // OFDM Info
+
+ if( tmp & 0x20 ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_FEF;
+ if( m_T2Profile == T2P_Lite ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_LITE;
+
+ CHK_ERROR(ReadRegT(0x22,0x54,&tmp));
+ pT2_PLPIDS->PLPID = tmp;
+
+ CHK_ERROR(ReadRegT(0x22,0x54 + 19 + 13,&tmp)); // Interval
+ if( tmp > 0 )
+ {
+ CHK_ERROR(ReadRegT(0x22,0x54 + 19,&tmp));
+ pT2_PLPIDS->CommonPLPID = tmp;
+ }
+
BYTE nPids = 0;
CHK_ERROR(ReadRegT(0x22,0x7F,&nPids));
- pValues[0] = nPids;
- if( nPids >= nValues ) nPids = BYTE(nValues-1);
+ pT2_PLPIDS->NumPLPS = nPids;
+ CHK_ERROR(ReadRegT(0x22,0x80,&pT2_PLPIDS->PLPList[0], nPids > 128 ? 128 : nPids));
- CHK_ERROR(ReadRegT(0x22,0x80,&pValues[1], nPids > 128 ? 128 : nPids));
-
if( nPids > 128 )
{
- CHK_ERROR(ReadRegT(0x23,0x10,&pValues[129], nPids - 128));
+ CHK_ERROR(ReadRegT(0x23,0x10,&pT2_PLPIDS->PLPList[128], nPids - 128));
}
- *pReturned = nPids + 1;
+
}
while(0);
UnFreezeRegsT();
static void GetPLPIds(struct cxd_state *state, u32 nValues,
u8 *Values, u32 *Returned)
{
u8 nPids = 0;
u8 nPids = 0, tmp;
*Returned = 0;
if (state->state != ActiveT2)
@@ -1645,6 +1816,7 @@ static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise)
static int read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct cxd_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 SNR = 0;
*snr = 0;
@@ -1671,6 +1843,9 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr)
break;
}
*snr = SNR;
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 10 * (s64) SNR;
return 0;
}
@@ -1731,6 +1906,110 @@ static int get_algo(struct dvb_frontend *fe)
return DVBFE_ALGO_HW;
}
static int get_fe_t2(struct cxd_state *state)
{
struct dvb_frontend *fe = &state->frontend;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 ofdm[5], modcod[2];
freeze_regst(state);
readregst_unlocked(state, 0x20, 0x5c, ofdm, 5);
readregst_unlocked(state, 0x22, 0x5b, modcod, 2);
unfreeze_regst(state);
switch (modcod[0] & 0x07) {
case 0:
p->fec_inner = FEC_1_2;
break;
case 1:
p->fec_inner = FEC_3_5;
break;
case 2:
p->fec_inner = FEC_2_3;
break;
case 3:
p->fec_inner = FEC_3_4;
break;
case 4:
p->fec_inner = FEC_4_5;
break;
case 5:
p->fec_inner = FEC_5_6;
break;
case 6:
p->fec_inner = FEC_1_3;
break;
case 7:
p->fec_inner = FEC_2_5;
break;
}
switch (modcod[1] & 0x07) {
case 0:
p->modulation = QPSK;
break;
case 1:
p->modulation = QAM_16;
break;
case 2:
p->modulation = QAM_64;
break;
case 3:
p->modulation = QAM_256;
break;
}
switch (ofdm[0] & 0x07) {
case 0:
p->transmission_mode = TRANSMISSION_MODE_2K;
break;
case 1:
p->transmission_mode = TRANSMISSION_MODE_8K;
break;
case 2:
p->transmission_mode = TRANSMISSION_MODE_4K;
break;
case 3:
p->transmission_mode = TRANSMISSION_MODE_1K;
break;
case 4:
p->transmission_mode = TRANSMISSION_MODE_16K;
break;
case 5:
p->transmission_mode = TRANSMISSION_MODE_32K;
break;
case 6:
p->transmission_mode = TRANSMISSION_MODE_64K;
break;
}
switch ((ofdm[1] >> 4) & 0x07) {
case 0:
p->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
p->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
p->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
p->guard_interval = GUARD_INTERVAL_1_4;
break;
case 4:
p->guard_interval = GUARD_INTERVAL_1_128;
break;
case 5:
p->guard_interval = GUARD_INTERVAL_19_128;
break;
case 6:
p->guard_interval = GUARD_INTERVAL_19_256;
break;
}
return 0;
}
static int get_fe_t(struct cxd_state *state)
{
struct dvb_frontend *fe = &state->frontend;
@@ -1842,7 +2121,7 @@ static int get_fe_c(struct cxd_state *state)
freeze_regst(state);
readregst_unlocked(state, 0x40, 0x19, &qam, 1);
unfreeze_regst(state);
p->modulation = qam & 0x07;
p->modulation = 1 + (qam & 0x07);
return 0;
}
@@ -1858,6 +2137,7 @@ static int get_frontend(struct dvb_frontend *fe)
get_fe_t(state);
break;
case ActiveT2:
get_fe_t2(state);
break;
case ActiveC:
get_fe_c(state);
@@ -1889,9 +2169,10 @@ static struct dvb_frontend_ops common_ops_2843 = {
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.sleep = sleep,
.i2c_gate_ctrl = gate_ctrl,
.set_frontend = set_parameters,
@@ -1926,9 +2207,10 @@ static struct dvb_frontend_ops common_ops_2837 = {
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.sleep = sleep,
.i2c_gate_ctrl = gate_ctrl,
.set_frontend = set_parameters,
@@ -1955,15 +2237,16 @@ static struct dvb_frontend_ops common_ops_2838 = {
.frequency_max = 865000000,
.symbol_rate_min = 870000,
.symbol_rate_max = 11700000,
.caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.sleep = sleep,
.i2c_gate_ctrl = gate_ctrl,
.set_frontend = set_parameters,

View File

@@ -4866,10 +4866,6 @@ static int drxk_set_parameters (struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
#endif
{
#ifndef USE_API3
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 delsys = p->delivery_system, old_delsys;
#endif
struct drxk_state *state = fe->demodulator_priv;
u32 IF;
@@ -4896,7 +4892,7 @@ static int drxk_set_parameters (struct dvb_frontend *fe,
return 0;
}
static int drxk_c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
static int drxk_c_get_frontend(struct dvb_frontend *fe)
{
//struct drxk_state *state = fe->demodulator_priv;
//printk("%s\n", __FUNCTION__);
@@ -4990,7 +4986,7 @@ static int drxk_t_sleep(struct dvb_frontend* fe)
return 0;
}
static int drxk_t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
static int drxk_t_get_frontend(struct dvb_frontend *fe)
{
//struct drxk_state *state = fe->demodulator_priv;
//printk("%s\n", __FUNCTION__);

View File

@@ -193,7 +193,8 @@ static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val)
if (stat)
pr_err("i2c read error 1\n");
if (!stat)
stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES);
stat = i2cread(state, (u8 *) val,
MXL_HYDRA_REG_SIZE_IN_BYTES);
le32_to_cpus(val);
if (stat)
pr_err("i2c read error 2\n");
@@ -218,10 +219,12 @@ static int send_command(struct mxl *state, u32 size, u8 *buf)
mutex_unlock(&state->base->i2c_lock);
usleep_range(1000, 2000);
mutex_lock(&state->base->i2c_lock);
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val);
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR,
&val);
}
if (!count) {
pr_info("mxl5xx: send_command busy\n");
mutex_unlock(&state->base->i2c_lock);
return -EBUSY;
}
}
@@ -246,7 +249,8 @@ static int write_register(struct mxl *state, u32 reg, u32 val)
return stat;
}
static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data)
static int write_register_block(struct mxl *state, u32 reg,
u32 size, u8 *data)
{
int stat;
u8 *buf = state->base->buf;
@@ -307,7 +311,8 @@ static int read_register(struct mxl *state, u32 reg, u32 *val)
if (stat)
pr_err("i2c read error 1\n");
if (!stat)
stat = i2cread(state, (u8 *) val, MXL_HYDRA_REG_SIZE_IN_BYTES);
stat = i2cread(state, (u8 *) val,
MXL_HYDRA_REG_SIZE_IN_BYTES);
mutex_unlock(&state->base->i2c_lock);
le32_to_cpus(val);
if (stat)
@@ -442,8 +447,23 @@ static int CfgDemodAbortTune(struct mxl *state)
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
abortTuneCmd.demodId = state->demod;
BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, cmdSize, &abortTuneCmd, cmdBuff);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE,
cmdSize, &abortTuneCmd, cmdBuff);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
}
static int reset_fec_counter(struct mxl *state)
{
MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd;
u32 demodIndex = (u32) state->demod;
u8 cmdSize = sizeof(u32);
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD,
MXL_CMD_WRITE, cmdSize, &demodIndex, cmdBuff);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
}
static int send_master_cmd(struct dvb_frontend *fe,
@@ -504,18 +524,22 @@ static int set_parameters(struct dvb_frontend *fe)
demodChanCfg.fecCodeRate = MXL_HYDRA_FEC_AUTO;
mutex_lock(&state->base->tune_lock);
if (time_after(jiffies + msecs_to_jiffies(200), state->base->next_tune))
if (time_after(jiffies + msecs_to_jiffies(200),
state->base->next_tune))
while (time_before(jiffies, state->base->next_tune))
msleep(10);
state->base->next_tune = jiffies + msecs_to_jiffies(100);
state->tuner_in_use = state->tuner;
BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE,
cmdSize, &demodChanCfg, cmdBuff);
stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
stat = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
mutex_unlock(&state->base->tune_lock);
return stat;
}
static int get_stats(struct dvb_frontend *fe);
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct mxl *state = fe->demodulator_priv;
@@ -532,7 +556,7 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
mutex_unlock(&state->base->status_lock);
*status = (regData == 1) ? 0x1f : 0;
get_stats(fe);
return stat;
}
@@ -559,6 +583,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
if (r)
return r;
#if 0
if (*status & FE_HAS_LOCK)
return 0;
@@ -567,6 +592,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
else
p->delivery_system = SYS_DVBS;
set_parameters(fe);
#endif
return 0;
}
@@ -597,6 +623,7 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr)
struct mxl *state = fe->demodulator_priv;
int stat;
u32 regData = 0;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
@@ -605,20 +632,69 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr)
&regData);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
*snr = (s16) (regData & 0xFFFF);
*snr = (s16) (regData & 0xFFFF); /* 100x dB */
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 10 * (s64) *snr;
return stat;
}
static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
*ber = 0;
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg[8], reg2[4], n = 0, d = 0;
int stat;
*ber = 0;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
stat = read_register_block(state,
(HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(7 * sizeof(u32)),
(u8 *) &reg[0]);
stat = read_register_block(
state,
(HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(4 * sizeof(u32)),
(u8 *) &reg2[0]);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
switch (p->delivery_system) {
case SYS_DSS:
break;
case SYS_DVBS:
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = reg[5];
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = reg[6] * 188 * 8;
break;
case SYS_DVBS2:
break;
default:
break;
}
pr_debug("mxl5xx: ber %08x %08x %08x %08x %08x %08x %08x\n",
reg[0], reg[1], reg[2], reg[3], reg[4], reg[5], reg[6]);
pr_debug("mxl5xx: ber2 %08x %08x %08x %08x\n",
reg[0], reg[1], reg[2], reg[3]);
//pre_bit_error, pre_bit_count
//post_bit_error, post_bit_count;
//block_error block_count;
//reset_fec_counter(state);
return 0;
}
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int stat;
u32 regData = 0;
@@ -629,7 +705,10 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
&regData);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
*strength = (u16) (regData & 0xFFFF);
*strength = (u16) (regData & 0xFFFF); /* 10x dBm */
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = 10 * (s64) (s16) (regData & 0xFFFF);
return stat;
}
@@ -638,17 +717,105 @@ static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
static int get_stats(struct dvb_frontend *fe)
{
u16 val;
u32 val32;
read_signal_strength(fe, &val);
read_snr(fe, &val);
read_ber(fe, &val32);
return 0;
}
static fe_code_rate_t conv_fec(MXL_HYDRA_FEC_E fec)
{
enum fe_code_rate fec2fec[11] = {
FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7,
FEC_7_8, FEC_8_9, FEC_9_10
};
if (fec > MXL_HYDRA_FEC_9_10)
return FEC_NONE;
return fec2fec[fec];
}
static int get_frontend(struct dvb_frontend *fe)
{
//struct mxl *state = fe->demodulator_priv;
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE];
u32 freq;
int stat;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
stat = read_register_block(state,
(HYDRA_DMD_STANDARD_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), // 25 * 4 bytes
(u8 *) &regData[0]);
// read demod channel parameters
stat = read_register_block(state,
(HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(4), // 4 bytes
(u8 *) &freq);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
pr_debug("mxl5xx: freq=%u delsys=%u srate=%u\n",
freq * 1000, regData[DMD_STANDARD_ADDR],
regData[DMD_SYMBOL_RATE_ADDR]);
p->symbol_rate = regData[DMD_SYMBOL_RATE_ADDR];
p->frequency = freq;
//p->delivery_system = (MXL_HYDRA_BCAST_STD_E )regData[DMD_STANDARD_ADDR];
//p->inversion = (MXL_HYDRA_SPECTRUM_E )regData[DMD_SPECTRUM_INVERSION_ADDR];
//freqSearchRangeKHz = (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]);
p->fec_inner = conv_fec(regData[DMD_FEC_CODE_RATE_ADDR]);
switch (p->delivery_system) {
case SYS_DSS:
break;
case SYS_DVBS:
break;
case SYS_DVBS2:
switch ((MXL_HYDRA_PILOTS_E )
regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) {
case MXL_HYDRA_PILOTS_OFF:
p->pilot = PILOT_OFF;
break;
case MXL_HYDRA_PILOTS_ON:
p->pilot = PILOT_ON;
break;
default:
break;
}
case SYS_DVBS:
switch ((MXL_HYDRA_MODULATION_E)
regData[DMD_MODULATION_SCHEME_ADDR]) {
case MXL_HYDRA_MOD_QPSK:
p->modulation = QPSK;
break;
case MXL_HYDRA_MOD_8PSK:
p->modulation = PSK_8;
break;
default:
break;
}
switch ((MXL_HYDRA_ROLLOFF_E)
regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) {
case MXL_HYDRA_ROLLOFF_0_20:
p->rolloff = ROLLOFF_20;
break;
case MXL_HYDRA_ROLLOFF_0_35:
p->rolloff = ROLLOFF_35;
break;
case MXL_HYDRA_ROLLOFF_0_25:
p->rolloff = ROLLOFF_25;
break;
default:
break;
}
break;
default:
return -EINVAL;
@@ -749,12 +916,14 @@ static int write_fw_segment(struct mxl *state,
u32 origSize = 0;
u8 *wBufPtr = NULL;
u32 blockSize = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
(MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4;
(MXL_HYDRA_I2C_HDR_SIZE +
MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4;
u8 wMsgBuffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
(MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)];
do {
size = origSize = (((u32)(dataCount + blockSize)) > totalSize) ?
size = origSize =
(((u32)(dataCount + blockSize)) > totalSize) ?
(totalSize - dataCount) : blockSize;
if (origSize & 3)
@@ -775,8 +944,8 @@ static int write_fw_segment(struct mxl *state,
return status;
}
static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr, u32 mbinBufferSize)
static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr,
u32 mbinBufferSize)
{
int status;
u32 index = 0;
@@ -801,26 +970,31 @@ static int do_firmware_download(struct mxl *state, u8 *mbinBufferPtr, u32 mbinBu
__func__, segmentPtr->header.id);
return -EINVAL;
}
segLength = get_big_endian(24, &(segmentPtr->header.len24[0]));
segAddress = get_big_endian(32, &(segmentPtr->header.address[0]));
segLength = get_big_endian(24,
&(segmentPtr->header.len24[0]));
segAddress = get_big_endian(32,
&(segmentPtr->header.address[0]));
if (state->base->type == MXL_HYDRA_DEVICE_568) {
if ((((segAddress & 0x90760000) == 0x90760000) ||
((segAddress & 0x90740000) == 0x90740000)) &&
(xcpuFwFlag == MXL_FALSE)) {
SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N, 1);
SET_REG_FIELD_DATA(PRCM_PRCM_CPU_SOFT_RST_N,
1);
msleep(200);
write_register(state, 0x90720000, 0);
msleep(10);
xcpuFwFlag = MXL_TRUE;
}
status = write_fw_segment(state, segAddress,
segLength, (u8 *) segmentPtr->data);
segLength,
(u8 *) segmentPtr->data);
} else {
if (((segAddress & 0x90760000) != 0x90760000) &&
((segAddress & 0x90740000) != 0x90740000))
status = write_fw_segment(state, segAddress,
segLength, (u8 *) segmentPtr->data);
segLength,
(u8 *) segmentPtr->data);
}
if (status)
return status;
@@ -883,14 +1057,17 @@ static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len)
if (status)
return status;
/* Disable clock to Baseband, Wideband, SerDes, Alias ext & Transport modules */
status = write_register(state, HYDRA_MODULES_CLK_2_REG, HYDRA_DISABLE_CLK_2);
/* Disable clock to Baseband, Wideband, SerDes,
Alias ext & Transport modules */
status = write_register(state, HYDRA_MODULES_CLK_2_REG,
HYDRA_DISABLE_CLK_2);
if (status)
return status;
/* Clear Software & Host interrupt status - (Clear on read) */
status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, &regData);
if (status)
return status;
status = do_firmware_download(state, mbin, mbin_len);
if (status)
return status;
@@ -927,13 +1104,15 @@ static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len)
pr_info("mxl5xx: Hydra FW alive. Hail!\n");
/* sometimes register values are wrong shortly after first heart beats */
/* sometimes register values are wrong shortly
after first heart beats */
msleep(50);
devSkuCfg.skuType = state->base->sku_type;
BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE,
cmdSize, &devSkuCfg, cmdBuff);
status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
status = send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
return status;
}
@@ -963,19 +1142,32 @@ static int cfg_ts_pad_mux(struct mxl *state, MXL_BOOL_E enableSerialTS)
case MXL_HYDRA_DEVICE_541S:
case MXL_HYDRA_DEVICE_561S:
case MXL_HYDRA_DEVICE_581S:
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL, padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_14_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_15_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_16_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_17_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_18_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_19_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_20_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_21_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_22_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_23_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_24_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_25_PINMUX_SEL,
padMuxValue);
status |= SET_REG_FIELD_DATA(PAD_MUX_DIGIO_26_PINMUX_SEL,
padMuxValue);
break;
case MXL_HYDRA_DEVICE_544:
@@ -1159,7 +1351,7 @@ static int enable_tuner(struct mxl *state, u32 tuner, u32 enable)
if (!count)
return -1;
read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val);
pr_info("mxl5xx: tuner %u ready = %u\n", tuner , (val >> tuner) & 1);
/*pr_info("mxl5xx: tuner %u ready = %u\n", tuner , (val >> tuner) & 1);*/
#endif
return 0;
@@ -1194,8 +1386,10 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
{XPT_TS_CLK_PHASE4}, {XPT_TS_CLK_PHASE5},
{XPT_TS_CLK_PHASE6}, {XPT_TS_CLK_PHASE7} };
MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = {
{XPT_LSB_FIRST0}, {XPT_LSB_FIRST1}, {XPT_LSB_FIRST2}, {XPT_LSB_FIRST3},
{XPT_LSB_FIRST4}, {XPT_LSB_FIRST5}, {XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} };
{XPT_LSB_FIRST0}, {XPT_LSB_FIRST1},
{XPT_LSB_FIRST2}, {XPT_LSB_FIRST3},
{XPT_LSB_FIRST4}, {XPT_LSB_FIRST5},
{XPT_LSB_FIRST6}, {XPT_LSB_FIRST7} };
MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = {
{XPT_SYNC_FULL_BYTE0}, {XPT_SYNC_FULL_BYTE1},
{XPT_SYNC_FULL_BYTE2}, {XPT_SYNC_FULL_BYTE3},
@@ -1230,16 +1424,17 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = {
{PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL},
{PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL},
{PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL} };
{PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL}};
MXL_REG_FIELD_T mxl561_xpt_ts_valid[MXL_HYDRA_DEMOD_ID_6] = {
{PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL},
{PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL},
{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL} };
{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}};
demodId = state->base->ts_map[demodId];
if (MXL_ENABLE == mpegOutParamPtr->enable) {
if (mpegOutParamPtr->mpegMode == MXL_HYDRA_MPEG_MODE_PARALLEL) {
if (mpegOutParamPtr->mpegMode ==
MXL_HYDRA_MPEG_MODE_PARALLEL) {
#if 0
for (i = MXL_HYDRA_DEMOD_ID_0; i < MXL_HYDRA_DEMOD_MAX; i++) {
mxlStatus |= MxLWare_Hydra_UpdateByMnemonic(devId,
@@ -1373,7 +1568,8 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
}
if (mpegOutParamPtr->mpegMode != MXL_HYDRA_MPEG_MODE_PARALLEL) {
status |= update_by_mnemonic(state,
status |=
update_by_mnemonic(state,
xpt_enable_output[demodId].regAddr,
xpt_enable_output[demodId].lsbPos,
xpt_enable_output[demodId].numOfBits,
@@ -1415,7 +1611,8 @@ static int config_dis(struct mxl *state, u32 id)
BUILD_HYDRA_CMD(MXL_HYDRA_DISEQC_CFG_MSG_CMD,
MXL_CMD_WRITE, cmdSize, &diseqcMsg, cmdBuff);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
}
static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)

View File

@@ -36,7 +36,9 @@
#include "stv090x.h"
#include "stv090x_priv.h"
#define ERRCTRL1_DVBS1 0x76
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
#define ERRCTRL1_DVBS1 0x76
#define ERRCTRL1_DVBS2 0x67
#define STOP_DEMOD 1
@@ -728,8 +730,16 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8
{
const struct stv090x_config *config = state->config;
int ret;
u8 buf[2 + count];
struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
u8 buf[MAX_XFER_SIZE];
struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0,
.buf = buf, .len = 2 + count };
if (2 + count > sizeof(buf)) {
printk(KERN_WARNING
"%s: i2c wr reg=%04x: len=%d is too big!\n",
KBUILD_MODNAME, reg, count);
return -EINVAL;
}
buf[0] = reg >> 8;
buf[1] = reg & 0xff;
@@ -2144,7 +2154,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
u32 reg;
s32 car_step, steps, cur_step, dir, freq, timeout_lock;
int lock = 0;
int lock;
if (state->srate >= 10000000)
timeout_lock = timeout_dmd / 3;
@@ -2152,18 +2162,20 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
timeout_lock = timeout_dmd / 2;
lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
if (!lock) {
if (lock)
return lock;
if (state->srate >= 10000000) {
if (stv090x_chk_tmg(state)) {
if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
goto err;
lock = stv090x_get_dmdlock(state, timeout_dmd);
} else {
lock = 0;
return stv090x_get_dmdlock(state, timeout_dmd);
}
} else {
return 0;
}
if (state->srate <= 4000000)
car_step = 1000;
else if (state->srate <= 7000000)
@@ -2184,7 +2196,6 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
cur_step = 1;
dir = 1;
if (!lock) {
freq = state->frequency;
state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
while ((cur_step <= steps) && (!lock)) {
@@ -2242,10 +2253,6 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
dir *= -1;
cur_step++;
}
}
}
}
return lock;
err_gateoff:
@@ -2661,14 +2668,9 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
return STV090x_RANGEOK;
else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
return STV090x_RANGEOK;
else
return STV090x_OUTOFRANGE; /* Out of Range */
} else {
} else
if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
return STV090x_RANGEOK;
else
return STV090x_OUTOFRANGE;
}
return STV090x_OUTOFRANGE;
@@ -2787,6 +2789,12 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod
aclc = car_loop[i].crl_pilots_off_30;
}
} else { /* 16APSK and 32APSK */
/*
* This should never happen in practice, except if
* something is really wrong at the car_loop table.
*/
if (i >= 11)
i = 10;
if (state->srate <= 3000000)
aclc = car_loop_apsk_low[i].crl_pilots_on_2;
else if (state->srate <= 7000000)
@@ -3435,6 +3443,48 @@ err:
return -1;
}
static int stv090x_set_pls(struct stv090x_state *state, u8 pls_mode, u32 pls_code)
{
dprintk(FE_DEBUG, 1, "Set PLS code %d (mode %d)", pls_code, pls_mode);
if (STV090x_WRITE_DEMOD(state, PLROOT2, (pls_mode << 2) | (pls_code >> 16)) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, PLROOT1, (pls_code >> 8) & 0xff) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, PLROOT0, pls_code & 0xff) < 0)
goto err;
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
static int stv090x_set_mis(struct stv090x_state *state, u32 mis)
{
u32 reg;
if (mis == NO_STREAM_ID_FILTER) {
dprintk(FE_DEBUG, 1, "Disable MIS filtering");
reg = STV090x_READ_DEMOD(state, PDELCTRL1);
STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00);
if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
goto err;
} else {
dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis);
reg = STV090x_READ_DEMOD(state, PDELCTRL1);
STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01);
if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis & 0xff) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0)
goto err;
}
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
#ifndef USE_API3
static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
#else
@@ -3443,6 +3493,7 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *props = &fe->dtv_property_cache;
u32 pls = 1;
#ifndef USE_API3
if (props->frequency == 0)
@@ -3450,7 +3501,19 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
return DVBFE_ALGO_SEARCH_INVALID;
#endif
state->delsys = props->delivery_system;
switch (props->delivery_system) {
case SYS_DSS:
state->delsys = STV090x_DSS;
break;
case SYS_DVBS:
state->delsys = STV090x_DVBS1;
break;
case SYS_DVBS2:
state->delsys = STV090x_DVBS2;
break;
default:
return DVBFE_ALGO_SEARCH_INVALID;
}
#ifndef USE_API3
state->frequency = props->frequency;
state->srate = props->symbol_rate;
@@ -3469,6 +3532,16 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
state->search_range = 5000000;
}
/* Backwards compatibility to "crazy" API.
PRBS X root cannot be 0, so this should always work. */
if ((props->stream_id != NO_STREAM_ID_FILTER) &&
(props->stream_id & 0xffffff00))
pls = props->stream_id >> 8;
if (props->pls != NO_SCRAMBLING_CODE)
pls = props->pls | 0x40000; /* props->pls is always gold code */
stv090x_set_pls(state, (pls >> 18) & 3, pls & 0x3ffff);
stv090x_set_mis(state, props->stream_id);
if (stv090x_algo(state) == STV090x_RANGEOK) {
dprintk(FE_DEBUG, 1, "Search success!");
return DVBFE_ALGO_SEARCH_SUCCESS;
@@ -3480,6 +3553,43 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
return DVBFE_ALGO_SEARCH_ERROR;
}
static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr);
static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength);
static int stv090x_ber_prop(struct dvb_frontend *fe, enum fe_status *status)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg, h, m, l;
u32 n = 0, d = 1;
if (!(*status & FE_HAS_LOCK)) {
n = 1;
d = 1;
} else {
/* Counter 1 */
reg = STV090x_READ_DEMOD(state, ERRCNT12);
h = STV090x_GETFIELD_Px(reg, ERR_CNT12_FIELD);
reg = STV090x_READ_DEMOD(state, ERRCNT11);
m = STV090x_GETFIELD_Px(reg, ERR_CNT11_FIELD);
reg = STV090x_READ_DEMOD(state, ERRCNT10);
l = STV090x_GETFIELD_Px(reg, ERR_CNT10_FIELD);
n = ((h << 16) | (m << 8) | l);
}
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue =n;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = d;
return 0;
}
static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct stv090x_state *state = fe->demodulator_priv;
@@ -3500,9 +3610,11 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
case 1: /* first PLH detected */
default:
dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
state->rec_mode = 0;
break;
case 2: /* DVB-S2 mode */
state->rec_mode = 2;
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
@@ -3516,6 +3628,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
break;
case 3: /* DVB-S1/legacy mode */
state->rec_mode = 1;
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
@@ -3529,13 +3642,22 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
break;
}
{
u16 val;
u32 ber;
stv090x_read_cnr(fe, &val);
stv090x_read_signal_strength(fe, &val);
stv090x_ber_prop(fe, status);
}
return 0;
}
static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg, h, m, l;
enum fe_status status;
@@ -3555,6 +3677,14 @@ static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber)
*ber = ((h << 16) | (m << 8) | l);
}
#if 0
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = n;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = d;
#endif
return 0;
}
@@ -3650,6 +3780,7 @@ static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg;
s32 agc_0, agc_1, agc;
s32 str;
@@ -3666,8 +3797,15 @@ static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
str = 0;
else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
str = -100;
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = 1000 * (s64) (s32) str;
#ifdef DBVALS
*strength = str;
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = 10 * (s64) str;
#else
*strength = (str + 100) * 0xFFFF / 100;
#endif
@@ -3694,13 +3832,13 @@ static int stv090x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg_0, reg_1, reg, i;
s32 val_0, val_1, val = 0;
u8 lock_f;
#ifndef DBVALS
s32 cnr_db;
s32 div;
u32 last;
#endif
switch (state->delsys) {
case STV090x_DVBS2:
@@ -3717,21 +3855,16 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
msleep(1);
}
val /= 16;
#ifdef DBVALS
*cnr = stv090x_table_lookup(stv090x_s2cn_tab,
cnr_db = stv090x_table_lookup(stv090x_s2cn_tab,
ARRAY_SIZE(stv090x_s2cn_tab) - 1, val);
#else
last = ARRAY_SIZE(stv090x_s2cn_tab) - 1;
div = stv090x_s2cn_tab[0].read -
stv090x_s2cn_tab[last].read;
*cnr = 0xFFFF - ((val * 0xFFFF) / div);
#endif
} else
#ifdef DBVALS
*cnr = -30;
#else
} else {
cnr_db = -30;
*cnr = 0;
#endif
}
break;
case STV090x_DVBS1:
@@ -3749,26 +3882,30 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
msleep(1);
}
val /= 16;
#ifdef DBVALS
*cnr = stv090x_table_lookup(stv090x_s1cn_tab,
cnr_db = stv090x_table_lookup(stv090x_s1cn_tab,
ARRAY_SIZE(stv090x_s1cn_tab) - 1, val);
#else
last = ARRAY_SIZE(stv090x_s1cn_tab) - 1;
div = stv090x_s1cn_tab[0].read -
stv090x_s1cn_tab[last].read;
*cnr = 0xFFFF - ((val * 0xFFFF) / div);
#endif
} else
} else {
cnr_db = -30;
*cnr = 0;
}
break;
default:
break;
}
#ifdef DBVALS
*cnr = cnr_db;
#endif
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 100 * (s64) cnr_db;
return 0;
}
static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
static int stv090x_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct stv090x_state *state = fe->demodulator_priv;
u32 reg;
@@ -3866,7 +4003,8 @@ err:
return -1;
}
static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
static int stv090x_send_diseqc_burst(struct dvb_frontend *fe,
enum fe_sec_mini_cmd burst)
{
struct stv090x_state *state = fe->demodulator_priv;
u32 reg, idle = 0, fifo_full = 1;
@@ -3977,12 +4115,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_TSTTNR1);
STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
goto err;
goto err_unlock;
/* power off DiSEqC 1 */
reg = stv090x_read_reg(state, STV090x_TSTTNR2);
STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
goto err;
goto err_unlock;
/* check whether path 2 is already sleeping, that is when
ADC2 is off */
@@ -4001,7 +4139,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
goto err;
goto err_unlock;
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
/* sampling 1 clock */
STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
@@ -4012,7 +4150,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
goto err_unlock;
break;
case STV090x_DEMODULATOR_1:
@@ -4020,12 +4158,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_TSTTNR3);
STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
goto err;
goto err_unlock;
/* power off DiSEqC 2 */
reg = stv090x_read_reg(state, STV090x_TSTTNR4);
STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
goto err;
goto err_unlock;
/* check whether path 1 is already sleeping, that is when
ADC1 is off */
@@ -4044,7 +4182,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
goto err;
goto err_unlock;
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
/* sampling 2 clock */
STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
@@ -4055,7 +4193,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
goto err_unlock;
break;
default:
@@ -4068,7 +4206,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
goto err;
goto err_unlock;
}
mutex_unlock(&state->internal->demod_lock);
@@ -4076,8 +4214,10 @@ static int stv090x_sleep(struct dvb_frontend *fe)
err_gateoff:
stv090x_i2c_gate_ctrl(state, 0);
err:
goto err;
err_unlock:
mutex_unlock(&state->internal->demod_lock);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
@@ -4338,7 +4478,7 @@ err:
return -1;
}
static int stv090x_set_tspath(struct stv090x_state *state)
static int stv0900_set_tspath(struct stv090x_state *state)
{
u32 reg;
@@ -4588,8 +4728,6 @@ static int stv090x_set_tspath(struct stv090x_state *state)
}
printk("TSCFGH resets\n");
reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
@@ -4612,6 +4750,121 @@ err:
return -1;
}
static int stv0903_set_tspath(struct stv090x_state *state)
{
u32 reg;
if (state->internal->dev_ver >= 0x20) {
switch (state->config->ts1_mode) {
case STV090x_TSMODE_PARALLEL_PUNCTURED:
case STV090x_TSMODE_DVBCI:
stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
break;
case STV090x_TSMODE_SERIAL_PUNCTURED:
case STV090x_TSMODE_SERIAL_CONTINUOUS:
default:
stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c);
break;
}
} else {
switch (state->config->ts1_mode) {
case STV090x_TSMODE_PARALLEL_PUNCTURED:
case STV090x_TSMODE_DVBCI:
stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
break;
case STV090x_TSMODE_SERIAL_PUNCTURED:
case STV090x_TSMODE_SERIAL_CONTINUOUS:
default:
stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
break;
}
}
switch (state->config->ts1_mode) {
case STV090x_TSMODE_PARALLEL_PUNCTURED:
reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
break;
case STV090x_TSMODE_DVBCI:
reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
break;
case STV090x_TSMODE_SERIAL_PUNCTURED:
reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
break;
case STV090x_TSMODE_SERIAL_CONTINUOUS:
reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
break;
default:
break;
}
if (state->config->ts1_clk > 0) {
u32 speed;
switch (state->config->ts1_mode) {
case STV090x_TSMODE_PARALLEL_PUNCTURED:
case STV090x_TSMODE_DVBCI:
default:
speed = state->internal->mclk /
(state->config->ts1_clk / 4);
if (speed < 0x08)
speed = 0x08;
if (speed > 0xFF)
speed = 0xFF;
break;
case STV090x_TSMODE_SERIAL_PUNCTURED:
case STV090x_TSMODE_SERIAL_CONTINUOUS:
speed = state->internal->mclk /
(state->config->ts1_clk / 32);
if (speed < 0x20)
speed = 0x20;
if (speed > 0xFF)
speed = 0xFF;
break;
}
reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
goto err;
if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
goto err;
}
reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
goto err;
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
static int stv090x_init(struct dvb_frontend *fe)
{
struct stv090x_state *state = fe->demodulator_priv;
@@ -4675,8 +4928,13 @@ static int stv090x_init(struct dvb_frontend *fe)
goto err;
#if 0
if (stv090x_set_tspath(state) < 0)
if (state->device == STV0900) {
if (stv0900_set_tspath(state) < 0)
goto err;
} else {
if (stv0903_set_tspath(state) < 0)
goto err;
}
#endif
return 0;
@@ -4717,6 +4975,7 @@ static int stv090x_setup(struct dvb_frontend *fe)
/* Stop Demod */
if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0)
goto err;
if (state->device == STV0900)
if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0)
goto err;
@@ -4725,6 +4984,7 @@ static int stv090x_setup(struct dvb_frontend *fe)
/* Set No Tuner Mode */
if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0)
goto err;
if (state->device == STV0900)
if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0)
goto err;
@@ -4732,6 +4992,7 @@ static int stv090x_setup(struct dvb_frontend *fe)
STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0)
goto err;
if (state->device == STV0900)
if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0)
goto err;
@@ -4793,8 +5054,13 @@ static int stv090x_setup(struct dvb_frontend *fe)
if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
goto err;
if (stv090x_set_tspath(state) < 0)
if (state->device == STV0900) {
if (stv0900_set_tspath(state) < 0)
goto err;
} else {
if (stv0903_set_tspath(state) < 0)
goto err;
}
return 0;
err:
@@ -4802,8 +5068,8 @@ err:
return -1;
}
int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
u8 xor_value)
static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
u8 value, u8 xor_value)
{
struct stv090x_state *state = fe->demodulator_priv;
u8 reg = 0;
@@ -4814,7 +5080,132 @@ int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
}
EXPORT_SYMBOL(stv090x_set_gpio);
static int stv090x_get_frontend(struct dvb_frontend *fe)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 tmp;
u32 reg = 0;
if (state->rec_mode == 2) {
u32 mc;
enum fe_modulation modcod2mod[0x20] = {
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
PSK_8, PSK_8, PSK_8, PSK_8,
PSK_8, PSK_8, APSK_16, APSK_16,
APSK_16, APSK_16, APSK_16, APSK_16,
APSK_32, APSK_32, APSK_32, APSK_32,
APSK_32,
};
enum fe_code_rate modcod2fec[0x20] = {
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
FEC_9_10
};
mc = state->modcod;
p->pilot = (state->pilots & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc];
} else if (state->rec_mode == 1) {
reg = STV090x_READ_DEMOD(state, VITCURPUN);
switch( reg & 0x1F ) {
case 0x0d:
p->fec_inner = FEC_1_2;
break;
case 0x12:
p->fec_inner = FEC_2_3;
break;
case 0x15:
p->fec_inner = FEC_3_4;
break;
case 0x18:
p->fec_inner = FEC_5_6;
break;
case 0x1a:
p->fec_inner = FEC_7_8;
break;
default:
p->fec_inner = FEC_NONE;
break;
}
p->rolloff = ROLLOFF_35;
} else {
}
return 0;
}
static int get_frontend(struct dvb_frontend *fe)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 tmp;
u32 reg = 0;
if (state->rec_mode == 2) {
u32 mc;
enum fe_modulation modcod2mod[0x20] = {
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
PSK_8, PSK_8, PSK_8, PSK_8,
PSK_8, PSK_8, APSK_16, APSK_16,
APSK_16, APSK_16, APSK_16, APSK_16,
APSK_32, APSK_32, APSK_32, APSK_32,
APSK_32,
};
enum fe_code_rate modcod2fec[0x20] = {
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
FEC_9_10
};
mc = state->modcod;
p->pilot = (state->pilots & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc];
} else if (state->rec_mode == 1) {
reg = STV090x_READ_DEMOD(state, VITCURPUN);
switch( reg & 0x1F ) {
case 0x0d:
p->fec_inner = FEC_1_2;
break;
case 0x12:
p->fec_inner = FEC_2_3;
break;
case 0x15:
p->fec_inner = FEC_3_4;
break;
case 0x18:
p->fec_inner = FEC_5_6;
break;
case 0x1a:
p->fec_inner = FEC_7_8;
break;
default:
p->fec_inner = FEC_NONE;
break;
}
p->rolloff = ROLLOFF_35;
} else {
}
return 0;
}
static struct dvb_frontend_ops stv090x_ops = {
#ifndef USE_API3
@@ -4842,6 +5233,7 @@ static struct dvb_frontend_ops stv090x_ops = {
.sleep = stv090x_sleep,
.get_frontend_algo = stv090x_frontend_algo,
.get_frontend = stv090x_get_frontend,
.diseqc_send_master_cmd = stv090x_send_diseqc_msg,
.diseqc_send_burst = stv090x_send_diseqc_burst,
@@ -4857,7 +5249,7 @@ static struct dvb_frontend_ops stv090x_ops = {
};
struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod)
{
@@ -4911,15 +5303,22 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
}
}
if (state->internal->dev_ver >= 0x30)
state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
/* workaround for stuck DiSEqC output */
if (config->diseqc_envelope_mode)
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
config->set_gpio = stv090x_set_gpio;
dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
state->device == STV0900 ? "STV0900" : "STV0903",
demod,
state->internal->dev_ver);
printk("STV0900 version 0x%02x\n", state->internal->dev_ver);
return &state->frontend;
err_remove:

View File

@@ -101,18 +101,18 @@ struct stv090x_config {
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);
/* dir = 0 -> output, dir = 1 -> input/open-drain */
int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
u8 xor_value);
};
#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
extern struct dvb_frontend *stv090x_attach(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,
@@ -123,12 +123,6 @@ static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *c
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 */

View File

@@ -274,6 +274,7 @@ struct stv090x_state {
s32 DemodTimeout;
s32 FecTimeout;
u32 rec_mode;
};
#endif /* __STV090x_PRIV_H */

View File

@@ -1,7 +1,7 @@
/*
* Driver for the ST STV0910 DVB-S/S2 demodulator.
*
* Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
* Copyright (C) 2014-2016 Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de>
* developed for Digital Devices GmbH
*
@@ -38,6 +38,7 @@
#include "stv0910_regs.h"
#define EXT_CLOCK 30000000
#define TUNING_DELAY 200
#define BER_SRC_S 0x20
#define BER_SRC_S2 0x20
@@ -46,7 +47,6 @@ LIST_HEAD(stvlist);
enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto };
enum DVBS2_FECType { DVBS2_64K, DVBS2_16K };
enum DVBS2_ModCod {
@@ -103,6 +103,7 @@ struct stv {
u16 regoff;
u8 i2crpt;
u8 tscfgh;
u8 tsgeneral;
u8 tsspeed;
unsigned long tune_time;
@@ -123,9 +124,17 @@ struct stv {
u32 Pilots;
enum FE_STV0910_RollOff FERollOff;
int isStandardBroadcast;
int isVCM;
u32 CurScramblingCode;
u32 ScramblingCode;
u32 LastBERNumerator;
u32 LastBERDenominator;
u8 BERScale;
u8 VTH[6];
};
struct SInitTable {
@@ -133,9 +142,9 @@ struct SInitTable {
u8 Data;
};
struct SLookupSNTable {
s16 SignalToNoise;
u16 RefValue;
struct SLookup {
s16 Value;
u16 RegValue;
};
static inline int i2c_write(struct i2c_adapter *adap, u8 adr,
@@ -193,7 +202,20 @@ static int read_regs(struct stv *state, u16 reg, u8 *val, int len)
reg, val, len);
}
struct SLookupSNTable S1_SN_Lookup[] = {
static int write_shared_reg(struct stv *state, u16 reg, u8 mask, u8 val)
{
int status;
u8 tmp;
mutex_lock(&state->base->reg_lock);
status = read_reg(state, reg, &tmp);
if (!status)
status = write_reg(state, reg, (tmp & ~mask) | (val & mask));
mutex_unlock(&state->base->reg_lock);
return status;
}
struct SLookup S1_SN_Lookup[] = {
{ 0, 9242 }, /*C/N= 0dB*/
{ 05, 9105 }, /*C/N=0.5dB*/
{ 10, 8950 }, /*C/N=1.0dB*/
@@ -250,7 +272,7 @@ struct SLookupSNTable S1_SN_Lookup[] = {
{ 510, 425 } /*C/N=51.0dB*/
};
struct SLookupSNTable S2_SN_Lookup[] = {
struct SLookup S2_SN_Lookup[] = {
{ -30, 13950 }, /*C/N=-2.5dB*/
{ -25, 13580 }, /*C/N=-2.5dB*/
{ -20, 13150 }, /*C/N=-2.0dB*/
@@ -452,24 +474,45 @@ static int GetCurSymbolRate(struct stv *state, u32 *pSymbolRate)
static int GetSignalParameters(struct stv *state)
{
u8 tmp;
if (!state->Started)
return -1;
if (state->ReceiveMode == Mode_DVBS2) {
u8 tmp;
u8 rolloff;
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
state->ModCod = (enum FE_STV0910_ModCod) ((tmp & 0x7c) >> 2);
state->Pilots = (tmp & 0x01) != 0;
state->FECType = (enum DVBS2_FECType) ((tmp & 0x02) >> 1);
#if 0
read_reg(state, RSTV0910_P2_TMGOBS + state->regoff, &rolloff);
rolloff = rolloff >> 6;
state->FERollOff = (enum FE_STV0910_RollOff) rolloff;
#endif
} else if (state->ReceiveMode == Mode_DVBS) {
/* todo */
read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp);
state->PunctureRate = FEC_NONE;
switch (tmp & 0x1F) {
case 0x0d:
state->PunctureRate = FEC_1_2;
break;
case 0x12:
state->PunctureRate = FEC_2_3;
break;
case 0x15:
state->PunctureRate = FEC_3_4;
break;
case 0x18:
state->PunctureRate = FEC_5_6;
break;
case 0x1A:
state->PunctureRate = FEC_7_8;
break;
}
state->isVCM = 0;
state->isStandardBroadcast = 1;
state->FERollOff = FE_SAT_35;
}
return 0;
}
@@ -485,18 +528,20 @@ static int TrackingOptimization(struct stv *state)
switch (state->ReceiveMode) {
case Mode_DVBS:
tmp |= 0x40; break;
tmp |= 0x40;
break;
case Mode_DVBS2:
tmp |= 0x80; break;
tmp |= 0x80;
break;
default:
tmp |= 0xC0; break;
tmp |= 0xC0;
break;
}
write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp);
if (state->ReceiveMode == Mode_DVBS2) {
/* force to PRE BCH Rate */
write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff,
BER_SRC_S2 | state->BERScale);
/*Disable Reed-Solomon */
write_shared_reg(state, RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 0x03);
if (state->FECType == DVBS2_64K) {
u8 aclc = get_optim_cloop(state, state->ModCod,
@@ -523,40 +568,51 @@ static int TrackingOptimization(struct stv *state)
}
}
}
if (state->ReceiveMode == Mode_DVBS) {
u8 tmp;
read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp);
state->PunctureRate = FEC_NONE;
switch (tmp & 0x1F) {
case 0x0d:
state->PunctureRate = FEC_1_2;
break;
case 0x12:
state->PunctureRate = FEC_2_3;
break;
case 0x15:
state->PunctureRate = FEC_3_4;
break;
case 0x18:
state->PunctureRate = FEC_5_6;
break;
case 0x1A:
state->PunctureRate = FEC_7_8;
break;
}
}
return 0;
}
static s32 TableLookup(struct SLookup *Table,
int TableSize, u16 RegValue)
{
s32 Value;
int imin = 0;
int imax = TableSize - 1;
int i;
s32 RegDiff;
/* Assumes Table[0].RegValue > Table[imax].RegValue */
if( RegValue >= Table[0].RegValue )
Value = Table[0].Value;
else if( RegValue <= Table[imax].RegValue )
Value = Table[imax].Value;
else
{
while(imax-imin > 1)
{
i = (imax + imin) / 2;
if( (Table[imin].RegValue >= RegValue) && (RegValue >= Table[i].RegValue) )
imax = i;
else
imin = i;
}
RegDiff = Table[imax].RegValue - Table[imin].RegValue;
Value = Table[imin].Value;
if( RegDiff != 0 )
Value += ((s32)(RegValue - Table[imin].RegValue) *
(s32)(Table[imax].Value - Table[imin].Value))/(RegDiff);
}
return Value;
}
static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise)
{
int i;
u8 Data0;
u8 Data1;
u16 Data;
int nLookup;
struct SLookupSNTable *Lookup;
struct SLookup *Lookup;
*SignalToNoise = 0;
@@ -575,25 +631,7 @@ static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise)
Lookup = S1_SN_Lookup;
}
Data = (((u16)Data1) << 8) | (u16) Data0;
if (Data > Lookup[0].RefValue) {
*SignalToNoise = Lookup[0].SignalToNoise;
} else if (Data <= Lookup[nLookup-1].RefValue) {
*SignalToNoise = Lookup[nLookup-1].SignalToNoise;
} else {
for (i = 0; i < nLookup - 1; i += 1) {
if (Data <= Lookup[i].RefValue &&
Data > Lookup[i+1].RefValue) {
*SignalToNoise =
(s32)(Lookup[i].SignalToNoise) +
((s32)(Data - Lookup[i].RefValue) *
(s32)(Lookup[i+1].SignalToNoise -
Lookup[i].SignalToNoise)) /
((s32)(Lookup[i+1].RefValue) -
(s32)(Lookup[i].RefValue));
break;
}
}
}
*SignalToNoise = TableLookup(Lookup, nLookup, Data);
return 0;
}
@@ -670,7 +708,8 @@ static u32 DVBS2_nBCH(enum DVBS2_ModCod ModCod, enum DVBS2_FECType FECType)
return 64800;
}
static int GetBitErrorRateS2(struct stv *state, u32 *BERNumerator,
static int GetBitErrorRateS2(struct stv *state,
u32 *BERNumerator,
u32 *BERDenominator)
{
u8 Regs[3];
@@ -812,11 +851,117 @@ static int Stop(struct stv *state)
}
static int init_search_param(struct stv *state)
{
u8 tmp;
read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp);
tmp |= 0x20; // Filter_en (no effect if SIS=non-MIS
write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp);
read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, &tmp);
tmp &= ~0x02; // frame mode = 0
write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, tmp);
write_reg(state, RSTV0910_P2_UPLCCST0 + state->regoff, 0xe0);
write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 0x00);
read_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, &tmp);
tmp &= ~0x01; // nosync = 0, in case next signal is standard TS
write_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, tmp);
read_reg(state, RSTV0910_P2_TSCFGL + state->regoff, &tmp);
tmp &= ~0x04; // embindvb = 0
write_reg(state, RSTV0910_P2_TSCFGL + state->regoff, tmp);
read_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, &tmp);
tmp &= ~0x80; // syncbyte = 0
write_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, tmp);
read_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, &tmp);
tmp &= ~0x08; // token = 0
write_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, tmp);
read_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, &tmp);
tmp &= ~0x30; // hysteresis threshold = 0
write_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, tmp);
read_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, &tmp);
tmp = (tmp & ~0x30) | 0x10; // isi obs mode = 1, observe min ISI
write_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, tmp);
return 0;
}
static int EnablePunctureRate(struct stv *state, enum fe_code_rate rate)
{
switch(rate) {
case FEC_1_2:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x01);
case FEC_2_3:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x02);
case FEC_3_4:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x04);
case FEC_5_6:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x08);
case FEC_7_8:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x20);
case FEC_NONE:
default:
return write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2f);
}
}
static int set_vth_default(struct stv *state)
{
state->VTH[0] = 0xd7;
state->VTH[1] = 0x85;
state->VTH[2] = 0x58;
state->VTH[3] = 0x3a;
state->VTH[4] = 0x34;
state->VTH[5] = 0x28;
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->VTH[0]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->VTH[1]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->VTH[2]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->VTH[3]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->VTH[4]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->VTH[5]);
return 0;
}
static int set_vth(struct stv *state)
{
static struct SLookup VTHLookupTable[] = {
{250, 8780}, /*C/N=1.5dB*/
{100, 7405}, /*C/N=4.5dB*/
{40, 6330}, /*C/N=6.5dB*/
{12, 5224}, /*C/N=8.5dB*/
{5, 4236} /*C/N=10.5dB*/
};
int i;
u8 tmp[2];
int status = read_regs(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, tmp, 2);
u16 RegValue = (tmp[0] << 8) | tmp[1];
s32 vth = TableLookup(VTHLookupTable, ARRAY_SIZE(VTHLookupTable), RegValue);
for (i = 0; i < 6; i += 1)
if (state->VTH[i] > vth)
state->VTH[i] = vth;
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->VTH[0]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->VTH[1]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->VTH[2]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->VTH[3]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->VTH[4]);
write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->VTH[5]);
return status;
}
static int Start(struct stv *state, struct dtv_frontend_properties *p)
{
s32 Freq;
u8 regDMDCFGMD;
u16 symb;
u32 ScramblingCode = 1;
if (p->symbol_rate < 100000 || p->symbol_rate > 70000000)
return -EINVAL;
@@ -828,6 +973,34 @@ static int Start(struct stv *state, struct dtv_frontend_properties *p)
if (state->Started)
write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C);
init_search_param(state);
if (p->stream_id != NO_STREAM_ID_FILTER) {
/* Backwards compatibility to "crazy" API.
PRBS X root cannot be 0, so this should always work.
*/
if (p->stream_id & 0xffffff00)
ScramblingCode = p->stream_id >> 8;
write_reg(state, RSTV0910_P2_ISIENTRY + state->regoff, p->stream_id & 0xff);
write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 0xff);
//pr_info("ID=%08x\n", p->stream_id & 0xff);
}
/* props->pls is always gold code ! */
if (p->pls != NO_SCRAMBLING_CODE)
ScramblingCode = p->pls | 0x40000;
if (ScramblingCode != state->CurScramblingCode) {
write_reg(state, RSTV0910_P2_PLROOT0 + state->regoff,
ScramblingCode & 0xff);
write_reg(state, RSTV0910_P2_PLROOT1 + state->regoff,
(ScramblingCode >> 8) & 0xff);
write_reg(state, RSTV0910_P2_PLROOT2 + state->regoff,
(ScramblingCode >> 16) & 0x07);
state->CurScramblingCode = ScramblingCode;
//pr_info("PLS=%08x\n", ScramblingCode);
}
if (p->symbol_rate <= 1000000) { /*SR <=1Msps*/
state->DemodTimeout = 3000;
state->FecTimeout = 2000;
@@ -863,25 +1036,43 @@ static int Start(struct stv *state, struct dtv_frontend_properties *p)
read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &regDMDCFGMD);
write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff,
regDMDCFGMD |= 0xC0);
write_shared_reg(state, RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 0x00);
/* Disable DSS */
write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00);
write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F);
EnablePunctureRate(state, FEC_NONE);
/* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/
write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B);
write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A);
write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84);
write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84);
write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C);
write_reg(state, RSTV0910_P2_CARFREQ + state->regoff, 0x79);
write_reg(state, RSTV0910_P2_ACLC2S216A + state->regoff, 0x29);
write_reg(state, RSTV0910_P2_ACLC2S232A + state->regoff, 0x09);
write_reg(state, RSTV0910_P2_BCLC2S216A + state->regoff, 0x84);
write_reg(state, RSTV0910_P2_BCLC2S232A + state->regoff, 0x84);
/* Reset CAR3, bug DVBS2->DVBS1 lock*/
/* Note: The bit is only pulsed -> no lock on shared register needed */
write_reg(state, RSTV0910_TSTRES0, state->nr ? 0x04 : 0x08);
write_reg(state, RSTV0910_TSTRES0, 0);
set_vth_default(state);
/* Reset demod */
write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F);
write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46);
Freq = (state->SearchRange / 2000) + 600;
if (p->symbol_rate <= 5000000)
Freq -= (600 + 80);
Freq = (state->SearchRange / 2000) + 80;
else
Freq = (state->SearchRange / 2000) + 1600;
Freq = (Freq << 16) / (state->base->mclk / 1000);
write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff,
@@ -932,26 +1123,36 @@ static int probe(struct stv *state)
if (id != 0x51)
return -EINVAL;
pr_info("stv0910: found STV0910 id=0x%02x\n", id);
/* pr_info("stv0910: found STV0910 id=0x%02x\n", id); */
/* Configure the I2C repeater to off */
write_reg(state, RSTV0910_P1_I2CRPT, 0x24);
/* Configure the I2C repeater to off */
write_reg(state, RSTV0910_P2_I2CRPT, 0x24);
/* Set the I2C to oversampling ratio */
write_reg(state, RSTV0910_I2CCFG, 0x88);
write_reg(state, RSTV0910_I2CCFG, 0x88); /* state->i2ccfg */
write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */
write_reg(state, RSTV0910_PADCFG, 0x05); /* RF AGC Pads Dev = 05 */
write_reg(state, RSTV0910_PADCFG, 0x05); /* RFAGC Pads Dev = 05 */
write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */
write_reg(state, RSTV0910_TSGENERAL, 0x00); /* TSGENERAL */
write_reg(state, RSTV0910_TSGENERAL, state->tsgeneral); /* TSGENERAL */
write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */
write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */
write_reg(state, RSTV0910_P1_CAR3CFG, 0x02);
write_reg(state, RSTV0910_P2_CAR3CFG, 0x02);
write_reg(state, RSTV0910_P1_DMDCFG4, 0x04);
write_reg(state, RSTV0910_P2_DMDCFG4, 0x04);
write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */
write_reg(state, RSTV0910_TSTRES0, 0x00);
write_reg(state, RSTV0910_P1_TSPIDFLT1, 0x00);
write_reg(state, RSTV0910_P2_TSPIDFLT1, 0x00);
write_reg(state, RSTV0910_P1_TMGCFG2, 0x80);
write_reg(state, RSTV0910_P2_TMGCFG2, 0x80);
set_mclock(state, 135000000);
/* TS output */
@@ -1038,6 +1239,114 @@ static int set_parameters(struct dvb_frontend *fe)
return stat;
}
static int get_frequency_offset(struct stv *state, s32 *off)
{
u8 cfr0, cfr1, cfr2;
s32 derot;
read_reg(state, RSTV0910_P2_CFR2 + state->regoff, &cfr2);
read_reg(state, RSTV0910_P2_CFR1 + state->regoff, &cfr1);
read_reg(state, RSTV0910_P2_CFR0 + state->regoff, &cfr0);
derot = ((u32) cfr2 << 16) | ((u32)cfr1 << 8) | cfr0;
if (derot & (1<<23))
derot |= 0xFF000000;
*off = - (s32) (((s64) derot * (s64) state->base->mclk) >> 24);
//pr_info("foff = %d\n", *off);
return 0;
}
static int get_frontend(struct dvb_frontend *fe)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 tmp;
if (state->ReceiveMode == Mode_DVBS2) {
u32 mc;
enum fe_modulation modcod2mod[0x20] = {
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
QPSK, QPSK, QPSK, QPSK,
PSK_8, PSK_8, PSK_8, PSK_8,
PSK_8, PSK_8, APSK_16, APSK_16,
APSK_16, APSK_16, APSK_16, APSK_16,
APSK_32, APSK_32, APSK_32, APSK_32,
APSK_32,
};
enum fe_code_rate modcod2fec[0x20] = {
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
FEC_9_10
};
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
mc = ((tmp & 0x7c) >> 2);
p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc];
} else if (state->ReceiveMode == Mode_DVBS) {
read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp);
switch( tmp & 0x1F ) {
case 0x0d:
p->fec_inner = FEC_1_2;
break;
case 0x12:
p->fec_inner = FEC_2_3;
break;
case 0x15:
p->fec_inner = FEC_3_4;
break;
case 0x18:
p->fec_inner = FEC_5_6;
break;
case 0x1a:
p->fec_inner = FEC_7_8;
break;
default:
p->fec_inner = FEC_NONE;
break;
}
p->rolloff = ROLLOFF_35;
} else {
}
return 0;
}
static int ManageMatypeInfo(struct stv *state)
{
if (!state->Started)
return -1;
if (state->ReceiveMode == Mode_DVBS2 ) {
u8 BBHeader[2];
read_regs(state, RSTV0910_P2_MATSTR1 + state->regoff,
BBHeader, 2);
state->FERollOff =
(enum FE_STV0910_RollOff) (BBHeader[0] & 0x03);
state->isVCM = (BBHeader[0] & 0x10) == 0;
state->isStandardBroadcast = (BBHeader[0] & 0xFC) == 0xF0;
} else if (state->ReceiveMode == Mode_DVBS) {
state->isVCM = 0;
state->isStandardBroadcast = 1;
state->FERollOff = FE_SAT_35;
}
return 0;
}
static int read_snr(struct dvb_frontend *fe, u16 *snr);
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength);
static int read_ber(struct dvb_frontend *fe, u32 *ber);
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
{
@@ -1046,25 +1355,54 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
u8 DStatus = 0;
enum ReceiveMode CurReceiveMode = Mode_None;
u32 FECLock = 0;
u16 val;
u32 ber;
s32 foff;
get_frequency_offset(state, &foff);
read_signal_strength(fe, &val);
read_snr(fe, &val);
read_ber(fe, &ber);
read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState);
if (DmdState & 0x40) {
read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &DStatus);
read_reg(state, RSTV0910_P2_DSTATUS + state->regoff,
&DStatus);
if (DStatus & 0x08)
CurReceiveMode = (DmdState & 0x20) ?
Mode_DVBS : Mode_DVBS2;
}
if (CurReceiveMode == Mode_None) {
set_vth(state);
//if( Time >= m_DemodTimeout ) *pLockStatus = NEVER_LOCK;
*status = 0;
return 0;
}
*status |= 0x0f;
if (state->ReceiveMode == Mode_None) {
state->ReceiveMode = CurReceiveMode;
state->DemodLockTime = jiffies;
state->FirstTimeLock = 0;
state->FirstTimeLock = 1;
GetSignalParameters(state);
TrackingOptimization(state);
#if 0
if( CurReceiveMode == Mode_DVBS2 && m_bPilots
&& ( m_ModCod == FE_8PSK_23 || m_ModCod == FE_8PSK_35) )
{
LONG C_N;
CHK_ERROR(GetSignalToNoise(&C_N));
if( C_N < 80 )
{
CHK_ERROR(WriteReg(RSTV0910_P2_CARHDR + m_DemodOffset , 0x04));
CHK_ERROR(WriteReg(RSTV0910_P2_BCLC2S28 + m_DemodOffset , 0x31));
}
}
#endif
write_reg(state, RSTV0910_P2_TSCFGH + state->regoff,
state->tscfgh);
@@ -1091,6 +1429,7 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
}
if (!FECLock)
//if( Time >= m_DemodLockTime + m_FecTimeout ) *pLockStatus = NEVER_LOCK;
return 0;
*status |= 0x10;
@@ -1099,8 +1438,21 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
u8 tmp;
state->FirstTimeLock = 0;
GetSignalParameters(state);
ManageMatypeInfo(state);
#if 0
ULONG Bitrate;
CSTV0910::GetBitrate(&Bitrate);
BYTE newTSSPEED = (Bitrate > 67000000) ? 0x30 : 0x40;
if (newTSSPEED != m_TSSPEED)
{
KdPrintEx((MSG_INFO "_%d " __FUNCTION__ " TSSPEED = %02X\n", m_Instance, newTSSPEED));
CHK_ERROR(WriteReg(RSTV0910_P2_TSSPEED + m_DemodOffset, newTSSPEED));
m_TSSPEED = newTSSPEED;
}
#endif
if (state->ReceiveMode == Mode_DVBS2) {
/* FSTV0910_P2_MANUALSX_ROLLOFF,
FSTV0910_P2_MANUALS2_ROLLOFF = 0 */
@@ -1111,11 +1463,13 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
&tmp);
/*reset DVBS2 packet delinator error counter */
tmp |= 0x40;
write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff,
write_reg(state, RSTV0910_P2_PDELCTRL2 +
state->regoff,
tmp);
/*reset DVBS2 packet delinator error counter */
tmp &= ~0x40;
write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff,
write_reg(state, RSTV0910_P2_PDELCTRL2 +
state->regoff,
tmp);
state->BERScale = 2;
@@ -1138,8 +1492,25 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
infinit error count mode )*/
write_reg(state, RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1);
TrackingOptimization(state);
set_vth_default(state);
if (state->ReceiveMode == Mode_DVBS)
EnablePunctureRate(state, state->PunctureRate);
}
#if 0
if( m_isVCM )
{
// Use highest signaled ModCod for quality
BYTE tmp;
CHK_ERROR(ReadReg(RSTV0910_P2_DMDMODCOD +
m_DemodOffset,&tmp));
FE_STV0910_ModCod ModCod =
FE_STV0910_ModCod((tmp & 0x7c) >> 2);
if( ModCod > m_ModCod )
m_ModCod = ModCod;
}
#endif
return 0;
}
@@ -1258,21 +1629,28 @@ static int sleep(struct dvb_frontend *fe)
return 0;
}
static int read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
s32 SNR;
*snr = 0;
if (GetSignalToNoise(state, &SNR))
return -EIO;
*snr = SNR;
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 100 * (s64) SNR;
return 0;
}
static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 n, d;
GetBitErrorRate(state, &n, &d);
@@ -1280,18 +1658,98 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
*ber = n / d;
else
*ber = 0;
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = n;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = d;
return 0;
}
static s32 Log10x100(u32 x)
{
static u32 LookupTable[100] = {
101157945, 103514217, 105925373, 108392691, 110917482,
113501082, 116144861, 118850223, 121618600, 124451461,
127350308, 130316678, 133352143, 136458314, 139636836,
142889396, 146217717, 149623566, 153108746, 156675107,
160324539, 164058977, 167880402, 171790839, 175792361,
179887092, 184077200, 188364909, 192752491, 197242274,
201836636, 206538016, 211348904, 216271852, 221309471,
226464431, 231739465, 237137371, 242661010, 248313311,
254097271, 260015956, 266072506, 272270131, 278612117,
285101827, 291742701, 298538262, 305492111, 312607937,
319889511, 327340695, 334965439, 342767787, 350751874,
358921935, 367282300, 375837404, 384591782, 393550075,
402717034, 412097519, 421696503, 431519077, 441570447,
451855944, 462381021, 473151259, 484172368, 495450191,
506990708, 518800039, 530884444, 543250331, 555904257,
568852931, 582103218, 595662144, 609536897, 623734835,
638263486, 653130553, 668343918, 683911647, 699841996,
716143410, 732824533, 749894209, 767361489, 785235635,
803526122, 822242650, 841395142, 860993752, 881048873,
901571138, 922571427, 944060876, 966050879, 988553095,
};
s32 y;
int i;
if (x == 0)
return 0;
y = 800;
if (x >= 1000000000) {
x /= 10;
y += 100;
}
while (x < 100000000) {
x *= 10;
y -= 100;
}
i = 0;
while (i < 100 && x > LookupTable[i])
i += 1;
y += i;
return y;
}
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct stv *state = fe->demodulator_priv;
u8 Agc1, Agc0;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 Reg[2];
s32 bbgain;
s32 Power = 0;
int i;
read_reg(state, RSTV0910_P2_AGCIQIN1 + state->regoff, &Agc1);
read_reg(state, RSTV0910_P2_AGCIQIN0 + state->regoff, &Agc0);
read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2);
*strength = (((u32) Reg[0]) << 8) | Reg[1];
*strength = ((255 - Agc1) * 3300) / 256;
for (i = 0; i < 5; i += 1) {
read_regs(state, RSTV0910_P2_POWERI + state->regoff, Reg, 2);
Power += (u32) Reg[0] * (u32) Reg[0] +
(u32) Reg[1] * (u32) Reg[1];
msleep(3);
}
Power /= 5;
bbgain = (465 - Log10x100(Power)) * 10;
if (fe->ops.tuner_ops.get_rf_strength)
fe->ops.tuner_ops.get_rf_strength(fe, strength);
else
*strength = 0;
if (bbgain < (s32) *strength)
*strength -= bbgain;
else
*strength = 0;
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].uvalue = 10 * (s64) (s16) *strength - 108750;
/* *strength is in hundredth dBuv, uvalue is in thousandth dBm */
return 0;
}
@@ -1323,6 +1781,7 @@ static struct dvb_frontend_ops stv0910_ops = {
.release = release,
.i2c_gate_ctrl = gate_ctrl,
.get_frontend_algo = get_algo,
.get_frontend = get_frontend,
.tune = tune,
.read_status = read_status,
.set_tone = set_tone,
@@ -1359,13 +1818,15 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
return NULL;
state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40);
state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00;
state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4);
state->tsspeed = 0x40;
state->tsspeed = 0x28;
state->nr = nr;
state->regoff = state->nr ? 0 : 0x200;
state->SearchRange = 16000000;
state->DEMOD = 0x10; /* Inversion : Auto with reset to 0 */
state->ReceiveMode = Mode_None;
state->CurScramblingCode = NO_SCRAMBLING_CODE;
base = match_base(i2c, cfg->adr);
if (base) {
@@ -1402,5 +1863,5 @@ fail:
EXPORT_SYMBOL_GPL(stv0910_attach);
MODULE_DESCRIPTION("STV0910 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_AUTHOR("Ralph und Marcus Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -50,6 +50,7 @@ struct stv {
u8 reg[11];
u32 ref_freq;
u32 Frequency;
};
static int i2c_read(struct i2c_adapter *adap,
@@ -87,14 +88,12 @@ static int write_regs(struct stv *state, int reg, int len)
return i2c_write(state->i2c, state->adr, d, len + 1);
}
#if 0
static int write_reg(struct stv *state, u8 reg, u8 val)
{
u8 d[2] = {reg, val};
return i2c_write(state->i2c, state->adr, d, 2);
}
#endif
static int read_reg(struct stv *state, u8 reg, u8 *val)
{
@@ -106,20 +105,20 @@ static int read_regs(struct stv *state, u8 reg, u8 *val, int len)
return i2c_read(state->i2c, state->adr, &reg, 1, val, len);
}
#if 0
static void dump_regs(struct stv *state)
{
u8 d[11], *c = &state->reg[0];
read_regs(state, 0, d, 11);
#if 0
pr_info("stv6111_regs = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10]);
pr_info("reg[] = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
c[8], c[9], c[10]);
#endif
}
#endif
static int wait_for_call_done(struct stv *state, u8 mask)
{
@@ -185,7 +184,9 @@ static int attach_init(struct stv *state)
{
if (write_regs(state, 0, 11))
return -1;
#if 0
dump_regs(state);
#endif
return 0;
}
@@ -298,7 +299,11 @@ static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency)
}
read_reg(state, 0x08, &tmp);
state->Frequency = Frequency;
#if 0
dump_regs(state);
#endif
return 0;
}
@@ -306,7 +311,6 @@ static int set_params(struct dvb_frontend *fe)
{
struct stv *state = fe->tuner_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int status;
u32 freq, symb, cutoff;
if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2)
@@ -321,7 +325,7 @@ static int set_params(struct dvb_frontend *fe)
set_lof(state, freq, cutoff);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return status;
return 0;
}
static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -330,54 +334,351 @@ static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
static u32 AGC_Gain[] = {
000, /* 0.0 */
000, /* 0.1 */
1000, /* 0.2 */
2000, /* 0.3 */
3000, /* 0.4 */
4000, /* 0.5 */
5000, /* 0.6 */
6000, /* 0.7 */
7000, /* 0.8 */
14000, /* 0.9 */
20000, /* 1.0 */
27000, /* 1.1 */
32000, /* 1.2 */
37000, /* 1.3 */
42000, /* 1.4 */
47000, /* 1.5 */
50000, /* 1.6 */
53000, /* 1.7 */
56000, /* 1.8 */
58000, /* 1.9 */
60000, /* 2.0 */
62000, /* 2.1 */
63000, /* 2.2 */
64000, /* 2.3 */
64500, /* 2.4 */
65000, /* 2.5 */
65500, /* 2.6 */
66000, /* 2.7 */
66500, /* 2.8 */
67000, /* 2.9 */
struct SLookup {
s16 Value;
u16 RegValue;
};
static struct SLookup LNAGain_NF_LookUp[] = {
/*Gain *100dB*/ /*Reg*/
{ 2572 , 0 },
{ 2575 , 1 },
{ 2580 , 2 },
{ 2588 , 3 },
{ 2596 , 4 },
{ 2611 , 5 },
{ 2633 , 6 },
{ 2664 , 7 },
{ 2701 , 8 },
{ 2753 , 9 },
{ 2816 , 10 },
{ 2902 , 11 },
{ 2995 , 12 },
{ 3104 , 13 },
{ 3215 , 14 },
{ 3337 , 15 },
{ 3492 , 16 },
{ 3614 , 17 },
{ 3731 , 18 },
{ 3861 , 19 },
{ 3988 , 20 },
{ 4124 , 21 },
{ 4253 , 22 },
{ 4386 , 23 },
{ 4505 , 24 },
{ 4623 , 25 },
{ 4726 , 26 },
{ 4821 , 27 },
{ 4903 , 28 },
{ 4979 , 29 },
{ 5045 , 30 },
{ 5102 , 31 }
};
static struct SLookup LNAGain_IIP3_LookUp[] = {
/*Gain *100dB*/ /*reg*/
{ 1548 , 0 },
{ 1552 , 1 },
{ 1569 , 2 },
{ 1565 , 3 },
{ 1577 , 4 },
{ 1594 , 5 },
{ 1627 , 6 },
{ 1656 , 7 },
{ 1700 , 8 },
{ 1748 , 9 },
{ 1805 , 10 },
{ 1896 , 11 },
{ 1995 , 12 },
{ 2113 , 13 },
{ 2233 , 14 },
{ 2366 , 15 },
{ 2543 , 16 },
{ 2687 , 17 },
{ 2842 , 18 },
{ 2999 , 19 },
{ 3167 , 20 },
{ 3342 , 21 },
{ 3507 , 22 },
{ 3679 , 23 },
{ 3827 , 24 },
{ 3970 , 25 },
{ 4094 , 26 },
{ 4210 , 27 },
{ 4308 , 28 },
{ 4396 , 29 },
{ 4468 , 30 },
{ 4535 , 31 }
};
static struct SLookup Gain_RFAGC_LookUp[] = {
/*Gain *100dB*/ /*reg*/
{ 4870 , 0x3000 },
{ 4850 , 0x3C00 },
{ 4800 , 0x4500 },
{ 4750 , 0x4800 },
{ 4700 , 0x4B00 },
{ 4650 , 0x4D00 },
{ 4600 , 0x4F00 },
{ 4550 , 0x5100 },
{ 4500 , 0x5200 },
{ 4420 , 0x5500 },
{ 4316 , 0x5800 },
{ 4200 , 0x5B00 },
{ 4119 , 0x5D00 },
{ 3999 , 0x6000 },
{ 3950 , 0x6100 },
{ 3876 , 0x6300 },
{ 3755 , 0x6600 },
{ 3641 , 0x6900 },
{ 3567 , 0x6B00 },
{ 3425 , 0x6F00 },
{ 3350 , 0x7100 },
{ 3236 , 0x7400 },
{ 3118 , 0x7700 },
{ 3004 , 0x7A00 },
{ 2917 , 0x7C00 },
{ 2776 , 0x7F00 },
{ 2635 , 0x8200 },
{ 2516 , 0x8500 },
{ 2406 , 0x8800 },
{ 2290 , 0x8B00 },
{ 2170 , 0x8E00 },
{ 2073 , 0x9100 },
{ 1949 , 0x9400 },
{ 1836 , 0x9700 },
{ 1712 , 0x9A00 },
{ 1631 , 0x9C00 },
{ 1515 , 0x9F00 },
{ 1400 , 0xA200 },
{ 1323 , 0xA400 },
{ 1203 , 0xA700 },
{ 1091 , 0xAA00 },
{ 1011 , 0xAC00 },
{ 904 , 0xAF00 },
{ 787 , 0xB200 },
{ 685 , 0xB500 },
{ 571 , 0xB800 },
{ 464 , 0xBB00 },
{ 374 , 0xBE00 },
{ 275 , 0xC200 },
{ 181 , 0xC600 },
{ 102 , 0xCC00 },
{ 49 , 0xD900 }
};
// This table is 6 dB too low comapred to the others (probably created with a different BB_MAG setting)
static struct SLookup Gain_Channel_AGC_NF_LookUp[] = {
/*Gain *100dB*/ /*reg*/
{ 7082 , 0x3000 },
{ 7052 , 0x4000 },
{ 7007 , 0x4600 },
{ 6954 , 0x4A00 },
{ 6909 , 0x4D00 },
{ 6833 , 0x5100 },
{ 6753 , 0x5400 },
{ 6659 , 0x5700 },
{ 6561 , 0x5A00 },
{ 6472 , 0x5C00 },
{ 6366 , 0x5F00 },
{ 6259 , 0x6100 },
{ 6151 , 0x6400 },
{ 6026 , 0x6700 },
{ 5920 , 0x6900 },
{ 5835 , 0x6B00 },
{ 5770 , 0x6C00 },
{ 5681 , 0x6E00 },
{ 5596 , 0x7000 },
{ 5503 , 0x7200 },
{ 5429 , 0x7300 },
{ 5319 , 0x7500 },
{ 5220 , 0x7700 },
{ 5111 , 0x7900 },
{ 4983 , 0x7B00 },
{ 4876 , 0x7D00 },
{ 4755 , 0x7F00 },
{ 4635 , 0x8100 },
{ 4499 , 0x8300 },
{ 4405 , 0x8500 },
{ 4323 , 0x8600 },
{ 4233 , 0x8800 },
{ 4156 , 0x8A00 },
{ 4038 , 0x8C00 },
{ 3935 , 0x8E00 },
{ 3823 , 0x9000 },
{ 3712 , 0x9200 },
{ 3601 , 0x9500 },
{ 3511 , 0x9700 },
{ 3413 , 0x9900 },
{ 3309 , 0x9B00 },
{ 3213 , 0x9D00 },
{ 3088 , 0x9F00 },
{ 2992 , 0xA100 },
{ 2878 , 0xA400 },
{ 2769 , 0xA700 },
{ 2645 , 0xAA00 },
{ 2538 , 0xAD00 },
{ 2441 , 0xB000 },
{ 2350 , 0xB600 },
{ 2237 , 0xBA00 },
{ 2137 , 0xBF00 },
{ 2039 , 0xC500 },
{ 1938 , 0xDF00 },
{ 1927 , 0xFF00 }
};
static struct SLookup Gain_Channel_AGC_IIP3_LookUp[] = {
/*Gain *100dB*/ /*reg*/
{ 7070 , 0x3000 },
{ 7028 , 0x4000 },
{ 7019 , 0x4600 },
{ 6900 , 0x4A00 },
{ 6811 , 0x4D00 },
{ 6763 , 0x5100 },
{ 6690 , 0x5400 },
{ 6644 , 0x5700 },
{ 6617 , 0x5A00 },
{ 6598 , 0x5C00 },
{ 6462 , 0x5F00 },
{ 6348 , 0x6100 },
{ 6197 , 0x6400 },
{ 6154 , 0x6700 },
{ 6098 , 0x6900 },
{ 5893 , 0x6B00 },
{ 5812 , 0x6C00 },
{ 5773 , 0x6E00 },
{ 5723 , 0x7000 },
{ 5661 , 0x7200 },
{ 5579 , 0x7300 },
{ 5460 , 0x7500 },
{ 5308 , 0x7700 },
{ 5099 , 0x7900 },
{ 4910 , 0x7B00 },
{ 4800 , 0x7D00 },
{ 4785 , 0x7F00 },
{ 4635 , 0x8100 },
{ 4466 , 0x8300 },
{ 4314 , 0x8500 },
{ 4295 , 0x8600 },
{ 4144 , 0x8800 },
{ 3920 , 0x8A00 },
{ 3889 , 0x8C00 },
{ 3771 , 0x8E00 },
{ 3655 , 0x9000 },
{ 3446 , 0x9200 },
{ 3298 , 0x9500 },
{ 3083 , 0x9700 },
{ 3015 , 0x9900 },
{ 2833 , 0x9B00 },
{ 2746 , 0x9D00 },
{ 2632 , 0x9F00 },
{ 2598 , 0xA100 },
{ 2480 , 0xA400 },
{ 2236 , 0xA700 },
{ 2171 , 0xAA00 },
{ 2060 , 0xAD00 },
{ 1999 , 0xB000 },
{ 1974 , 0xB600 },
{ 1820 , 0xBA00 },
{ 1741 , 0xBF00 },
{ 1655 , 0xC500 },
{ 1444 , 0xDF00 },
{ 1325 , 0xFF00 },
};
static s32 TableLookup(struct SLookup *Table, int TableSize, u16 RegValue)
{
s32 Gain;
s32 RegDiff;
int imin = 0;
int imax = TableSize - 1;
int i;
// Assumes Table[0].RegValue < Table[imax].RegValue
if( RegValue <= Table[0].RegValue )
Gain = Table[0].Value;
else if( RegValue >= Table[imax].RegValue )
Gain = Table[imax].Value;
else {
while(imax-imin > 1) {
i = (imax + imin) / 2;
if ((Table[imin].RegValue <= RegValue) &&
(RegValue <= Table[i].RegValue) )
imax = i;
else
imin = i;
}
RegDiff = Table[imax].RegValue - Table[imin].RegValue;
Gain = Table[imin].Value;
if (RegDiff != 0)
Gain += ((s32) (RegValue - Table[imin].RegValue) *
(s32)(Table[imax].Value - Table[imin].Value))/(RegDiff);
}
return Gain;
}
static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
{
*st = 0;
#if 0
struct stv *state = fe->tuner_priv;
u16 RFAgc = *st;
s32 Gain;
u32 Index = RFAgc / 100;
if (Index >= (sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1))
Gain = AGC_Gain[sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1];
if ((state->reg[0x03] & 0x60) == 0 ) {
// RF Mode
// Read AGC ADC
u8 Reg = 0;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
write_reg(state, 0x02, state->reg[0x02] | 0x20);
read_reg(state, 2, &Reg);
if( Reg & 0x20 )
read_reg(state, 2, &Reg);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if((state->reg[0x02] & 0x80) == 0)
// NF
Gain = TableLookup(LNAGain_NF_LookUp,
ARRAY_SIZE(LNAGain_NF_LookUp), Reg & 0x1F);
else
Gain = AGC_Gain[Index] +
((AGC_Gain[Index+1] - AGC_Gain[Index]) *
(RFAgc % 100)) / 100;
*st = Gain;
#endif
// IIP3
Gain = TableLookup(LNAGain_IIP3_LookUp,
ARRAY_SIZE(LNAGain_IIP3_LookUp), Reg & 0x1F);
Gain += TableLookup(Gain_RFAGC_LookUp,
ARRAY_SIZE(Gain_RFAGC_LookUp), RFAgc);
Gain -= 2400;
} else {
// Channel Mode
if( (state->reg[0x02] & 0x80) == 0 ) {
// NF
Gain = TableLookup(Gain_Channel_AGC_NF_LookUp,
ARRAY_SIZE(Gain_Channel_AGC_NF_LookUp), RFAgc);
Gain += 600;
} else {
// IIP3
Gain = TableLookup(Gain_Channel_AGC_IIP3_LookUp,
ARRAY_SIZE(Gain_Channel_AGC_IIP3_LookUp), RFAgc);
}
}
if (state->Frequency > 0)
// Tilt correction ( 0.00016 dB/MHz )
Gain -= ((((s32)(state->Frequency / 1000) - 1550) * 2) / 12);
Gain += (s32)( (state->reg[0x01] & 0xC0 ) >> 6 ) * 600 - 1300;// + (BBGain * 10);
if( Gain < 0 )
Gain = 0;
else if (Gain > 10000)
Gain = 10000;
*st = 10000 - Gain;
return 0;
}

View File

@@ -447,8 +447,8 @@ static int attach_init(struct tda_state *state)
if (!state->m_isMaster)
state->m_bLTEnable = false;
pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID,
state->m_isMaster ? "master" : "slave");
/*pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID,
state->m_isMaster ? "master" : "slave");*/
if (state->m_ID != 18212)
return -1;
@@ -457,7 +457,7 @@ static int attach_init(struct tda_state *state)
if (stat < 0)
return stat;
pr_info("tda18212dd: PowerState %02x\n", PowerState);
/*pr_info("tda18212dd: PowerState %02x\n", PowerState);*/
if (state->m_isMaster) {
if (PowerState & 0x02) {
@@ -487,6 +487,7 @@ static int attach_init(struct tda_state *state)
FinishCalibration(state);
Standby(state);
#if 0
{
u8 RFCal_Log[12];
@@ -499,6 +500,7 @@ static int attach_init(struct tda_state *state)
RFCal_Log[8], RFCal_Log[9],
RFCal_Log[10], RFCal_Log[11]);
}
#endif
return stat;
}
@@ -775,6 +777,10 @@ static int sleep(struct dvb_frontend *fe)
struct tda_state *state = fe->tuner_priv;
Standby(state);
write_reg(state, THERMO_2, 0x01);
read_reg1(state, THERMO_1);
write_reg(state, THERMO_2, 0x00);
/* printk("sleep: temp = %u\n", state->Regs[THERMO_1]); */
return 0;
}

View File

@@ -165,6 +165,8 @@ typedef enum fe_code_rate {
FEC_3_5,
FEC_9_10,
FEC_2_5,
FEC_1_4,
FEC_1_3,
} fe_code_rate_t;
@@ -195,6 +197,7 @@ typedef enum fe_transmit_mode {
TRANSMISSION_MODE_32K,
TRANSMISSION_MODE_C1,
TRANSMISSION_MODE_C3780,
TRANSMISSION_MODE_64K,
} fe_transmit_mode_t;
#if defined(__DVB_CORE__) || !defined (__KERNEL__)
@@ -376,8 +379,9 @@ struct dvb_frontend_event {
#define DTV_STAT_TOTAL_BLOCK_COUNT 69
#define DTV_INPUT 70
#define DTV_PLS 71
#define DTV_MAX_COMMAND DTV_INPUT
#define DTV_MAX_COMMAND DTV_PLS
typedef enum fe_pilot {
PILOT_ON,
@@ -452,6 +456,7 @@ enum atscmh_rs_code_mode {
};
#define NO_STREAM_ID_FILTER (~0U)
#define NO_SCRAMBLING_CODE (~0U)
#define LNA_AUTO (~0U)
struct dtv_cmds_h {

View File

@@ -50,6 +50,11 @@ struct dvb_nsd_ts {
__u16 section_id;
};
struct dvb_ns_cap {
__u8 streams_max;
__u8 reserved[127];
};
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
#define NS_START _IO('o', 193)
#define NS_STOP _IO('o', 194)
@@ -66,4 +71,6 @@ struct dvb_nsd_ts {
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
#define NS_SET_CI _IOW('o', 204, __u8)
#define NS_GET_CAP _IOR('o', 204, struct dvb_ns_cap))
#endif /*_UAPI_DVBNS_H_*/

View File

@@ -26,6 +26,10 @@
#include <linux/compiler.h>
#ifndef __user
#define __user
#endif
typedef enum {
// All functions return -2 on "not open"
OSD_Close=1, // ()

View File

@@ -30,6 +30,10 @@
#include <time.h>
#endif
#ifndef __user
#define __user
#endif
typedef enum {
VIDEO_FORMAT_4_3, /* Select 4:3 format */
VIDEO_FORMAT_16_9, /* Select 16:9 format. */