Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd20ca9f authored by Andrew de Quincey's avatar Andrew de Quincey Committed by Mauro Carvalho Chehab
Browse files

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: default avatarAndrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 9a10655f
Loading
Loading
Loading
Loading
+48 −136
Original line number Diff line number Diff line
@@ -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) {

	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);
	val = cx24123_readreg(state, 0x29) & ~0x40;

	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;
}
@@ -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,26 +903,10 @@ 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:

		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;
		}

	case 0:
	/* wait for diseqc queue ready */
	cx24123_wait_for_diseqc(state);

		val = cx24123_readreg(state, 0x29);
	val = cx24123_readreg(state, 0x29) & ~0x40;

	switch (tone) {
	case SEC_TONE_ON:
@@ -1005,7 +919,6 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
		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;
+0 −9
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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.
+17 −7
Original line number Diff line number Diff line
@@ -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:
+1 −0
Original line number Diff line number Diff line
@@ -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;