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

Commit fec528b7 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] Add initial support for Terratec H5



Not working yet. There are some fixes at the DRX-K that are needed
for it to work.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 39624f7e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ config VIDEO_EM28XX_DVB
	select DVB_S921 if !DVB_FE_CUSTOMISE
	select DVB_DRXD if !DVB_FE_CUSTOMISE
	select DVB_CXD2820R if !DVB_FE_CUSTOMISE
	select DVB_DRXK if !DVB_FE_CUSTOMISE
	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
	select VIDEOBUF_DVB
	---help---
	  This adds support for DVB cards based on the
+37 −0
Original line number Diff line number Diff line
@@ -300,6 +300,23 @@ static struct em28xx_reg_seq pctv_290e[] = {
	{-1,			-1,	-1,		-1},
};

#if 0
static struct em28xx_reg_seq terratec_h5_gpio[] = {
	{EM28XX_R08_GPIO,	0xff,	0xff,	10},
	{EM2874_R80_GPIO,	0xf6,	0xff,	100},
	{EM2874_R80_GPIO,	0xf2,	0xff,	50},
	{EM2874_R80_GPIO,	0xf6,	0xff,	50},
	{ -1,			-1,	-1,	-1},
};

static struct em28xx_reg_seq terratec_h5_digital[] = {
	{EM2874_R80_GPIO,	0xf6,	0xff,	10},
	{EM2874_R80_GPIO,	0xe6,	0xff,	100},
	{EM2874_R80_GPIO,	0xa6,	0xff,	10},
	{ -1,			-1,	-1,	-1},
};
#endif

/*
 *  Board definitions
 */
