1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

Merge branch 'internal'

This commit is contained in:
mvoelkel 2016-08-04 01:00:35 +02:00
commit bb191aa5d7
26 changed files with 4170 additions and 1376 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

@ -145,7 +145,6 @@ int ReadFlash(int ddb, int argc, char *argv[], uint32_t Flags)
}
int FlashDetect(int dev)
{
uint8_t Cmd = 0x9F;
@ -765,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;
@ -1652,6 +1650,60 @@ int lic_erase(int dev, int argc, char* argv[], uint32_t Flags)
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[] =
{
@ -1661,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>" },
@ -1676,6 +1728,7 @@ struct SCommand CommandTable[] =
{ "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

@ -247,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;
@ -257,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;
@ -268,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;
@ -1081,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;
@ -1146,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

@ -201,10 +201,10 @@ static int ns_set_ci(struct dvbnss *nss, u8 ci)
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));
TS_CONTROL(dev->port[ciport].output));
usleep_range(1, 5);
ddbwritel(dev, (input->port->lnr << 21) | (input->nr << 16) | 0x1d,
TS_OUTPUT_CONTROL(ciport));
TS_CONTROL(dev->port[ciport].output));
dns->fe = dev->port[ciport].input[0];
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 °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 °C x 256 (ADM1032 ext)
#define TEMPMON1_SENSOR1 (TEMPMON_BASE + 0x08) // SHORT Temperature in °C x 256 (LM75A 0x90)
#define TEMPMON1_SENSOR2 (TEMPMON_BASE + 0x0C) // SHORT Temperature in °C x 256 (LM75A 0x92 or ADM1032 Int)
// V2 Temperature Monitor 2 ADM1032
#define TEMPMON2_BOARD (TEMPMON_SENSOR0) // SHORT Temperature in °C x 256 (ADM1032 int)
#define TEMPMON2_FPGACORE (TEMPMON_SENSOR1) // SHORT Temperature in °C x 256 (ADM1032 ext)
#define TEMPMON2_QAMCORE (TEMPMON_SENSOR2) // SHORT Temperature in °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,6 +57,34 @@ static void ddb_unmap(struct ddb *dev)
vfree(dev);
}
static void __devexit ddb_irq_disable(struct ddb *dev)
{
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);
#ifdef CONFIG_PCI_MSI
if (dev->msi)
pci_disable_msi(dev->pdev);
#endif
}
static void __devexit ddb_remove(struct pci_dev *pdev)
{
@ -70,16 +97,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
if (dev->link[0].info->ns_num)
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0, INTERRUPT_ENABLE);
ddbwritel(dev, 0, MSI1_ENABLE);
if (dev->msi == 2)
free_irq(dev->pdev->irq + 1, dev);
free_irq(dev->pdev->irq, dev);
#ifdef CONFIG_PCI_MSI
if (dev->msi)
pci_disable_msi(dev->pdev);
#endif
ddb_irq_exit(dev);
ddb_ports_release(dev);
ddb_buffers_free(dev);
@ -93,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;
@ -144,75 +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)
@ -223,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)
@ -256,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",
@ -418,26 +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_ct_8 = {
.type = DDB_OCTOPUS_MAX_CT,
.name = "Digital Devices MAX CT8",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x0f,
.board_control = 0x0ff,
.board_control_2 = 0xf00,
.ts_quirks = TS_QUIRK_SERIAL,
};
static struct ddb_info ddb_mod = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C modulator",
@ -446,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,
};
@ -493,7 +550,16 @@ static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
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),
@ -521,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

