Commit e82f2130 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] dvb: Update DVB frontend drivers

From: Michael Hunold <hunold@linuxtv.org>

alps_tdmb7, cx24110: use correct delay values, don't divide by HZ when using
dvb_delay(), found by Artur Skawina

alps_tdmb7: set FE_HAS_LOCK only when all low-order bits are valid

mt312: patch for the mt312 module, targeting the VP310: reduced heat,
implement "auto" inversion mode, remove debugging verbosity, add module
parameter for debugging (Augusto Cardoso)

nxt6000: code review and beautification, use per i2c-adapater void pointer
for private data in nxt_attach() / nxt_detach, fix frontend private data
handling.  patch by Mikael Rosbacke <rosbacke at nada.kth.se>

sp887x: firmware loader implementation contributed by Martin Stubbs, C99
comile fixes by Wolfgang Thiel

stv0299: Added new module parameter to choose between BER and UCBLOCKs error
monitoring since the STV0299 can't do both at once, Added modifications based
on the recommended settings in the SU1278 datasheet.

tda1004x: remove FE_CAN_INVERSION_AUTO

ves1820:completed nokia board support, increased some delays to get constant
results,set default pwm value to 0x48 for boards which don't have an eeprom
(by Andreas Oberritter)
parent 6aa4eec6
......@@ -159,7 +159,7 @@ static int cx22700_init (struct dvb_i2c_bus *i2c)
cx22700_writereg (i2c, 0x00, 0x02); /* soft reset */
cx22700_writereg (i2c, 0x00, 0x00);
dvb_delay (HZ/100);
dvb_delay(10);
for (i=0; i<sizeof(init_tab); i+=2)
cx22700_writereg (i2c, init_tab[i], init_tab[i+1]);
......@@ -281,15 +281,15 @@ static int cx22700_get_tps (struct dvb_i2c_bus *i2c, struct dvb_ofdm_parameters
val = cx22700_readreg (i2c, 0x02);
if ((val >> 3) > 4)
if (((val >> 3) & 0x07) > 4)
p->code_rate_HP = FEC_AUTO;
else
p->code_rate_HP = fec_tab[val >> 3];
p->code_rate_HP = fec_tab[(val >> 3) & 0x07];
if ((val & 0x7) > 4)
if ((val & 0x07) > 4)
p->code_rate_LP = FEC_AUTO;
else
p->code_rate_LP = fec_tab[val >> 3];
p->code_rate_LP = fec_tab[val & 0x07];
val = cx22700_readreg (i2c, 0x03);
......@@ -333,7 +333,7 @@ static int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
if (sync & 0x10)
*status |= FE_HAS_SYNC;
if (sync & 0x10)
if (*status == 0x0f)
*status |= FE_HAS_LOCK;
break;
......
......@@ -248,7 +248,7 @@ static int cx24108_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
cx24108_write(i2c,pll);
cx24110_writereg(i2c,0x56,0x7f);
dvb_delay(HZ/10); /* wait a moment for the tuner pll to lock */
dvb_delay(10); /* wait a moment for the tuner pll to lock */
/* tuner pll lock can be monitored on GPIO pin 4 of cx24110 */
while (!(cx24110_readreg(i2c,0x66)&0x20)&&i<1000)
......
......@@ -39,11 +39,19 @@
#define MT312_DEBUG 0
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
#define MT312_PLL_CLK 10000000UL /* 10 MHz */
/* number of active frontends */
static int mt312_count = 0;
#if MT312_DEBUG == 0
#define dprintk(x...)
#else
static int debug = 0;
#define dprintk if(debug == 1) printk
#endif
static struct dvb_frontend_info mt312_info = {
.name = "Zarlink MT312",
.type = FE_QPSK,
......@@ -86,7 +94,7 @@ static int mt312_read(struct dvb_i2c_bus *i2c,
return -EREMOTEIO;
}
#if MT312_DEBUG
{
if(debug) {
int i;
printk(KERN_INFO "R(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
......@@ -107,7 +115,7 @@ static int mt312_write(struct dvb_i2c_bus *i2c,
struct i2c_msg msg;
#if MT312_DEBUG
{
if(debug) {
int i;
printk(KERN_INFO "W(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
......@@ -205,7 +213,7 @@ static int sl1935_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
if (freq < 1550000)
buf[3] |= 0x10;
printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
buf[1], buf[2], buf[3]);
return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf));
......@@ -225,7 +233,7 @@ static int tsa5059_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
if (freq < 1550000)
buf[3] |= 0x02;
printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
buf[1], buf[2], buf[3]);
return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf));
......@@ -236,13 +244,13 @@ static int mt312_reset(struct dvb_i2c_bus *i2c, const u8 full)
return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40);
}
static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
static int mt312_init(struct dvb_i2c_bus *i2c, const long id, u8 pll)
{
int ret;
u8 buf[2];
/* wake up */
if ((ret = mt312_writereg(i2c, CONFIG, 0x8c)) < 0)
if ((ret = mt312_writereg(i2c, CONFIG, (pll == 60 ? 0x88 : 0x8c))) < 0)
return ret;
/* wait at least 150 usec */
......@@ -252,8 +260,17 @@ static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
if ((ret = mt312_reset(i2c, 1)) < 0)
return ret;
// Per datasheet, write correct values. 09/28/03 ACCJr.
// If we don't do this, we won't get FE_HAS_VITERBI in the VP310.
{
u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00};
if ((ret = mt312_write(i2c, VIT_SETUP, buf_def, sizeof(buf_def))) < 0)
return ret;
}
/* SYS_CLK */
buf[0] = mt312_div(MT312_SYS_CLK * 2, 1000000);
buf[0] = mt312_div((pll == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000);
/* DISEQC_RATIO */
buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
......@@ -370,16 +387,18 @@ static int mt312_set_voltage(struct dvb_i2c_bus *i2c, const fe_sec_voltage_t v)
return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]);
}
static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t * s)
static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s, const long id)
{
int ret;
u8 status[3];
u8 status[3], vit_mode;
*s = 0;
if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0)
return ret;
dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
if (status[0] & 0xc0)
*s |= FE_HAS_SIGNAL; /* signal noise ratio */
if (status[0] & 0x04)
......@@ -390,6 +409,16 @@ static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t * s)
*s |= FE_HAS_SYNC; /* byte align lock */
if (status[0] & 0x01)
*s |= FE_HAS_LOCK; /* qpsk lock */
// VP310 doesn't have AUTO, so we "implement it here" ACCJr
if ((id == ID_VP310) && !(status[0] & 0x01)) {
if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0)
return ret;
vit_mode ^= 0x40;
if ((ret = mt312_writereg(i2c, VIT_MODE, vit_mode)) < 0)
return ret;
if ((ret = mt312_writereg(i2c, GO, 0x01)) < 0)
return ret;
}
return 0;
}
......@@ -422,7 +451,7 @@ static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 * signal_strength)
*signal_strength = agc;
printk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
dprintk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
return 0;
}
......@@ -458,7 +487,7 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
const long id)
{
int ret;
u8 buf[5];
u8 buf[5], config_val;
u16 sr;
const u8 fec_tab[10] =
......@@ -467,6 +496,8 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr);
dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
if ((p->frequency < mt312_info.frequency_min)
|| (p->frequency > mt312_info.frequency_max))
return -EINVAL;
......@@ -489,6 +520,22 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
switch (id) {
case ID_VP310:
// For now we will do this only for the VP310.
// It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
if ((ret = mt312_readreg(i2c, CONFIG, &config_val) < 0))
return ret;
if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
{
if ((config_val & 0x0c) == 0x08) //We are running 60MHz
if ((ret = mt312_init(i2c, id, (u8) 90)) < 0)
return ret;
}
else
{
if ((config_val & 0x0c) == 0x0C) //We are running 90MHz
if ((ret = mt312_init(i2c, id, (u8) 60)) < 0)
return ret;
}
set_tv_freq = tsa5059_set_tv_freq;
break;
case ID_MT312:
......@@ -562,7 +609,7 @@ static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 * sr)
monitor = (buf[0] << 8) | buf[1];
printk(KERN_DEBUG "sr(auto) = %u\n",
dprintk(KERN_DEBUG "sr(auto) = %u\n",
mt312_div(monitor * 15625, 4));
} else {
if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0)
......@@ -578,9 +625,9 @@ static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 * sr)
sym_rat_op = (buf[0] << 8) | buf[1];
printk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
sym_rat_op, dec_ratio);
printk(KERN_DEBUG "*sr(manual) = %lu\n",
dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
(((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
}
......@@ -675,7 +722,7 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
return -EOPNOTSUPP;
case FE_READ_STATUS:
return mt312_read_status(i2c, arg);
return mt312_read_status(i2c, arg, (long) fe->data);
case FE_READ_BER:
return mt312_read_bercnt(i2c, arg);
......@@ -702,7 +749,12 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
return mt312_sleep(i2c);
case FE_INIT:
return mt312_init(i2c, (long) fe->data);
//For the VP310 we should run at 60MHz when ever possible.
//It should be better to run the mt312 ar lower speed when ever possible, but tunning will be slower. ACCJr 09/29/03
if ((long)fe->data == ID_MT312)
return mt312_init(i2c, (long) fe->data, (u8) 90);
else
return mt312_init(i2c, (long) fe->data, (u8) 60);
case FE_RESET:
return mt312_reset(i2c, 0);
......@@ -755,6 +807,11 @@ static void __exit mt312_module_exit(void)
module_init(mt312_module_init);
module_exit(mt312_module_exit);
#if MT312_DEBUG != 0
MODULE_PARM(debug,"i");
MODULE_PARM_DESC(debug, "enable verbose debug messages");
#endif
MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver");
MODULE_AUTHOR("Andreas Oberritter <obi@saftware.de>");
MODULE_LICENSE("GPL");
......@@ -55,34 +55,21 @@ static struct dvb_frontend_info nxt6000_info = {
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.notifier_delay = 0,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
};
#pragma pack(1)
struct nxt6000_config {
u8 demod_addr;
u8 tuner_addr;
u8 tuner_type;
u8 clock_inversion;
};
#pragma pack()
#define TUNER_TYPE_ALP510 0
#define TUNER_TYPE_SP5659 1
#define TUNER_TYPE_SP5730 2
#define FE2NXT(fe) ((struct nxt6000_config *)&(fe->data))
#define FE2NXT(fe) ((struct nxt6000_config *)((fe)->data))
#define FREQ2DIV(freq) ((freq + 36166667) / 166667)
#define dprintk if (debug) printk
......@@ -116,8 +103,10 @@ static u8 nxt6000_read(struct dvb_i2c_bus *i2c, u8 addr, u8 reg)
int ret;
u8 b0[] = {reg};
u8 b1[] = {0};
struct i2c_msg msgs[] = {{.addr = addr >> 1, .flags = 0, .buf = b0, .len = 1},
{.addr = addr >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1}};
struct i2c_msg msgs[] = {
{.addr = addr >> 1,.flags = 0,.buf = b0,.len = 1},
{.addr = addr >> 1,.flags = I2C_M_RD,.buf = b1,.len = 1}
};
ret = i2c->xfer(i2c, msgs, 2);
......@@ -394,7 +383,7 @@ static void nxt6000_setup(struct dvb_frontend *fe)
nxt6000_writereg(fe, OFDM_ITB_FREQ_1, 0x06);
nxt6000_writereg(fe, OFDM_ITB_FREQ_2, 0x31);
nxt6000_writereg(fe, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
nxt6000_writereg(fe, CAS_FREQ, 0xBB); // CHECKME
nxt6000_writereg(fe, CAS_FREQ, 0xBB); /* CHECKME */
nxt6000_writereg(fe, OFDM_SYR_CTL, 1 << 2);
nxt6000_writereg(fe, OFDM_PPM_CTL_1, PPM256);
nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, 0x49);
......@@ -414,20 +403,20 @@ static void nxt6000_setup(struct dvb_frontend *fe)
static void nxt6000_dump_status(struct dvb_frontend *fe)
{
u8 val;
// printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
// printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
// printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
// printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
// printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
// printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
// printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
// printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
// printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
// printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
/*
printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
*/
printk("NXT6000 status:");
val = nxt6000_readreg(fe, RS_COR_STAT);
......@@ -460,13 +449,11 @@ static void nxt6000_dump_status(struct dvb_frontend *fe)
break;
case 0x03:
printk(" VITERBI CODERATE: 5/6,");
break;
case 0x04:
printk(" VITERBI CODERATE: 7/8,");
break;
default:
......@@ -503,13 +490,11 @@ static void nxt6000_dump_status(struct dvb_frontend *fe)
break;
case 0x04:
printk(" CoreState: WAIT_PPM,");
break;
case 0x01:
printk(" CoreState: WAIT_TRL,");
break;
case 0x05:
......@@ -586,13 +571,11 @@ static void nxt6000_dump_status(struct dvb_frontend *fe)
break;
case 0x03:
printk(" TPSLP: 5/6,");
break;
case 0x04:
printk(" TPSLP: 7/8,");
break;
default:
......@@ -622,13 +605,11 @@ static void nxt6000_dump_status(struct dvb_frontend *fe)
break;
case 0x03:
printk(" TPSHP: 5/6,");
break;
case 0x04:
printk(" TPSHP: 7/8,");
break;
default:
......@@ -669,7 +650,7 @@ static void nxt6000_dump_status(struct dvb_frontend *fe)
}
// Strange magic required to gain access to RF_AGC_STATUS
/* Strange magic required to gain access to RF_AGC_STATUS */
nxt6000_readreg(fe, RF_AGC_VAL_1);
val = nxt6000_readreg(fe, RF_AGC_STATUS);
val = nxt6000_readreg(fe, RF_AGC_STATUS);
......@@ -735,21 +716,23 @@ static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_READ_SIGNAL_STRENGTH:
{
// s16 *signal = (s16 *)arg;
// *signal=(((signed char)readreg(client, 0x16))+128)<<8;
s16 *signal = (s16 *) arg;
/*
*signal=(((signed char)readreg(client, 0x16))+128)<<8;
*/
*signal = 0;
return 0;
}
case FE_READ_SNR:
{
// s16 *snr = (s16 *)arg;
// *snr=readreg(client, 0x24)<<8;
// *snr|=readreg(client, 0x25);
s16 *snr = (s16 *) arg;
/*
*snr=readreg(client, 0x24)<<8;
*snr|=readreg(client, 0x25);
*/
*snr = 0;
break;
}
......@@ -831,70 +814,74 @@ static u8 demod_addr_tbl[] = {0x14, 0x18, 0x24, 0x28};
static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data)
{
u8 addr_nr;
u8 fe_count = 0;
struct nxt6000_config nxt;
struct nxt6000_config *pnxt;
dprintk("nxt6000: attach\n");
pnxt = kmalloc(sizeof(demod_addr_tbl)*sizeof(struct nxt6000_config), GFP_KERNEL);
if (NULL == pnxt) {
dprintk("nxt6000: no memory for private data.\n");
return -ENOMEM;
}
*data = pnxt;
for (addr_nr = 0; addr_nr < sizeof(demod_addr_tbl); addr_nr++) {
struct nxt6000_config *nxt = &pnxt[addr_nr];
if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE)
continue;
if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) {
nxt->tuner_addr = 0xC0;
nxt->tuner_type = TUNER_TYPE_ALP510;
nxt->clock_inversion = 1;
nxt.tuner_addr = 0xC0;
nxt.tuner_type = TUNER_TYPE_ALP510;
nxt.clock_inversion = 1;
dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt.tuner_addr);
dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr);
} else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC2, NULL, 0) == 0) {
nxt->tuner_addr = 0xC2;
nxt->tuner_type = TUNER_TYPE_SP5659;
nxt->clock_inversion = 0;
nxt.tuner_addr = 0xC2;
nxt.tuner_type = TUNER_TYPE_SP5659;
nxt.clock_inversion = 0;
dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt.tuner_addr);
dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr);
} else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) {
nxt->tuner_addr = 0xC0;
nxt->tuner_type = TUNER_TYPE_SP5730;
nxt->clock_inversion = 0;
nxt.tuner_addr = 0xC0;
nxt.tuner_type = TUNER_TYPE_SP5730;
nxt.clock_inversion = 0;
dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt.tuner_addr);
dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt->tuner_addr);
} else {
printk("nxt6000: unable to detect tuner\n");
continue;
}
nxt.demod_addr = demod_addr_tbl[addr_nr];
nxt->demod_addr = demod_addr_tbl[addr_nr];
dprintk("nxt6000: attached at %d:%d\n", i2c->adapter->num, i2c->id);
dvb_register_frontend(nxt6000_ioctl, i2c, (void *)(*((u32 *)&nxt)), &nxt6000_info);
dvb_register_frontend(nxt6000_ioctl, i2c, (void *)nxt, &nxt6000_info);
fe_count++;
}
return (fe_count > 0) ? 0 : -ENODEV;
if (fe_count == 0) {
kfree(pnxt);
return -ENODEV;
}
return 0;
}
static void nxt6000_detach(struct dvb_i2c_bus *i2c, void *data)
{
struct nxt6000_config *pnxt = (struct nxt6000_config *)data;
dprintk("nxt6000: detach\n");
dvb_unregister_frontend(nxt6000_ioctl, i2c);
kfree(pnxt);
}
static __init int nxt6000_init(void)
......
/**********************************************************************/
* DRV6000reg.H
/*
* Public Include File for DRV6000 users
* (ie. NxtWave Communications - NXT6000 demodulator driver)
*
* Copyright (C) 2001 NxtWave Communications, Inc.
*
* $Log: nxt6000.h,v $
* Revision 1.2 2003/01/27 12:32:42 fschirmer
* Lots of bugfixes and new features
*
* Revision 1.1 2003/01/21 18:43:09 fschirmer
* Nxt6000 based frontend driver
*
* Revision 1.1 2003/01/03 02:25:45 obi
* alps tdme7 driver
*
*
* Rev 1.10 Jun 12 2002 11:28:02 dkoeger
* Updated for SA in GUi work
*
* Rev 1.9 Apr 01 2002 10:38:46 dkoeger
* Updated for 1.0.31 GUI
*
* Rev 1.8 Mar 11 2002 10:04:56 dkoeger
* Updated for 1.0.31 GUI version
*
* Rev 1.5 Dec 07 2001 14:40:40 dkoeger
* Updated for 1.0.28 GUI
*
* Rev 1.4 Nov 13 2001 11:09:00 dkoeger
* No change.
*
* Rev 1.3 Aug 23 2001 14:21:02 dkoeger
* Updated for driver version 2.1.9
*
* Rev 1.2 Jul 09 2001 09:20:04 dkoeger
* Updated for 1.0.18
*
* Rev 1.1 Jun 13 2001 16:14:24 dkoeger
* Updated to reflect NXT6000 GUI BETA 1.0.11 6/13/2001
**********************************************************************/
*/
/* Nxt6000 Register Addresses and Bit Masks */
......
/*
Driver for the Microtune 7202D Frontend
*/
/*
This driver needs a copy of the Avermedia firmware. The version tested
is part of the Avermedia DVB-T 1.3.26.3 Application. If the software is
installed in Windows the file will be in the /Program Files/AVerTV DVB-T/
directory and is called sc_main.mc. Alternatively it can "extracted" from
the install cab files. Copy this file to /etc/dvb/sc_main.mc.
With this version of the file the first 10 bytes are discarded and the
next 0x4000 loaded. This may change in future versions.
*/
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/unistd.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "dvb_functions.h"
#ifndef DVB_SP887X_FIRMWARE_FILE
#define DVB_SP887X_FIRMWARE_FILE "/etc/dvb/sc_main.mc"
#endif
static char *sp887x_firmware = DVB_SP887X_FIRMWARE_FILE;
#if 0
#define dprintk(x...) printk(x)
......@@ -39,7 +67,7 @@ struct dvb_frontend_info sp887x_info = {
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_RECOVER
};
static int errno;
static
int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
......@@ -112,6 +140,7 @@ u16 sp887x_readreg (struct dvb_frontend *fe, u16 reg)
static
void sp887x_microcontroller_stop (struct dvb_frontend *fe)
{
dprintk("%s\n", __FUNCTION__);
sp887x_writereg(fe, 0xf08, 0x000);
sp887x_writereg(fe, 0xf09, 0x000);
......@@ -123,6 +152,7 @@ void sp887x_microcontroller_stop (struct dvb_frontend *fe)
static
void sp887x_microcontroller_start (struct dvb_frontend *fe)
{
dprintk("%s\n", __FUNCTION__);
sp887x_writereg(fe, 0xf08, 0x000);
sp887x_writereg(fe, 0xf09, 0x000);
......@@ -135,6 +165,7 @@ static
void sp887x_setup_agc (struct dvb_frontend *fe)
{
/* setup AGC parameters */
dprintk("%s\n", __FUNCTION__);
sp887x_writereg(fe, 0x33c, 0x054);
sp887x_writereg(fe, 0x33b, 0x04c);
sp887x_writereg(fe, 0x328, 0x000);
......@@ -152,8 +183,6 @@ void sp887x_setup_agc (struct dvb_frontend *fe)
}
#include "sp887x_firm.h"
#define BLOCKSIZE 30
/**
......@@ -162,14 +191,63 @@ void sp887x_setup_agc (struct dvb_frontend *fe)
static
int sp887x_initial_setup (struct dvb_frontend *fe)
{
u8 buf [BLOCKSIZE];
u8 buf [BLOCKSIZE+2];
unsigned char *firmware = NULL;
int i;
int fd;
int filesize;
int fw_size;
mm_segment_t fs;
dprintk("%s\n", __FUNCTION__);
/* soft reset */
sp887x_writereg(fe, 0xf1a, 0x000);
sp887x_microcontroller_stop (fe);
fs = get_fs();
// Load the firmware
set_fs(get_ds());
fd = open(sp887x_firmware, 0, 0);
if (fd < 0) {
printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,
sp887x_firmware);
return -EIO;
}
filesize = lseek(fd, 0L, 2);
if (filesize <= 0) {
printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,
sp887x_firmware);
sys_close(fd);
return -EIO;
}
fw_size = 0x4000;
// allocate buffer for it
firmware = vmalloc(fw_size);
if (firmware == NULL) {
printk(KERN_WARNING "%s: Out of memory loading firmware\n",
__FUNCTION__);
sys_close(fd);
return -EIO;
}
// read it!
// read the first 16384 bytes from the file
// ignore the first 10 bytes
lseek(fd, 10, 0);
if (read(fd, firmware, fw_size) != fw_size) {
printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);
vfree(firmware);
sys_close(fd);
return -EIO;
}
sys_close(fd);
set_fs(fs);
printk ("%s: firmware upload... ", __FUNCTION__);
/* setup write pointer to -1 (end of memory) */
......@@ -179,12 +257,12 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
/* dummy write (wrap around to start of memory) */
sp887x_writereg(fe, 0x8f0a, 0x0000);
for (i=0; i<sizeof(sp887x_firm); i+=BLOCKSIZE) {
for (i=0; i<fw_size; i+=BLOCKSIZE) {
int c = BLOCKSIZE;
int err;
if (i+c > sizeof(sp887x_firm))
c = sizeof(sp887x_firm) - i;
if (i+c > fw_size)
c = fw_size - i;
/* bit 0x8000 in address is set to enable 13bit mode */
/* bit 0x4000 enables multibyte read/write transfers */
......@@ -192,15 +270,18 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
buf[0] = 0xcf;
buf[1] = 0x0a;
memcpy(&buf[2], &sp887x_firm[i], c);
memcpy(&buf[2], firmware + i, c);
if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) {
printk ("failed.\n");
printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
vfree(firmware);
return err;
}
}
vfree(firmware);
/* don't write RS bytes between packets */
sp887x_writereg(fe, 0xc13, 0x001);
......
This diff is collapsed.
......@@ -108,7 +108,7 @@ static struct dvb_frontend_info tda10045h_info = {
.frequency_min = 51000000,
.frequency_max = 858000000,
.frequency_stepsize = 166667,
.caps = FE_CAN_INVERSION_AUTO |
.caps =
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
......
......@@ -19,6 +19,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
......@@ -70,7 +72,18 @@ static int verbose;
#define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff))
#define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff))
#if defined(CONFIG_DBOX2)
#define XIN 69600000UL
#define DISABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0)
#define ENABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0)
#define HAS_INVERSION(reg0) (reg0 & 0x20)
#else /* PCI cards */
#define XIN 57840000UL
#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0)
#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0)
#define HAS_INVERSION(reg0) (!(reg0 & 0x20))
#endif
#define FIN (XIN >> 4)
......@@ -209,9 +222,9 @@ static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0,
reg0 |= GET_REG0(fe->data) & 0x62;
if (INVERSION_ON == inversion)
reg0 &= ~0x20;
ENABLE_INVERSION(reg0);
else if (INVERSION_OFF == inversion)
reg0 |= 0x20;
DISABLE_INVERSION(reg0);
ves1820_writereg (fe, 0x00, reg0 & 0xfe);
ves1820_writereg (fe, 0x00, reg0 | 0x01);
......@@ -220,7 +233,7 @@ static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0,
* check lock and toggle inversion bit if required...
*/
if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) {
dvb_delay(10);
mdelay(30);
if (!(ves1820_readreg (fe, 0x11) & 0x08)) {
reg0 ^= 0x20;
ves1820_writereg (fe, 0x00, reg0 & 0xfe);
......@@ -242,6 +255,10 @@ static int ves1820_init (struct dvb_frontend *fe)
ves1820_writereg (fe, 0, 0);
#if defined(CONFIG_DBOX2)
ves1820_inittab[2] &= ~0x08;
#endif
for (i=0; i<53; i++)
ves1820_writereg (fe, i, ves1820_inittab[i]);
......@@ -330,6 +347,10 @@ static int ves1820_set_parameters (struct dvb_frontend *fe,
ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion);
/* yes, this speeds things up: userspace reports lock in about 8 ms
instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */
mdelay(30);
return 0;
}
......@@ -419,14 +440,14 @@ static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
fe->i2c->adapter->num, afc,
-((s32)(p->u.qam.symbol_rate >> 3) * afc >> 7));
p->inversion = reg0 & 0x20 ? INVERSION_OFF : INVERSION_ON;
p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF;
p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16;
p->u.qam.fec_inner = FEC_NONE;
p->frequency = ((p->frequency + 31250) / 62500) * 62500;
// To prevent overflow, shift symbol rate first a
// couple of bits.
/* To prevent overflow, shift symbol rate first a
couple of bits. */
p->frequency -= (s32)(p->u.qam.symbol_rate >> 3) * afc >> 7;
break;
}
......@@ -462,8 +483,6 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
printk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num);
} else {
type = -1;
printk ("DVB: VES1820(%d): unknown PLL, "
"please report to <linuxdvb@linuxtv.org>!!\n", i2c->adapter->num);
}
return type;
......@@ -477,13 +496,11 @@ static u8 read_pwm (struct dvb_i2c_bus *i2c)
struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 },
{ .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } };
i2c->xfer (i2c, msg, 2);
if ((i2c->xfer(i2c, msg, 2) != 2) || (pwm == 0xff))
pwm = 0x48;
printk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm);
if (pwm == 0xff)
pwm = 0x48;
return pwm;
}
......@@ -516,8 +533,7 @@ static int ves1820_attach (struct dvb_i2c_bus *i2c, void **data)
if ((demod_addr = probe_demod_addr(i2c)) < 0)
return -ENODEV;
if ((tuner_type = probe_tuner(i2c)) < 0)
return -ENODEV;
tuner_type = probe_tuner(i2c);
if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) {
printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment