Commit 9ca9efb0 authored by Ralph Metzler's avatar Ralph Metzler Committed by Mauro Carvalho Chehab
Browse files

[media] ngene: Support Digital Devices DuoFlex CT



Support Digital Devices DuoFlex CT with ngene.

Signed-off-by: default avatarRalph Metzler <rmetzler@digitaldevices.de>
Signed-off-by: default avatarOliver Endriss <o.endriss@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent f9004df7
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,8 @@ config DVB_NGENE
	select DVB_STV6110x if !DVB_FE_CUSTOMISE
	select DVB_STV6110x if !DVB_FE_CUSTOMISE
	select DVB_STV090x if !DVB_FE_CUSTOMISE
	select DVB_STV090x if !DVB_FE_CUSTOMISE
	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
	select DVB_DRXK if !DVB_FE_CUSTOMISE
	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
	---help---
	---help---
	  Support for Micronas PCI express cards with nGene bridge.
	  Support for Micronas PCI express cards with nGene bridge.
+138 −38
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@
#include "lnbh24.h"
#include "lnbh24.h"
#include "lgdt330x.h"
#include "lgdt330x.h"
#include "mt2131.h"
#include "mt2131.h"
#include "drxk.h"




/****************************************************************************/
/****************************************************************************/
@@ -83,6 +84,52 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
}
}




static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
{
	struct ngene_channel *chan = fe->sec_priv;
	int status;

	if (enable) {
		down(&chan->dev->pll_mutex);
		status = chan->gate_ctrl(fe, 1);
	} else {
		status = chan->gate_ctrl(fe, 0);
		up(&chan->dev->pll_mutex);
	}
	return status;
}

struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
					 struct i2c_adapter *i2c, u8 adr);

static int tuner_attach_tda18271(struct ngene_channel *chan)
{
	struct i2c_adapter *i2c;
	struct dvb_frontend *fe;

	i2c = &chan->dev->channel[0].i2c_adapter;
	if (chan->fe->ops.i2c_gate_ctrl)
		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
	if (chan->fe->ops.i2c_gate_ctrl)
		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
	if (!fe) {
		printk("No TDA18271 found!\n");
		return -ENODEV;
	}

	return 0;
}

static int tuner_attach_probe(struct ngene_channel *chan)
{
	if (chan->demod_type == 0)
		return tuner_attach_stv6110(chan);
	if (chan->demod_type == 1)
		return tuner_attach_tda18271(chan);
	return -EINVAL;
}

static int demod_attach_stv0900(struct ngene_channel *chan)
static int demod_attach_stv0900(struct ngene_channel *chan)
{
{
	struct i2c_adapter *i2c;
	struct i2c_adapter *i2c;
@@ -130,6 +177,60 @@ static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
		up(&chan->dev->pll_mutex);
		up(&chan->dev->pll_mutex);
}
}


static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
{
	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
				   .buf  = val,  .len   = 1 }};
	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
}

static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
			  u16 reg, u8 *val)
{
	u8 msg[2] = {reg>>8, reg&0xff};
	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
				   .buf  = msg, .len   = 2},
				  {.addr = adr, .flags = I2C_M_RD,
				   .buf  = val, .len   = 1}};
	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
}

static int port_has_stv0900(struct i2c_adapter *i2c, int port)
{
	u8 val;
	if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
		return 0;
	return 1;
}

static int port_has_drxk(struct i2c_adapter *i2c, int port)
{
	u8 val;

	if (i2c_read(i2c, 0x29+port, &val) < 0)
		return 0;
	printk("DRXK@%02x\n", 0x29+port);
	return 1;
}

static int demod_attach_drxk(struct ngene_channel *chan,
			     struct i2c_adapter *i2c)
{
	struct dvb_frontend *fe;

	chan->fe = fe = dvb_attach(drxk_attach,
				   i2c, 0x29 + (chan->number^2),
				   &chan->fe2);
	if (!chan->fe) {
		printk("No DRXK found!\n");
		return -ENODEV;
	}
	fe->sec_priv = chan;
	chan->gate_ctrl = fe->ops.i2c_gate_ctrl;
	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
	return 0;
}

