diff mbox

[2/2,media] ngene: add support for Terratec Cynergy 2400i, Dual DVB-T

Message ID 5015A230.4020502@sfr.fr (mailing list archive)
State New, archived
Headers show

Commit Message

Patrice Chotard July 29, 2012, 8:50 p.m. UTC
[media] ngene: add support for Terratec Cynergy 2400i
 Dual DVB-T

This code is based on ngene initial check-in
(dae52d009fc950b5c209260d50fcc000f5becd3c)

Signed-off-by: Patrice Chotard <patricechotard@free.fr>
---
 drivers/media/dvb/ngene/ngene-cards.c |  263
+++++++++++++++++++++++++++++++++
 1 files changed, 263 insertions(+), 0 deletions(-)

+
 /****************************************************************************/
 /* Switch control (I2C gates, etc.)
*****************************************/
 /****************************************************************************/
@@ -463,6 +694,37 @@ static struct ngene_info ngene_info_m780 = {
 	.fw_version	= 15,
 };

+static struct drxd_config fe_terratec_dvbt_0 = {
+	.index          = 0,
+	.demod_address  = 0x70,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
+	.clock          = 20000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_terratec_dvbt_1 = {
+	.index          = 1,
+	.demod_address  = 0x71,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
+	.clock          = 20000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_terratec = {
+	.type           = NGENE_TERRATEC,
+	.name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
+	.i2c_access     = 1,
+};
+
 /****************************************************************************/


@@ -487,6 +749,7 @@ static const struct pci_device_id ngene_id_tbl[]
__devinitdata = {
 	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
 	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
 	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
+	NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
 	{0}
 };
 MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Mauro Carvalho Chehab July 31, 2012, 3:31 a.m. UTC | #1
Em 29-07-2012 17:50, Patrice Chotard escreveu:
> [media] ngene: add support for Terratec Cynergy 2400i
>   Dual DVB-T

Sorry, but the patch got line wrapped. Please re-send this patch series.

Thanks!
Mauro
> 
> This code is based on ngene initial check-in
> (dae52d009fc950b5c209260d50fcc000f5becd3c)
> 
> Signed-off-by: Patrice Chotard <patricechotard@free.fr>
> ---
>   drivers/media/dvb/ngene/ngene-cards.c |  263
> +++++++++++++++++++++++++++++++++
>   1 files changed, 263 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/media/dvb/ngene/ngene-cards.c
> b/drivers/media/dvb/ngene/ngene-cards.c
> index 7539a5d..08c610f 100644
> --- a/drivers/media/dvb/ngene/ngene-cards.c
> +++ b/drivers/media/dvb/ngene/ngene-cards.c
> @@ -42,6 +42,8 @@
>   #include "mt2131.h"
>   #include "tda18271c2dd.h"
>   #include "drxk.h"
> +#include "drxd.h"
> +#include "dvb-pll.h"
> 
> 
>   /****************************************************************************/
> @@ -312,6 +314,235 @@ static int demod_attach_lg330x(struct
> ngene_channel *chan)
>   	return (chan->fe) ? 0 : -ENODEV;
>   }
> 
> +static int demod_attach_drxd(struct ngene_channel *chan)
> +{
> +	struct drxd_config *feconf;
> +
> +	feconf = chan->dev->card_info->fe_config[chan->number];
> +
> +	chan->fe = dvb_attach(drxd_attach, feconf, chan,
> +			&chan->i2c_adapter, &chan->dev->pci_dev->dev);
> +	if (!chan->fe) {
> +		pr_err("No DRXD found!\n");
> +		return -ENODEV;
> +	}
> +
> +	if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
> +			&chan->i2c_adapter,
> +			feconf->pll_type)) {
> +		pr_err("No pll(%d) found!\n", feconf->pll_type);
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +
> +/****************************************************************************/
> +/* EEPROM TAGS
> **************************************************************/
> +/****************************************************************************/
> +
> +#define MICNG_EE_START      0x0100
> +#define MICNG_EE_END        0x0FF0
> +
> +#define MICNG_EETAG_END0    0x0000
> +#define MICNG_EETAG_END1    0xFFFF
> +
> +/* 0x0001 - 0x000F reserved for housekeeping */
> +/* 0xFFFF - 0xFFFE reserved for housekeeping */
> +
> +/* Micronas assigned tags
> +   EEProm tags for hardware support */
> +
> +#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
> +#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
> +
> +#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
> +#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
> +
> +/* Tag range for OEMs */
> +
> +#define MICNG_EETAG_OEM_FIRST  0xC000
> +#define MICNG_EETAG_OEM_LAST   0xFFEF
> +
> +static int i2c_write_eeprom(struct i2c_adapter *adapter,
> +			    u8 adr, u16 reg, u8 data)
> +{
> +	u8 m[3] = {(reg >> 8), (reg & 0xff), data};
> +	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
> +			      .len = sizeof(m)};
> +
> +	if (i2c_transfer(adapter, &msg, 1) != 1) {
> +		pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int i2c_read_eeprom(struct i2c_adapter *adapter,
> +			   u8 adr, u16 reg, u8 *data, int len)
> +{
> +	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 = data, .len = len} };
> +
> +	if (i2c_transfer(adapter, msgs, 2) != 2) {
> +		pr_err(DEVICE_NAME ": Error reading EEPROM\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int ReadEEProm(struct i2c_adapter *adapter,
> +		      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
> +{
> +	int status = 0;
> +	u16 Addr = MICNG_EE_START, Length, tag = 0;
> +	u8  EETag[3];
> +
> +	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
> +		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
> +			return -1;
> +		tag = (EETag[0] << 8) | EETag[1];
> +		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
> +			return -1;
> +		if (tag == Tag)
> +			break;
> +		Addr += sizeof(u16) + 1 + EETag[2];
> +	}
> +	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
> +		pr_err(DEVICE_NAME
> +		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
> +		       tag, EETag[2]);
> +		return -1;
> +	}
> +	Length = EETag[2];
> +	if (Length > MaxLen)
> +		Length = (u16) MaxLen;
> +	if (Length > 0) {
> +		Addr += sizeof(u16) + 1;
> +		status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
> +		if (!status) {
> +			*pLength = EETag[2];
> +			if (Length < EETag[2])
> +				; /*status=STATUS_BUFFER_OVERFLOW; */
> +		}
> +	}
> +	return status;
> +}
> +
> +static int WriteEEProm(struct i2c_adapter *adapter,
> +		       u16 Tag, u32 Length, u8 *data)
> +{
> +	int status = 0;
> +	u16 Addr = MICNG_EE_START;
> +	u8 EETag[3];
> +	u16 tag = 0;
> +	int retry, i;
> +
> +	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
> +		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
> +			return -1;
> +		tag = (EETag[0] << 8) | EETag[1];
> +		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
> +			return -1;
> +		if (tag == Tag)
> +			break;
> +		Addr += sizeof(u16) + 1 + EETag[2];
> +	}
> +	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
> +		pr_err(DEVICE_NAME
> +		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
> +		       tag, EETag[2]);
> +		return -1;
> +	}
> +
> +	if (Length > EETag[2])
> +		return -EINVAL;
> +	/* Note: We write the data one byte at a time to avoid
> +	   issues with page sizes. (which are different for
> +	   each manufacture and eeprom size)
> +	 */
> +	Addr += sizeof(u16) + 1;
> +	for (i = 0; i < Length; i++, Addr++) {
> +		status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
> +
> +		if (status)
> +			break;
> +
> +		/* Poll for finishing write cycle */
> +		retry = 10;
> +		while (retry) {
> +			u8 Tmp;
> +
> +			msleep(50);
> +			status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
> +			if (status)
> +				break;
> +			if (Tmp != data[i])
> +				pr_err(DEVICE_NAME
> +				       "eeprom write error\n");
> +			retry -= 1;
> +		}
> +		if (status) {
> +			pr_err(DEVICE_NAME
> +			       ": Timeout polling eeprom\n");
> +			break;
> +		}
> +	}
> +	return status;
> +}
> +
> +static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16
> *data)
> +{
> +	int stat;
> +	u8 buf[2];
> +	u32 len = 0;
> +
> +	stat = ReadEEProm(adapter, tag, 2, buf, &len);
> +	if (stat)
> +		return stat;
> +	if (len != 2)
> +		return -EINVAL;
> +
> +	*data = (buf[0] << 8) | buf[1];
> +	return 0;
> +}
> +
> +static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag,
> u16 data)
> +{
> +	int stat;
> +	u8 buf[2];
> +
> +	buf[0] = data >> 8;
> +	buf[1] = data & 0xff;
> +	stat = WriteEEProm(adapter, tag, 2, buf);
> +	if (stat)
> +		return stat;
> +	return 0;
> +}
> +
> +static s16 osc_deviation(void *priv, s16 deviation, int flag)
> +{
> +	struct ngene_channel *chan = priv;
> +	struct i2c_adapter *adap = &chan->i2c_adapter;
> +	u16 data = 0;
> +
> +	if (flag) {
> +		data = (u16) deviation;
> +		pr_info(DEVICE_NAME ": write deviation %d\n",
> +		       deviation);
> +		eeprom_write_ushort(adap, 0x1000 + chan->number, data);
> +	} else {
> +		if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
> +			data = 0;
> +		pr_info(DEVICE_NAME ": read deviation %d\n",
> +		       (s16) data);
> +	}
> +
> +	return (s16) data;
> +}
> +
>   /****************************************************************************/
>   /* Switch control (I2C gates, etc.)
> *****************************************/
>   /****************************************************************************/
> @@ -463,6 +694,37 @@ static struct ngene_info ngene_info_m780 = {
>   	.fw_version	= 15,
>   };
> 
> +static struct drxd_config fe_terratec_dvbt_0 = {
> +	.index          = 0,
> +	.demod_address  = 0x70,
> +	.demod_revision = 0xa2,
> +	.demoda_address = 0x00,
> +	.pll_address    = 0x60,
> +	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
> +	.clock          = 20000,
> +	.osc_deviation  = osc_deviation,
> +};
> +
> +static struct drxd_config fe_terratec_dvbt_1 = {
> +	.index          = 1,
> +	.demod_address  = 0x71,
> +	.demod_revision = 0xa2,
> +	.demoda_address = 0x00,
> +	.pll_address    = 0x60,
> +	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
> +	.clock          = 20000,
> +	.osc_deviation  = osc_deviation,
> +};
> +
> +static struct ngene_info ngene_info_terratec = {
> +	.type           = NGENE_TERRATEC,
> +	.name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
> +	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
> +	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
> +	.fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
> +	.i2c_access     = 1,
> +};
> +
>   /****************************************************************************/
> 
> 
> @@ -487,6 +749,7 @@ static const struct pci_device_id ngene_id_tbl[]
> __devinitdata = {
>   	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
>   	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
>   	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
> +	NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
>   	{0}
>   };
>   MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/dvb/ngene/ngene-cards.c
b/drivers/media/dvb/ngene/ngene-cards.c
index 7539a5d..08c610f 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -42,6 +42,8 @@ 
 #include "mt2131.h"
 #include "tda18271c2dd.h"
 #include "drxk.h"
