mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
V4L/DVB (4012): Fix cx24123 diseqc
Rework diseqc support to be more in line with the other demod drivers. Fix Nova-S-Plus/Nova-SE2 diseqc. Cleanup API. Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
9a10655ffa
commit
cd20ca9f19
@ -48,7 +48,6 @@ struct cx24123_state
|
||||
|
||||
u32 lastber;
|
||||
u16 snr;
|
||||
u8 lnbreg;
|
||||
|
||||
/* Some PLL specifics for tuning */
|
||||
u32 VCAarg;
|
||||
@ -249,29 +248,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
|
||||
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;
|
||||
@ -295,11 +271,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
|
||||
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);
|
||||
@ -687,10 +658,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
|
||||
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
|
||||
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
|
||||
|
||||
/* Configure the LNB for 14V */
|
||||
if (state->config->use_isl6421)
|
||||
cx24123_writelnbreg(state, 0x0, 0x2a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -699,50 +666,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
switch (state->config->use_isl6421) {
|
||||
val = cx24123_readreg(state, 0x29) & ~0x40;
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
dprintk("%s: setting voltage 13V\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val | 0x80);
|
||||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: setting voltage 18V\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val & 0x7f);
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -763,27 +698,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
|
||||
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;
|
||||
int i, val, tone;
|
||||
|
||||
dprintk("%s:\n",__FUNCTION__);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* stop continuous tone if enabled */
|
||||
tone = cx24123_readreg(state, 0x29);
|
||||
if (tone & 0x10)
|
||||
cx24123_writereg(state, 0x29, tone & ~0x50);
|
||||
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
|
||||
|
||||
for (i = 0; i < cmd->msg_len; i++)
|
||||
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
|
||||
@ -794,36 +722,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
|
||||
/* 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;
|
||||
int val, tone;
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* stop continuous tone if enabled */
|
||||
tone = cx24123_readreg(state, 0x29);
|
||||
if (tone & 0x10)
|
||||
cx24123_writereg(state, 0x29, tone & ~0x50);
|
||||
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
/* select tone mode */
|
||||
val = cx24123_readreg(state, 0x2a) & 0xf8;
|
||||
cx24123_writereg(state, 0x2a, val | 0x04);
|
||||
|
||||
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
|
||||
msleep(30);
|
||||
val = cx24123_readreg(state, 0x29);
|
||||
|
||||
if (burst == SEC_MINI_A)
|
||||
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
|
||||
else if (burst == SEC_MINI_B)
|
||||
@ -832,7 +757,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
|
||||
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;
|
||||
}
|
||||
|
||||
@ -973,38 +903,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
switch (state->config->use_isl6421) {
|
||||
case 1:
|
||||
/* wait for diseqc queue ready */
|
||||
cx24123_wait_for_diseqc(state);
|
||||
|
||||
val = cx24123_readlnbreg(state, 0x0);
|
||||
val = cx24123_readreg(state, 0x29) & ~0x40;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@ -1040,7 +953,6 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
||||
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;
|
||||
|
@ -28,17 +28,8 @@ struct cx24123_config
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/*
|
||||
cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
|
||||
for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
|
||||
from register 0x29 of the CX24123 demodulator
|
||||
*/
|
||||
int use_isl6421;
|
||||
|
||||
/* Need to set device param for start_dma */
|
||||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
|
||||
void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
||||
|
@ -61,6 +61,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
|
||||
select DVB_LGDT330X
|
||||
select DVB_NXT200X
|
||||
select DVB_CX24123
|
||||
select DVB_ISL6421
|
||||
---help---
|
||||
This builds cx88-dvb with all currently supported frontend
|
||||
demodulators. If you wish to tweak your configuration, and
|
||||
@ -139,6 +140,7 @@ config VIDEO_CX88_DVB_CX24123
|
||||
default y
|
||||
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
|
||||
select DVB_CX24123
|
||||
select DVB_ISL6421
|
||||
---help---
|
||||
This adds DVB-S support for cards based on the
|
||||
Connexant 2388x chip and the CX24123 demodulator.
|
||||
|
@ -59,6 +59,7 @@
|
||||
#ifdef HAVE_CX24123
|
||||
# include "cx24123.h"
|
||||
#endif
|
||||
#include "isl6421.h"
|
||||
|
||||
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
|
||||
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
|
||||
@ -479,28 +480,30 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
|
||||
static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct cx88_core *core = dev->core;
|
||||
|
||||
if (on)
|
||||
cx_write(MO_GP0_IO, 0x000006f9);
|
||||
else
|
||||
if (voltage == SEC_VOLTAGE_OFF) {
|
||||
cx_write(MO_GP0_IO, 0x000006fB);
|
||||
} else {
|
||||
cx_write(MO_GP0_IO, 0x000006f9);
|
||||
}
|
||||
|
||||
if (core->prev_set_voltage)
|
||||
return core->prev_set_voltage(fe, voltage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cx24123_config hauppauge_novas_config = {
|
||||
.demod_address = 0x55,
|
||||
.use_isl6421 = 1,
|
||||
.set_ts_params = cx24123_set_ts_param,
|
||||
};
|
||||
|
||||
static struct cx24123_config kworld_dvbs_100_config = {
|
||||
.demod_address = 0x15,
|
||||
.use_isl6421 = 0,
|
||||
.set_ts_params = cx24123_set_ts_param,
|
||||
.enable_lnb_voltage = cx24123_enable_lnb_voltage,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -710,10 +713,17 @@ static int dvb_register(struct cx8802_dev *dev)
|
||||
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
|
||||
dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, 0x08, 0x00, 0x00);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_KWORLD_DVBS_100:
|
||||
dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->core->prev_set_voltage = dev->dvb.frontend->ops->set_voltage;
|
||||
dev->dvb.frontend->ops->set_voltage = kworld_dvbs_100_set_voltage;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -298,6 +298,7 @@ struct cx88_core {
|
||||
/* config info -- dvb */
|
||||
struct dvb_pll_desc *pll_desc;
|
||||
unsigned int pll_addr;
|
||||
int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
||||
|
||||
/* state info */
|
||||
struct task_struct *kthread;
|
||||
|
Loading…
Reference in New Issue
Block a user