@ -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,7 +145,7 @@ struct ddb_ids {
};
struct ddb_info {
int type;
u32 type;
#define DDB_NONE 0
#define DDB_OCTOPUS 1
#define DDB_OCTOPUS_CI 2
@ -148,6 +153,9 @@ struct ddb_info {
#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;
@ -163,6 +171,7 @@ struct ddb_info {
u8 ts_quirks;
#define TS_QUIRK_SERIAL 1
#define TS_QUIRK_REVERSED 2
#define TS_QUIRK_NO_OUTPUT 4
struct ddb_regmap *regmap;
};
@ -171,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
@ -178,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;
@ -242,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;
@ -316,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;
@ -413,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;
@ -436,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)
@ -486,6 +520,7 @@ static inline void gtlw(struct ddb_link *link)
}
#endif
#if 0
static u32 ddblreadl(struct ddb_link *link, u32 adr)
{
if (unlikely(link->nr)) {
@ -519,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)
{
@ -714,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.23"
#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,
};
@ -134,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)
@ -185,9 +185,7 @@ static int __init octonet_probe(struct platform_device *pdev)
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)
@ -236,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)
@ -1174,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 {
@ -1273,18 +1333,20 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr);
static int get_stats(struct dvb_frontend *fe)
{
struct cxd_state *state = fe->demodulator_priv;
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 = 1000 * (s64) (s16) val;
p->strength.stat[0].uvalue = str;
read_snr(fe, &val);
p->cnr.len = 1;
@ -1313,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);
@ -1323,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);
@ -1369,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;
@ -1407,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;
}
@ -1458,7 +1578,7 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct cxd_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 n, d;
u32 n = 0, d = 1;
int s = 0;
*ber = 0;
@ -1504,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)
@ -1780,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;
@ -1907,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);

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,7 +219,8 @@ 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");
@ -247,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;
@ -308,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)
@ -443,8 +447,10 @@ 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)
@ -456,7 +462,8 @@ static int reset_fec_counter(struct mxl *state)
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]);
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
&cmdBuff[0]);
}
static int send_master_cmd(struct dvb_frontend *fe,
@ -517,14 +524,16 @@ 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;
}
@ -634,7 +643,7 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg[8], reg2[4];
u32 reg[8], reg2[4], n = 0, d = 0;
int stat;
*ber = 0;
@ -645,7 +654,8 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(7 * sizeof(u32)),
(u8 *) &reg[0]);
stat = read_register_block(state,
stat = read_register_block(
state,
(HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(4 * sizeof(u32)),
@ -670,9 +680,9 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
default:
break;
}
pr_info("mxl5xx: ber %08x %08x %08x %08x %08x %08x %08x\n",
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_info("mxl5xx: ber2 %08x %08x %08x %08x\n",
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;
@ -755,7 +765,7 @@ static int get_frontend(struct dvb_frontend *fe)
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
pr_info("mxl5xx: freq=%u delsys=%u srate=%u\n",
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];
@ -769,7 +779,8 @@ static int get_frontend(struct dvb_frontend *fe)
case SYS_DSS:
break;
case SYS_DVBS2:
switch ((MXL_HYDRA_PILOTS_E ) regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) {
switch ((MXL_HYDRA_PILOTS_E )
regData[DMD_DVBS2_PILOT_ON_OFF_ADDR]) {
case MXL_HYDRA_PILOTS_OFF:
p->pilot = PILOT_OFF;
break;
@ -780,7 +791,8 @@ static int get_frontend(struct dvb_frontend *fe)
break;
}
case SYS_DVBS:
switch ((MXL_HYDRA_MODULATION_E) regData[DMD_MODULATION_SCHEME_ADDR]) {
switch ((MXL_HYDRA_MODULATION_E)
regData[DMD_MODULATION_SCHEME_ADDR]) {
case MXL_HYDRA_MOD_QPSK:
p->modulation = QPSK;
break;
@ -790,7 +802,8 @@ static int get_frontend(struct dvb_frontend *fe)
default:
break;
}
switch ((MXL_HYDRA_ROLLOFF_E) regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) {
switch ((MXL_HYDRA_ROLLOFF_E)
regData[DMD_SPECTRUM_ROLL_OFF_ADDR]) {
case MXL_HYDRA_ROLLOFF_0_20:
p->rolloff = ROLLOFF_20;
break;
@ -903,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)
@ -929,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;
@ -955,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;
@ -1037,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;
@ -1081,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;
}
@ -1117,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:
@ -1313,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;
@ -1348,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},
@ -1393,7 +1433,8 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
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,
@ -1527,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,
@ -1569,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,6 +36,8 @@
#include "stv090x.h"
#include "stv090x_priv.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
#define ERRCTRL1_DVBS1 0x76
#define ERRCTRL1_DVBS2 0x67
@ -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;
@ -3585,7 +3658,6 @@ 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;
@ -3605,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;
}
@ -3723,6 +3803,9 @@ static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
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
@ -3813,7 +3896,6 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
default:
break;
}
#ifdef DBVALS
*cnr = cnr_db;
#endif
@ -3823,7 +3905,7 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
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;
@ -3921,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;
@ -4032,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 */
@ -4056,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);
@ -4067,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:
@ -4075,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 */
@ -4099,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);
@ -4110,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:
@ -4123,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);
@ -4131,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;
}
@ -4393,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;
@ -4643,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)
@ -4667,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;
@ -4730,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;
@ -4772,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;
@ -4780,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;
@ -4787,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;
@ -4848,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:
@ -4857,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;
@ -4869,7 +5080,69 @@ 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)
{
@ -4960,7 +5233,7 @@ static struct dvb_frontend_ops stv090x_ops = {
.sleep = stv090x_sleep,
.get_frontend_algo = stv090x_frontend_algo,
.get_frontend = get_frontend,
.get_frontend = stv090x_get_frontend,
.diseqc_send_master_cmd = stv090x_send_diseqc_msg,
.diseqc_send_burst = stv090x_send_diseqc_burst,
@ -4976,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)
{
@ -5030,10 +5303,15 @@ 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,

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

@ -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
@ -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 {
@ -193,6 +202,19 @@ static int read_regs(struct stv *state, u16 reg, u8 *val, int len)
reg, val, len);
}
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*/
@ -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,29 +568,6 @@ 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;
}
@ -558,7 +580,7 @@ static s32 TableLookup(struct SLookup *Table,
int i;
s32 RegDiff;
// Assumes Table[0].RegValue > Table[imax].RegValue
/* Assumes Table[0].RegValue > Table[imax].RegValue */
if( RegValue >= Table[0].RegValue )
Value = Table[0].Value;
else if( RegValue <= Table[imax].RegValue )
@ -686,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];
@ -828,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;
@ -844,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;
@ -879,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,
@ -955,7 +1130,7 @@ static int probe(struct stv *state)
/* 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); /* RFAGC Pads Dev = 05 */
@ -964,10 +1139,20 @@ static int probe(struct stv *state)
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 */
@ -1054,12 +1239,31 @@ 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] = {
@ -1118,6 +1322,28 @@ static int get_frontend(struct dvb_frontend *fe)
}
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);
@ -1125,13 +1351,15 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber);
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 DmdState = 0;
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);
@ -1140,24 +1368,42 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
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 = 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);
usleep_range(3000, 4000);
@ -1183,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;
@ -1191,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 */
@ -1203,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;
@ -1230,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;
}
@ -1439,24 +1718,21 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct stv *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 Agc1, Agc0;
u8 Reg[2];
s32 bbgain;
s32 Power = 0;
int i;
read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, Reg, 2);
//KdPrintEx((MSG_INFO "_%d " __FUNCTION__ " AGCIQIN1 = %02x%02x\n",m_Instance,Reg[0],Reg[1]));
*strength = (((u32) Reg[0]) << 8) | Reg[1];
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];
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)
@ -1464,7 +1740,6 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
else
*strength = 0;
printk("pwr = %d bb = %d str = %u\n", Power, bbgain, *strength);
if (bbgain < (s32) *strength)
*strength -= bbgain;
else
@ -1474,6 +1749,7 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
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;
}
@ -1550,6 +1826,7 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
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) {
@ -1586,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

@ -105,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)
{
@ -184,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;
}
@ -299,7 +301,9 @@ static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency)
state->Frequency = Frequency;
#if 0
dump_regs(state);
#endif
return 0;
}
@ -330,39 +334,6 @@ 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;
@ -618,7 +589,6 @@ static struct SLookup Gain_Channel_AGC_IIP3_LookUp[] = {
{ 1325 , 0xFF00 },
};
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static s32 TableLookup(struct SLookup *Table, int TableSize, u16 RegValue)
{

View File

@ -197,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__)
@ -378,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,
@ -454,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. */