+#include "drxd.h"
+#include "dvb-pll.h"


 /****************************************************************************/
@@ -312,6 +314,235 @@  static int demod_attach_lg330x(struct
ngene_channel *chan)
 	return (chan->fe) ? 0 : -ENODEV;
 }

+static int demod_attach_drxd(struct ngene_channel *chan)
+{
+	struct drxd_config *feconf;
+
+	feconf = chan->dev->card_info->fe_config[chan->number];
+
+	chan->fe = dvb_attach(drxd_attach, feconf, chan,
+			&chan->i2c_adapter, &chan->dev->pci_dev->dev);
+	if (!chan->fe) {
+		pr_err("No DRXD found!\n");
+		return -ENODEV;
+	}
+
+	if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
+			&chan->i2c_adapter,
+			feconf->pll_type)) {
+		pr_err("No pll(%d) found!\n", feconf->pll_type);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/****************************************************************************/
+/* EEPROM TAGS
**************************************************************/
+/****************************************************************************/
+
+#define MICNG_EE_START      0x0100
+#define MICNG_EE_END        0x0FF0
+
+#define MICNG_EETAG_END0    0x0000
+#define MICNG_EETAG_END1    0xFFFF
+
+/* 0x0001 - 0x000F reserved for housekeeping */
+/* 0xFFFF - 0xFFFE reserved for housekeeping */
+
+/* Micronas assigned tags
+   EEProm tags for hardware support */
+
+#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
+#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
+
+#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
+#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
+
+/* Tag range for OEMs */
+
+#define MICNG_EETAG_OEM_FIRST  0xC000
+#define MICNG_EETAG_OEM_LAST   0xFFEF
+
+static int i2c_write_eeprom(struct i2c_adapter *adapter,
+			    u8 adr, u16 reg, u8 data)
+{
+	u8 m[3] = {(reg >> 8), (reg & 0xff), data};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
+			      .len = sizeof(m)};
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int i2c_read_eeprom(struct i2c_adapter *adapter,
+			   u8 adr, u16 reg, u8 *data, int len)
+{
+	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 = data, .len = len} };
+
+	if (i2c_transfer(adapter, msgs, 2) != 2) {
+		pr_err(DEVICE_NAME ": Error reading EEPROM\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int ReadEEProm(struct i2c_adapter *adapter,
+		      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START, Length, tag = 0;
+	u8  EETag[3];
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		pr_err(DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+	Length = EETag[2];
+	if (Length > MaxLen)
+		Length = (u16) MaxLen;
+	if (Length > 0) {
+		Addr += sizeof(u16) + 1;
+		status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
+		if (!status) {
+			*pLength = EETag[2];
+			if (Length < EETag[2])
+				; /*status=STATUS_BUFFER_OVERFLOW; */
+		}
+	}
+	return status;
+}
+
+static int WriteEEProm(struct i2c_adapter *adapter,
+		       u16 Tag, u32 Length, u8 *data)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START;
+	u8 EETag[3];
+	u16 tag = 0;
+	int retry, i;
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		pr_err(DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+
+	if (Length > EETag[2])
+		return -EINVAL;
+	/* Note: We write the data one byte at a time to avoid
+	   issues with page sizes. (which are different for
+	   each manufacture and eeprom size)
+	 */
+	Addr += sizeof(u16) + 1;
+	for (i = 0; i < Length; i++, Addr++) {
+		status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
+
+		if (status)
+			break;
+
+		/* Poll for finishing write cycle */
+		retry = 10;
+		while (retry) {
+			u8 Tmp;
+
+			msleep(50);
+			status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
+			if (status)
+				break;
+			if (Tmp != data[i])
+				pr_err(DEVICE_NAME
+				       "eeprom write error\n");
+			retry -= 1;
+		}
+		if (status) {
+			pr_err(DEVICE_NAME
+			       ": Timeout polling eeprom\n");
+			break;
+		}
+	}
+	return status;
+}
+
+static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16
*data)
+{
+	int stat;
+	u8 buf[2];
+	u32 len = 0;
+
+	stat = ReadEEProm(adapter, tag, 2, buf, &len);
+	if (stat)
+		return stat;
+	if (len != 2)
+		return -EINVAL;
+
+	*data = (buf[0] << 8) | buf[1];
+	return 0;
+}
+
+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag,
u16 data)
+{
+	int stat;
+	u8 buf[2];
+
+	buf[0] = data >> 8;
+	buf[1] = data & 0xff;
+	stat = WriteEEProm(adapter, tag, 2, buf);
+	if (stat)
+		return stat;
+	return 0;
+}
+
+static s16 osc_deviation(void *priv, s16 deviation, int flag)
+{
+	struct ngene_channel *chan = priv;
+	struct i2c_adapter *adap = &chan->i2c_adapter;
+	u16 data = 0;
+
+	if (flag) {
+		data = (u16) deviation;
+		pr_info(DEVICE_NAME ": write deviation %d\n",
+		       deviation);
+		eeprom_write_ushort(adap, 0x1000 + chan->number, data);
+	} else {
+		if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
+			data = 0;
+		pr_info(DEVICE_NAME ": read deviation %d\n",
+		       (s16) data);
+	}
+
+	return (s16) data;
+}