@@ -843,6 +860,19 @@ struct em28xx_board em28xx_boards[] = {
			.gpio     = terratec_cinergy_USB_XS_FR_analog,
		} },
	},
	[EM2884_BOARD_TERRATEC_H5] = {
		.name         = "Terratec Cinergy H5",
		.has_dvb      = 1,
#if 0
		.tuner_type   = TUNER_PHILIPS_TDA8290,
		.tuner_addr   = 0x41,
		.dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
		.tuner_gpio   = terratec_h5_gpio,
#endif
		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
				EM28XX_I2C_CLK_WAIT_ENABLE |
				EM28XX_I2C_FREQ_400_KHZ,
	},
	[EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
		.name         = "Hauppauge WinTV HVR 900",
		.tda9887_conf = TDA9887_PRESENT,
@@ -1855,6 +1885,8 @@ struct usb_device_id em28xx_id_table[] = {
			.driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
	{ USB_DEVICE(0x0ccd, 0x0043),
			.driver_info = EM2870_BOARD_TERRATEC_XS },
	{ USB_DEVICE(0x0ccd, 0x10a2),
			.driver_info = EM2884_BOARD_TERRATEC_H5 },
	{ USB_DEVICE(0x0ccd, 0x0047),
			.driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
	{ USB_DEVICE(0x0ccd, 0x0084),
@@ -2840,6 +2872,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
			em28xx_info("chip ID is em2882/em2883\n");
			dev->wait_after_write = 0;
			break;
		case CHIP_ID_EM2884:
			em28xx_info("chip ID is em2884\n");
			dev->reg_gpio_num = EM2874_R80_GPIO;
			dev->wait_after_write = 0;
			break;
		default:
			em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
		}
+6 −2
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
{
	return em28xx_write_regs(dev, reg, &val, 1);
}
EXPORT_SYMBOL_GPL(em28xx_write_reg);

/*
 * em28xx_write_reg_bits()
@@ -618,7 +619,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
{
	int rc;

	if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
	if (dev->chip_id == CHIP_ID_EM2874 ||
	    dev->chip_id == CHIP_ID_EM2884 ||
	    dev->chip_id == CHIP_ID_EM28174) {
		/* The Transport Stream Enable Register moved in em2874 */
		if (!start) {
			rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
@@ -887,6 +890,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
	}
	return rc;
}
EXPORT_SYMBOL_GPL(em28xx_gpio_set);

int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
{
@@ -1111,7 +1115,7 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
	unsigned int chip_cfg2;
	unsigned int packet_size = 564;

	if (dev->chip_id == CHIP_ID_EM2874) {
	if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM2884) {
		/* FIXME - for now assume 564 like it was before, but the
		   em2874 code should be added to return the proper value... */
		packet_size = 564;
+109 −1
Original line number Diff line number Diff line
/*
 DVB device driver for em28xx

 (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
 (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>

 (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
	- Fixes for the driver to properly work with HVR-950
@@ -40,6 +40,8 @@
#include "s921.h"
#include "drxd.h"
#include "cxd2820r.h"
#include "tda18271c2dd.h"
#include "drxk.h"

MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -73,6 +75,10 @@ struct em28xx_dvb {
	struct dmx_frontend        fe_hw;
	struct dmx_frontend        fe_mem;
	struct dvb_net             net;

	/* Due to DRX-D - probably need changes */
	int (*gate_ctrl)(struct dvb_frontend *, int);
	struct semaphore      pll_mutex;
};


@@ -295,6 +301,78 @@ static struct drxd_config em28xx_drxd = {
	.disable_i2c_gate_ctrl = 1,
};

#define TERRATEC_H5_DRXK_I2C_ADDR	0x29

struct drxk_config terratec_h5_drxk = {
	.adr = 0x29,
};

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

	if (!dvb)
		return -EINVAL;

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

static void terratec_h5_init(struct em28xx *dev)
{
	int i;
	struct em28xx_reg_seq terratec_h5_init[] = {
		{EM28XX_R08_GPIO,	0xff,	0xff,	10},
		{EM2874_R80_GPIO,	0xf6,	0xff,	100},
		{EM2874_R80_GPIO,	0xf2,	0xff,	50},
		{EM2874_R80_GPIO,	0xf6,	0xff,	100},
		{ -1,                   -1,     -1,     -1},
	};
	struct em28xx_reg_seq terratec_h5_end[] = {
		{EM2874_R80_GPIO,	0xe6,	0xff,	100},
		{EM2874_R80_GPIO,	0xa6,	0xff,	50},
		{EM2874_R80_GPIO,	0xe6,	0xff,	100},
		{ -1,                   -1,     -1,     -1},
	};
	struct {
		unsigned char r[4];
		int len;
	} regs[] = {
		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
		{{ 0x01, 0x02 }, 2},
		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
		{{ 0x01, 0x00 }, 2},
		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
		{{ 0x01, 0x00 }, 2},
		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
		{{ 0x04, 0x00 }, 2},
		{{ 0x00, 0x04 }, 2},
		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
		{{ 0x04, 0x14 }, 2},
		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
	};

	em28xx_gpio_set(dev, terratec_h5_init);
	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
	msleep(10);
	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
	msleep(10);

	dev->i2c_client.addr = 0x82 >> 1;

	for (i = 0; i < ARRAY_SIZE(regs); i++)
		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
	em28xx_gpio_set(dev, terratec_h5_end);
};

static int mt352_terratec_xs_init(struct dvb_frontend *fe)
{
	/* Values extracted from a USB trace of the Terratec Windows driver */
@@ -688,6 +766,36 @@ static int dvb_init(struct em28xx *dev)
				/* leave FE 0 still active */
			}
		}
		break;
	case EM2884_BOARD_TERRATEC_H5:
		terratec_h5_init(dev);

		/* dvb->fe[1] will be DVB-C, and dvb->fe[0] will be DVB-T */
		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]);
		if (!dvb->fe[0] || !dvb->fe[1]) {
			result = -EINVAL;
			goto out_free;
		}
		/* FIXME: do we need a pll semaphore? */
		dvb->fe[0]->sec_priv = dvb;
		sema_init(&dvb->pll_mutex, 1);
		dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
		dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
		dvb->fe[1]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
		dvb->fe[1]->id = 1;

		/* Attach tda18271 */
		if (dvb->fe[0]->ops.i2c_gate_ctrl)
			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
		if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
			result = -EINVAL;
			goto out_free;
		}
		if (dvb->fe[0]->ops.i2c_gate_ctrl)
			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
		if (dvb->fe[1]->ops.i2c_gate_ctrl)
			dvb->fe[1]->ops.i2c_gate_ctrl(dvb->fe[1], 1);

		break;
	default:
		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
+3 −1
Original line number Diff line number Diff line
@@ -330,7 +330,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
	struct em28xx_eeprom *em_eeprom = (void *)eedata;
	int i, err, size = len, block;

	if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM28174) {
	if (dev->chip_id == CHIP_ID_EM2874 ||
	    dev->chip_id == CHIP_ID_EM28174 ||
	    dev->chip_id == CHIP_ID_EM2884) {
		/* Empia switched to a 16-bit addressable eeprom in newer
		   devices.  While we could certainly write a routine to read
		   the eeprom, there is nothing of use in there that cannot be
Loading