static int cineS2_probe(struct ngene_channel *chan)
static int cineS2_probe(struct ngene_channel *chan)
{
{
	struct i2c_adapter *i2c;
	struct i2c_adapter *i2c;
@@ -144,26 +245,20 @@ static int cineS2_probe(struct ngene_channel *chan)
	else
	else
		i2c = &chan->dev->channel[1].i2c_adapter;
		i2c = &chan->dev->channel[1].i2c_adapter;


	if (port_has_stv0900(i2c, chan->number)) {
		chan->demod_type=0;
		fe_conf = chan->dev->card_info->fe_config[chan->number];
		fe_conf = chan->dev->card_info->fe_config[chan->number];
	i2c_msg.addr = fe_conf->address;

	/* probe demod */
	i2c_msg.len = 2;
	buf[0] = 0xf1;
	buf[1] = 0x00;
	rc = i2c_transfer(i2c, &i2c_msg, 1);
	if (rc != 1)
		return -ENODEV;

		/* demod found, attach it */
		/* demod found, attach it */
		rc = demod_attach_stv0900(chan);
		rc = demod_attach_stv0900(chan);
		if (rc < 0 || chan->number < 2)
		if (rc < 0 || chan->number < 2)
			return rc;
			return rc;
  
  
		/* demod #2: reprogram outputs DPN1 & DPN2 */
		/* demod #2: reprogram outputs DPN1 & DPN2 */
		i2c_msg.addr = fe_conf->address;
		i2c_msg.len = 3;
		i2c_msg.len = 3;
		buf[0] = 0xf1;
		buf[0] = 0xf1;
	switch (chan->number) {
		switch (chan->number)
		{
		case 2:
		case 2:
			buf[1] = 0x5c;
			buf[1] = 0x5c;
			buf[2] = 0xc2;
			buf[2] = 0xc2;
@@ -180,7 +275,12 @@ static int cineS2_probe(struct ngene_channel *chan)
			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
			return -EIO;
			return -EIO;
		}
		}

	} else if (port_has_drxk(i2c, chan->number^2)) {
		chan->demod_type=1;
		demod_attach_drxk(chan, i2c);
	} else {
		printk("No demod found on chan %d\n", chan->number);
	}
	return 0;
	return 0;
}
}


@@ -337,7 +437,7 @@ static struct ngene_info ngene_info_duoFlexS2 = {
	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
			   NGENE_IO_TSOUT},
			   NGENE_IO_TSOUT},
	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
	.tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
	.tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
+13 −2
Original line number Original line Diff line number Diff line
@@ -41,7 +41,7 @@


#include "ngene.h"
#include "ngene.h"


static int one_adapter = 1;
static int one_adapter = 0;
module_param(one_adapter, int, 0444);
module_param(one_adapter, int, 0444);
MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
MODULE_PARM_DESC(one_adapter, "Use only one adapter.");


@@ -461,7 +461,7 @@ static u8 TSFeatureDecoderSetup[8 * 5] = {
	0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
	0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
	0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXH */
	0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXH */
	0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXHser */
	0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXHser */
	0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* S2ser */
	0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* S2ser */
	0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
	0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
};
};


@@ -1443,6 +1443,9 @@ static void release_channel(struct ngene_channel *chan)
		chan->ci_dev = NULL;
		chan->ci_dev = NULL;
	}
	}


	if (chan->fe2) {
		dvb_unregister_frontend(chan->fe2);
	}
	if (chan->fe) {
	if (chan->fe) {
		dvb_unregister_frontend(chan->fe);
		dvb_unregister_frontend(chan->fe);
		dvb_frontend_detach(chan->fe);
		dvb_frontend_detach(chan->fe);
@@ -1534,6 +1537,14 @@ static int init_channel(struct ngene_channel *chan)
			goto err;
			goto err;
		chan->has_demux = true;
		chan->has_demux = true;
	}
	}
	if (chan->fe2) {
		if (dvb_register_frontend(adapter, chan->fe2) < 0)
			goto err;
			chan->fe2->tuner_priv=chan->fe->tuner_priv;
			memcpy(&chan->fe2->ops.tuner_ops,
			       &chan->fe->ops.tuner_ops,
			       sizeof(struct dvb_tuner_ops));
	}


	if (chan->has_demux) {
	if (chan->has_demux) {
		ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
		ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+3 −0
Original line number Original line Diff line number Diff line
@@ -641,8 +641,11 @@ struct ngene_channel {
	int                   mode;
	int                   mode;
	bool                  has_adapter;
	bool                  has_adapter;
	bool                  has_demux;
	bool                  has_demux;
	int                   demod_type;
	int (*gate_ctrl)(struct dvb_frontend *, int);


	struct dvb_frontend  *fe;
	struct dvb_frontend  *fe;
	struct dvb_frontend  *fe2;
	struct dmxdev         dmxdev;
	struct dmxdev         dmxdev;
	struct dvb_demux      demux;
	struct dvb_demux      demux;
	struct dvb_net        dvbnet;
	struct dvb_net        dvbnet;