struct cx24123_state
{
struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
const struct cx24123_config* config;
struct dvb_frontend frontend;
u32 lastber;
u16 snr;
+ u8 lnbreg;
/* Some PLL specifics for tuning */
u32 VCAarg;
return 0;
}
+static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ /* fixme: put the intersil addr int the config */
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if (debug>1)
+ printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
+ __FUNCTION__,reg, data);
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ /* cache the write, no way to read back */
+ state->lnbreg = data;
+
+ return 0;
+}
+
static int cx24123_readreg(struct cx24123_state* state, u8 reg)
{
int ret;
return b1[0];
}
+static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
+{
+ return state->lnbreg;
+}
+
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
u8 nom_reg = cx24123_readreg(state, 0x0e);
u8 pll_mult;
/* check if symbol rate is within limits */
- if ((srate > state->frontend.ops.info.symbol_rate_max) ||
- (srate < state->frontend.ops.info.symbol_rate_min))
+ if ((srate > state->ops.info.symbol_rate_max) ||
+ (srate < state->ops.info.symbol_rate_min))
return -EOPNOTSUPP;;
/* choose the sampling rate high enough for the required operation,
ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
- if (adiv == 0 && ndiv > 0)
- ndiv--;
+ if (adiv == 0)
+ ndiv++;
/* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
+
+ /* Configure the LNB for 14V */
+ if (state->config->use_isl6421)
+ cx24123_writelnbreg(state, 0x0, 0x2a);
+
return 0;
}
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
- val = cx24123_readreg(state, 0x29) & ~0x40;
+ switch (state->config->use_isl6421) {
- switch (voltage) {
- case SEC_VOLTAGE_13:
- dprintk("%s: setting voltage 13V\n", __FUNCTION__);
- return cx24123_writereg(state, 0x29, val & 0x7f);
- case SEC_VOLTAGE_18:
- dprintk("%s: setting voltage 18V\n", __FUNCTION__);
- return cx24123_writereg(state, 0x29, val | 0x80);
- default:
- return -EINVAL;
- };
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__);
+ return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
+ case SEC_VOLTAGE_18:
+ dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__);
+ return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
+ case SEC_VOLTAGE_OFF:
+ dprintk("%s: isl5421 voltage off\n",__FUNCTION__);
+ return cx24123_writelnbreg(state, 0x0, val & 0x30);
+ default:
+ return -EINVAL;
+ };
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_18:
+ dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ case SEC_VOLTAGE_OFF:
+ dprintk("%s: setting voltage off\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 0);
+ return 0;
+ default:
+ return -EINVAL;
+ };
+ }
return 0;
}
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
struct cx24123_state *state = fe->demodulator_priv;
- int i, val, tone;
+ int i, val;
dprintk("%s:\n",__FUNCTION__);
- /* stop continuous tone if enabled */
- tone = cx24123_readreg(state, 0x29);
- if (tone & 0x10)
- cx24123_writereg(state, 0x29, tone & ~0x50);
+ /* check if continuous tone has been stopped */
+ if (state->config->use_isl6421)
+ val = cx24123_readlnbreg(state, 0x00) & 0x10;
+ else
+ val = cx24123_readreg(state, 0x29) & 0x10;
+
+
+ if (val) {
+ printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
+ return -ENOTSUPP;
+ }
/* wait for diseqc queue ready */
cx24123_wait_for_diseqc(state);
/* select tone mode */
- cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
+ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
for (i = 0; i < cmd->msg_len; i++)
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
/* wait for diseqc message to finish sending */
cx24123_wait_for_diseqc(state);
- /* restart continuous tone if enabled */
- if (tone & 0x10) {
- cx24123_writereg(state, 0x29, tone & ~0x40);
- }
-
return 0;
}
static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
struct cx24123_state *state = fe->demodulator_priv;
- int val, tone;
+ int val;
dprintk("%s:\n", __FUNCTION__);
- /* stop continuous tone if enabled */
- tone = cx24123_readreg(state, 0x29);
- if (tone & 0x10)
- cx24123_writereg(state, 0x29, tone & ~0x50);
+ /* check if continuous tone has been stoped */
+ if (state->config->use_isl6421)
+ val = cx24123_readlnbreg(state, 0x00) & 0x10;
+ else
+ val = cx24123_readreg(state, 0x29) & 0x10;
+
+
+ if (val) {
+ printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
+ return -ENOTSUPP;
+ }
- /* wait for diseqc queue ready */
cx24123_wait_for_diseqc(state);
/* select tone mode */
- cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
- msleep(30);
+ val = cx24123_readreg(state, 0x2a) & 0xf8;
+ cx24123_writereg(state, 0x2a, val | 0x04);
+
val = cx24123_readreg(state, 0x29);
+
if (burst == SEC_MINI_A)
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
else if (burst == SEC_MINI_B)
return -EINVAL;
cx24123_wait_for_diseqc(state);
- cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
- /* restart continuous tone if enabled */
- if (tone & 0x10) {
- cx24123_writereg(state, 0x29, tone & ~0x40);
- }
return 0;
}
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
- /* wait for diseqc queue ready */
- cx24123_wait_for_diseqc(state);
+ switch (state->config->use_isl6421) {
+ case 1:
- val = cx24123_readreg(state, 0x29) & ~0x40;
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: isl6421 sec tone on\n",__FUNCTION__);
+ return cx24123_writelnbreg(state, 0x0, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: isl6421 sec tone off\n",__FUNCTION__);
+ return cx24123_writelnbreg(state, 0x0, val & 0x2f);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
- switch (tone) {
- case SEC_TONE_ON:
- dprintk("%s: setting tone on\n", __FUNCTION__);
- return cx24123_writereg(state, 0x29, val | 0x10);
- case SEC_TONE_OFF:
- dprintk("%s: setting tone off\n",__FUNCTION__);
- return cx24123_writereg(state, 0x29, val & 0xef);
- default:
- printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
- return -EINVAL;
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n",__FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
}
return 0;
/* setup the state */
state->config = config;
state->i2c = i2c;
+ memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
state->lastber = 0;
state->snr = 0;
+ state->lnbreg = 0;
state->VCAarg = 0;
state->VGAarg = 0;
state->bandselectarg = 0;
}
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;