linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] tda18212: add support for slave chip version
@ 2014-07-31 22:33 Antti Palosaari
  2014-07-31 22:33 ` [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard Antti Palosaari
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Antti Palosaari @ 2014-07-31 22:33 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

There is 2 different versions of that chip available, master and
slave. Slave is used only on dual tuner devices with master tuner.
Laser printing top of chip is 18212/M or 18212/S according to chip
version.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/tuners/tda18212.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c
index 05a4ac9..15b09f8 100644
--- a/drivers/media/tuners/tda18212.c
+++ b/drivers/media/tuners/tda18212.c
@@ -306,7 +306,8 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
 {
 	struct tda18212_priv *priv = NULL;
 	int ret;
-	u8 val;
+	u8 chip_id = chip_id;
+	char *version;
 
 	priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
 	if (priv == NULL)
@@ -320,26 +321,38 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
 
 	/* check if the tuner is there */
-	ret = tda18212_rd_reg(priv, 0x00, &val);
+	ret = tda18212_rd_reg(priv, 0x00, &chip_id);
+	dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
-	if (!ret)
-		dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
-	if (ret || val != 0xc7) {
-		kfree(priv);
-		return NULL;
+	if (ret)
+		goto err;
+
+	switch (chip_id) {
+	case 0xc7:
+		version = "M"; /* master */
+		break;
+	case 0x47:
+		version = "S"; /* slave */
+		break;
+	default:
+		goto err;
 	}
 
 	dev_info(&priv->i2c->dev,
-			"%s: NXP TDA18212HN successfully identified\n",
-			KBUILD_MODNAME);
+			"%s: NXP TDA18212HN/%s successfully identified\n",
+			KBUILD_MODNAME, version);
 
 	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
 
 	return fe;
+err:
+	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	kfree(priv);
+	return NULL;
 }
 EXPORT_SYMBOL(tda18212_attach);
 
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard
  2014-07-31 22:33 [PATCH 1/4] tda18212: add support for slave chip version Antti Palosaari
@ 2014-07-31 22:33 ` Antti Palosaari
  2014-09-23 11:39   ` Mauro Carvalho Chehab
  2014-07-31 22:33 ` [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver Antti Palosaari
  2014-07-31 22:33 ` [PATCH 4/4] ddbridge: add support for DVB-C/C2/T/T2 extension card Antti Palosaari
  2 siblings, 1 reply; 7+ messages in thread
From: Antti Palosaari @ 2014-07-31 22:33 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Just add delivery system for DVB-C2 standard. Other parameters
should be added later.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 include/uapi/linux/dvb/frontend.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h
index c56d77c..98648eb 100644
--- a/include/uapi/linux/dvb/frontend.h
+++ b/include/uapi/linux/dvb/frontend.h
@@ -410,6 +410,7 @@ typedef enum fe_delivery_system {
 	SYS_DVBT2,
 	SYS_TURBO,
 	SYS_DVBC_ANNEX_C,
+	SYS_DVBC2,
 } fe_delivery_system_t;
 
 /* backward compatibility */
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver
  2014-07-31 22:33 [PATCH 1/4] tda18212: add support for slave chip version Antti Palosaari
  2014-07-31 22:33 ` [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard Antti Palosaari
@ 2014-07-31 22:33 ` Antti Palosaari
  2014-09-23 11:47   ` Mauro Carvalho Chehab
  2014-07-31 22:33 ` [PATCH 4/4] ddbridge: add support for DVB-C/C2/T/T2 extension card Antti Palosaari
  2 siblings, 1 reply; 7+ messages in thread
From: Antti Palosaari @ 2014-07-31 22:33 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
Driver taken from Digital Devices Linux driver package
dddvb-0.9.15a.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/Kconfig   |    8 +
 drivers/media/dvb-frontends/Makefile  |    1 +
 drivers/media/dvb-frontends/cxd2843.c | 2025 +++++++++++++++++++++++++++++++++
 drivers/media/dvb-frontends/cxd2843.h |   30 +
 4 files changed, 2064 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/cxd2843.c
 create mode 100644 drivers/media/dvb-frontends/cxd2843.h

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index fe0ddcc..5475f59 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -72,6 +72,14 @@ config DVB_SI2165
 
 	  Say Y when you want to support this frontend.
 
+config DVB_CXD2843
+	tristate "Sony CXD2843"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
+	  Say Y when you want to support this frontend.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index edf103d..9a9f131 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
 obj-$(CONFIG_DVB_STV0367) += stv0367.o
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
 obj-$(CONFIG_DVB_SI2165) += si2165.o
diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
new file mode 100644
index 0000000..10fc240
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2843.c
@@ -0,0 +1,2025 @@
+/*
+ * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator.
+ * Also supports the CXD2837ER DVB-T/T2/C and the
+ * CXD2838ER ISDB-T demodulator.
+ *
+ * Copyright (C) 2013-2014 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <linux/mutex.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "cxd2843.h"
+
+#define USE_ALGO 1
+
+enum EDemodType { CXD2843, CXD2837, CXD2838 };
+enum EDemodState { Unknown, Shutdown, Sleep, ActiveT,
+		   ActiveT2, ActiveC, ActiveC2, ActiveIT };
+enum ET2Profile { T2P_Base, T2P_Lite };
+enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC,
+	     OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT };
+
+struct cxd_state {
+	struct dvb_frontend   frontend;
+	struct i2c_adapter   *i2c;
+	struct mutex          mutex;
+
+	u8  adrt;
+	u8  curbankt;
+
+	u8  adrx;
+	u8  curbankx;
+
+	enum EDemodType  type;
+	enum EDemodState state;
+	enum ET2Profile T2Profile;
+	enum omode omode;
+
+	u8    IF_FS;
+	int   ContinuousClock;
+	int   SerialMode;
+	u8    SerialClockFrequency;
+
+	u32   LockTimeout;
+	u32   TSLockTimeout;
+	u32   L1PostTimeout;
+	u32   DataSliceID;
+	int   FirstTimeLock;
+	u32   plp;
+	u32   last_status;
+
+	u32   bandwidth;
+	u32   bw;
+
+	unsigned long tune_time;
+
+	u32   LastBERNominator;
+	u32   LastBERDenominator;
+	u8    BERScaleMax;
+};
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {
+		.addr = adr, .flags = 0, .buf = data, .len = len};
+
+	if (i2c_transfer(adap, &msg, 1) != 1) {
+		pr_err("cxd2843: i2c_write error\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int writeregs(struct cxd_state *state, u8 adr, u8 reg,
+		     u8 *regd, u16 len)
+{
+	u8 data[len + 1];
+
+	data[0] = reg;
+	memcpy(data + 1, regd, len);
+	return i2c_write(state->i2c, adr, data, len + 1);
+}
+
+static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat)
+{
+	u8 mm[2] = {reg, dat};
+
+	return i2c_write(state->i2c, adr, mm, 2);
+}
+
+static int i2c_read(struct i2c_adapter *adap,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
+				     .buf = msg, .len = len},
+				   { .addr = adr, .flags = I2C_M_RD,
+				     .buf = answ, .len = alen } };
+	if (i2c_transfer(adap, msgs, 2) != 2) {
+		pr_err("cxd2843: i2c_read error\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int readregs(struct cxd_state *state, u8 adr, u8 reg,
+		    u8 *val, int count)
+{
+	return i2c_read(state->i2c, adr, &reg, 1, val, count);
+}
+
+static int readregst_unlocked(struct cxd_state *cxd, u8 bank,
+			      u8 Address, u8 *pValue, u16 count)
+{
+	int status = 0;
+
+	if (bank != 0xFF && cxd->curbankt != bank) {
+		status = writereg(cxd, cxd->adrt, 0, bank);
+		if (status < 0) {
+			cxd->curbankt = 0xFF;
+			return status;
+		}
+		cxd->curbankt = bank;
+	}
+	status = readregs(cxd, cxd->adrt, Address, pValue, count);
+	return status;
+}
+
+static int readregst(struct cxd_state *cxd, u8 Bank,
+		     u8 Address, u8 *pValue, u16 count)
+{
+	int status;
+
+	mutex_lock(&cxd->mutex);
+	status = readregst_unlocked(cxd, Bank, Address, pValue, count);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank,
+			      u8 Address, u8 *pValue, u16 count)
+{
+	int status = 0;
+
+	if (Bank != 0xFF && cxd->curbankx != Bank) {
+		status = writereg(cxd, cxd->adrx, 0, Bank);
+		if (status < 0) {
+			cxd->curbankx = 0xFF;
+			return status;
+		}
+		cxd->curbankx = Bank;
+	}
+	status = readregs(cxd, cxd->adrx, Address, pValue, count);
+	return status;
+}
+
+static int readregsx(struct cxd_state *cxd, u8 Bank,
+		     u8 Address, u8 *pValue, u16 count)
+{
+	int status;
+
+	mutex_lock(&cxd->mutex);
+	status = readregsx_unlocked(cxd, Bank, Address, pValue, count);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank,
+			       u8 Address, u8 *pValue, u16 count)
+{
+	int status = 0;
+
+	if (Bank != 0xFF && cxd->curbankx != Bank) {
+		status = writereg(cxd, cxd->adrx, 0, Bank);
+		if (status < 0) {
+			cxd->curbankx = 0xFF;
+			return status;
+		}
+		cxd->curbankx = Bank;
+	}
+	status = writeregs(cxd, cxd->adrx, Address, pValue, count);
+	return status;
+}
+
+static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address,
+		      u8 *pValue, u16 count)
+{
+	int status;
+
+	mutex_lock(&cxd->mutex);
+	status = writeregsx_unlocked(cxd, Bank, Address, pValue, count);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
+{
+	return writeregsx(cxd, Bank, Address, &val, 1);
+}
+
+static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank,
+			       u8 Address, u8 *pValue, u16 count)
+{
+	int status = 0;
+
+	if (Bank != 0xFF && cxd->curbankt != Bank) {
+		status = writereg(cxd, cxd->adrt, 0, Bank);
+		if (status < 0) {
+			cxd->curbankt = 0xFF;
+			return status;
+		}
+		cxd->curbankt = Bank;
+	}
+	status = writeregs(cxd, cxd->adrt, Address, pValue, count);
+	return status;
+}
+
+static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address,
+		      u8 *pValue, u16 count)
+{
+	int status;
+
+	mutex_lock(&cxd->mutex);
+	status = writeregst_unlocked(cxd, Bank, Address, pValue, count);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
+{
+	return writeregst(cxd, Bank, Address, &val, 1);
+}
+
+static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address,
+		      u8 Value, u8 Mask)
+{
+	int status = 0;
+	u8 tmp;
+
+	mutex_lock(&cxd->mutex);
+	status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1);
+	if (status < 0)
+		return status;
+	tmp = (tmp & ~Mask) | Value;
+	status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address,
+		      u8 Value, u8 Mask)
+{
+	int status = 0;
+	u8 Tmp = 0x00;
+
+	mutex_lock(&cxd->mutex);
+	status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1);
+	if (status < 0)
+		return status;
+	Tmp = (Tmp & ~Mask) | Value;
+	status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static int freeze_regst(struct cxd_state *cxd)
+{
+	mutex_lock(&cxd->mutex);
+	return writereg(cxd, cxd->adrt, 1, 1);
+}
+
+static int unfreeze_regst(struct cxd_state *cxd)
+{
+	int status = 0;
+
+	status = writereg(cxd, cxd->adrt, 1, 0);
+	mutex_unlock(&cxd->mutex);
+	return status;
+}
+
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64)a * (u64)b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+/* TPSData[0] [7:6]  CNST[1:0] */
+/* TPSData[0] [5:3]  HIER[2:0] */
+/* TPSData[0] [2:0]  HRATE[2:0] */
+/* TPSData[1] [7:5]  LRATE[2:0] */
+/* TPSData[1] [4:3]  GI[1:0] */
+/* TPSData[1] [2:1]  MODE[1:0] */
+/* TPSData[2] [7:6]  FNUM[1:0] */
+/* TPSData[2] [5:0]  LENGTH_INDICATOR[5:0] */
+/* TPSData[3] [7:0]  CELLID[15:8] */
+/* TPSData[4] [7:0]  CELLID[7:0] */
+/* TPSData[5] [5:0]  RESERVE_EVEN[5:0] */
+/* TPSData[6] [5:0]  RESERVE_ODD[5:0] */
+
+static int read_tps(struct cxd_state *state, u8 *tps)
+{
+	if (state->last_status != 0x1f)
+		return 0;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x10, 0x2f, tps, 7);
+	unfreeze_regst(state);
+	return 0;
+}
+
+static void Active_to_Sleep(struct cxd_state *state)
+{
+	if (state->state <= Sleep)
+		return;
+
+	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
+	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
+	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
+	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
+	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
+	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
+	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
+	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
+	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
+	state->state = Sleep;
+}
+
+static void ActiveT2_to_Sleep(struct cxd_state *state)
+{
+	if (state->state <= Sleep)
+		return;
+
+	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
+	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
+	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
+
+	writeregt(state, 0x13, 0x83, 0x40);
+	writeregt(state, 0x13, 0x86, 0x21);
+	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
+	writeregt(state, 0x13, 0x9F, 0xFB);
+
+	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
+	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
+	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
+	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
+	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
+	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
+	state->state = Sleep;
+}
+
+static void ActiveC2_to_Sleep(struct cxd_state *state)
+{
+	if (state->state <= Sleep)
+		return;
+
+	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
+	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
+	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
+
+	writeregt(state, 0x20, 0xC2, 0x11);
+	writebitst(state, 0x25, 0x6A, 0x02, 0x03);
+	{
+		static u8 data[3] = { 0x07, 0x61, 0x36 };
+		writeregst(state, 0x25, 0x89, data, sizeof(data));
+	}
+	writebitst(state, 0x25, 0xCB, 0x05, 0x07);
+	{
+		static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 };
+		writeregst(state, 0x25, 0xDC, data, sizeof(data));
+	}
+	writeregt(state, 0x25, 0xE2, 0x2F);
+	writeregt(state, 0x25, 0xE5, 0x2F);
+	writebitst(state, 0x27, 0x20, 0x00, 0x01);
+	writebitst(state, 0x27, 0x35, 0x00, 0x01);
+	writebitst(state, 0x27, 0xD9, 0x19, 0x3F);
+	writebitst(state, 0x2A, 0x78, 0x01, 0x07);
+	writeregt(state, 0x2A, 0x86, 0x08);
+	writeregt(state, 0x2A, 0x88, 0x14);
+	writebitst(state, 0x2B, 0x2B, 0x00, 0x1F);
+	{
+		u8 data[2] = { 0x75, 0x75 };
+		writeregst(state, 0x2D, 0x24, data, sizeof(data));
+	}
+
+	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
+	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
+	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
+	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
+	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
+	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
+	state->state = Sleep;
+}
+
+static int ConfigureTS(struct cxd_state *state,
+		       enum EDemodState newDemodState)
+{
+	int status = 0;
+	u8 OSERCKMODE = state->SerialMode ?  1 : 0;
+	u8 OSERDUTYMODE = state->SerialMode ?  1 : 0;
+	u8 OTSCKPERIOD = 8;
+	u8 OREG_CKSEL_TSIF = state->SerialMode ?
+		state->SerialClockFrequency : 0;
+
+	if (state->SerialMode && state->SerialClockFrequency >= 3) {
+		OSERCKMODE = 2;
+		OSERDUTYMODE = 2;
+		OTSCKPERIOD = 16;
+		OREG_CKSEL_TSIF = state->SerialClockFrequency - 3;
+	}
+	writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */
+	writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */
+	writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */
+	writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */
+	/* OREG_CKSEL_TSIF */
+	writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03);
+	writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */
+
+	if (newDemodState == ActiveT)
+		writebitst(state, 0x10, 0x66, 0x01, 0x01);
+	if (newDemodState == ActiveC)
+		writebitst(state, 0x40, 0x66, 0x01, 0x01);
+
+	return status;
+}
+
+static void BandSettingT(struct cxd_state *state, u32 iffreq)
+{
+	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
+			  (iffreq >> 8) & 0xff, iffreq & 0xff};
+
+	switch (state->bw) {
+	default:
+	case 8:
+	{
+		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		u8 CL_data[] = { 0x01, 0xE0 };
+		u8 NF_data[] = { 0x01, 0x02 };
+
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
+		break;
+	}
+	case 7:
+	{
+		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
+		u8 CL_data[] = { 0x12, 0xF8 };
+		u8 NF_data[] = { 0x00, 0x03 };
+
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
+		break;
+	}
+	case 6:
+	{
+		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		u8 CL_data[] = { 0x1F, 0xDC };
+		u8 NF_data[] = { 0x00, 0x03 };
+
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
+		break;
+	}
+	case 5:
+	{
+		static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
+		static u8 CL_data[] = { 0x26, 0x3C };
+		static u8 NF_data[] = { 0x00, 0x03 };
+
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
+		break;
+	}
+	}
+}
+
+static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq)
+{
+	ConfigureTS(state, ActiveT);
+	writeregx(state, 0x00, 0x17, 0x01);   /* Mode */
+	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
+	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
+	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
+	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
+	{
+		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
+		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
+		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
+	}
+	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
+
+	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */
+	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
+
+	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
+
+	writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */
+	writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */
+	writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */
+
+	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
+	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
+
+	BandSettingT(state, iffreq);
+
+	writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */
+
+	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
+	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
+}
+
+static void BandSettingT2(struct cxd_state *state, u32 iffreq)
+{
+	u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff,
+			 iffreq & 0xff};
+
+	switch (state->bw) {
+	default:
+	case 8:
+	{
+		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		/* Timing recovery */
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		/* Add EQ Optimisation for tuner here */
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		/* System Bandwidth */
+		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
+	}
+	break;
+	case 7:
+	{
+		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
+	}
+	break;
+	case 6:
+	{
+		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
+	}
+	break;
+	case 5:
+	{
+		u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
+	}
+	break;
+	case 2: /* 1.7 MHz */
+	{
+		u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC };
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x03, 0x07);
+	}
+	break;
+	}
+}
+
+
+static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq)
+{
+	ConfigureTS(state, ActiveT2);
+
+	writeregx(state, 0x00, 0x17, 0x02);   /* Mode */
+	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
+	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
+	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
+	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
+
+	{
+		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
+		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
+		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
+	}
+	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
+
+	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
+	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
+	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
+
+	writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */
+	writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */
+
+	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
+	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
+
+	writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */
+	writeregt(state, 0x13, 0x86, 0x34);
+	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
+	writeregt(state, 0x13, 0x9F, 0xD8);
+
+	BandSettingT2(state, iffreq);
+
+	writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */
+
+	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
+	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
+}
+
+
+static void BandSettingC(struct cxd_state *state, u32 iffreq)
+{
+	u8 data[3];
+
+	data[0] = (iffreq >> 16) & 0xFF;
+	data[1] = (iffreq >>  8) & 0xFF;
+	data[2] = (iffreq) & 0xFF;
+	writeregst(state, 0x10, 0xB6, data, 3);
+}
+
+static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq)
+{
+	ConfigureTS(state, ActiveC);
+
+	writeregx(state, 0x00, 0x17, 0x04);   /* Mode */
+	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
+	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
+	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
+	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
+
+	{
+		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
+		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
+		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
+	}
+	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
+
+	writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */
+	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
+	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
+
+	writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */
+
+	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
+	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
+
+	BandSettingC(state, iffreq);
+
+	writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */
+
+	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
+	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
+}
+
+static void BandSettingC2(struct cxd_state *state, u32 iffreq)
+{
+	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
+			  (iffreq >> 8) & 0xff, iffreq & 0xff};
+
+	switch (state->bw) {
+	default:
+	case 8:
+	{
+		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		u8 data[2] = { 0x11, 0x9E };
+
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
+		writeregst(state, 0x50, 0xEC, data, sizeof(data));
+		writeregt(state, 0x50, 0xEF, 0x11);
+		writeregt(state, 0x50, 0xF1, 0x9E);
+	}
+	break;
+	case 6:
+	{
+		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		u8 data[2] = { 0x17, 0x70 };
+
+		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
+		writeregst(state, 0x50, 0xEC, data, sizeof(data));
+		writeregt(state, 0x50, 0xEF, 0x17);
+		writeregt(state, 0x50, 0xF1, 0x70);
+	}
+	break;
+	}
+}
+
+static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq)
+{
+	ConfigureTS(state, ActiveC2);
+
+	writeregx(state, 0x00, 0x17, 0x05);   /* Mode */
+	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
+	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
+	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
+	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
+
+	{
+		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
+		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
+		writeregst(state, 0x00, 0x43, data, sizeof(data));
+		/* Enable ADC 2+3 */
+	}
+	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
+
+	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
+	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
+	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
+
+	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
+	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
+
+	writeregt(state, 0x20, 0xC2, 0x00);
+	writebitst(state, 0x25, 0x6A, 0x00, 0x03);
+	{
+		u8 data[3] = { 0x0C, 0xD1, 0x40 };
+		writeregst(state, 0x25, 0x89, data, sizeof(data));
+	}
+	writebitst(state, 0x25, 0xCB, 0x01, 0x07);
+	{
+		u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 };
+		writeregst(state, 0x25, 0xDC, data, sizeof(data));
+	}
+	writeregt(state, 0x25, 0xE2, 0x30);
+	writeregt(state, 0x25, 0xE5, 0x30);
+	writebitst(state, 0x27, 0x20, 0x01, 0x01);
+	writebitst(state, 0x27, 0x35, 0x01, 0x01);
+	writebitst(state, 0x27, 0xD9, 0x18, 0x3F);
+	writebitst(state, 0x2A, 0x78, 0x00, 0x07);
+	writeregt(state, 0x2A, 0x86, 0x20);
+	writeregt(state, 0x2A, 0x88, 0x32);
+	writebitst(state, 0x2B, 0x2B, 0x10, 0x1F);
+	{
+		u8 data[2] = { 0x01, 0x01 };
+		writeregst(state, 0x2D, 0x24, data, sizeof(data));
+	}
+
+	BandSettingC2(state, iffreq);
+
+	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
+	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
+}
+
+
+static void BandSettingIT(struct cxd_state *state, u32 iffreq)
+{
+	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
+			  (iffreq >> 8) & 0xff, iffreq & 0xff};
+
+	switch (state->bw) {
+	default:
+	case 8:
+	{
+		u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */
+		u8 CL_data[] = { 0x15, 0xA8 };
+
+		/*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		/* Add EQ Optimisation for tuner here */
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+
+		writeregt(state, 0x10, 0xD7, 0x00);   /* System Bandwidth */
+		/*u8 CL_data[] = { 0x13, 0xFC }; */
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+	}
+	break;
+	case 7:
+	{
+		u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 };
+		u8 CL_data[] = { 0x1B, 0x5D };
+
+		/*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+
+		writeregt(state, 0x10, 0xD7, 0x02);
+		/*static u8 CL_data[] = { 0x1A, 0xFA };*/
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+	}
+	break;
+	case 6:
+	{
+		u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 };
+		u8 CL_data[] = { 0x1F, 0xEC };
+		/*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */
+		/*u8 CL_data[] = { 0x1F, 0x79 }; */
+
+		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
+		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
+		writeregt(state, 0x10, 0xD7, 0x04);
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
+	}
+	break;
+	}
+}
+
+static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq)
+{
+	u8 data2[3] = { 0xB9, 0xBA, 0x63 };  /* 20.5/41 MHz */
+	/*u8 data2[3] = { 0xB7,0x1B,0x00 }; */  /* 24 MHz */
+	u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */
+	/*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */
+
+	pr_info("%s\n", __func__);
+
+	ConfigureTS(state, ActiveIT);
+
+	/* writeregx(state, 0x00,0x17,0x01); */  /* 2838 has only one Mode */
+	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
+	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
+	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
+	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
+
+	{
+		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz, 24 MHz */
+		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
+		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
+	}
+	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
+
+	writeregst(state, 0x60, 0xA8, data2, sizeof(data2));
+
+	writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data));
+
+	writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */
+	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
+
+	BandSettingIT(state, iffreq);
+
+	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
+	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
+}
+
+static void T2_SetParameters(struct cxd_state *state)
+{
+	u8 Profile = 0x01;    /* Profile Base */
+	u8 notT2time = 12;    /* early unlock detection time */
+
+	if (state->T2Profile == T2P_Lite) {
+		Profile = 0x05;
+		notT2time = 40;
+	}
+
+	if (state->plp != 0xffffffff) {
+		state->T2Profile = ((state->plp & 0x100) != 0) ?
+			T2P_Lite : T2P_Base;
+		writeregt(state, 0x23, 0xAF, state->plp);
+		writeregt(state, 0x23, 0xAD, 0x01);
+	} else {
+		state->T2Profile = T2P_Base;
+		writeregt(state, 0x23, 0xAD, 0x00);
+	}
+
+	writebitst(state, 0x2E, 0x10, Profile, 0x07);
+	writeregt(state, 0x2B, 0x19, notT2time);
+}
+
+static void C2_ReleasePreset(struct cxd_state *state)
+{
+	{
+		static u8 data[2] = { 0x02, 0x80};
+		writeregst(state, 0x27, 0xF4, data, sizeof(data));
+	}
+	writebitst(state, 0x27, 0x51, 0x40, 0xF0);
+	writebitst(state, 0x27, 0x73, 0x07, 0x0F);
+	writebitst(state, 0x27, 0x74, 0x19, 0x3F);
+	writebitst(state, 0x27, 0x75, 0x19, 0x3F);
+	writebitst(state, 0x27, 0x76, 0x19, 0x3F);
+	if (state->bw == 6) {
+		static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA};
+		writeregst(state, 0x20, 0x9F, data, sizeof(data));
+	} else {
+		static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00};
+		writeregst(state, 0x20, 0x9F, data, sizeof(data));
+	}
+	writebitst(state, 0x27, 0xC9, 0x07, 0x07);
+	writebitst(state, 0x20, 0xC2, 0x11, 0x33);
+	{
+		static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8,
+				       0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 };
+		writeregst(state, 0x2A, 0x20, data, sizeof(data));
+	}
+	{
+		static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 };
+		writeregst(state, 0x50, 0x6B, data, sizeof(data));
+	}
+	writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */
+}
+
+static void C2_DemodSetting2(struct cxd_state *state)
+{
+	u8 data[6];
+	u32 TunePosition =
+		state->frontend.dtv_property_cache.frequency / 1000;
+
+	if (state->bw == 6)
+		TunePosition = ((TunePosition * 1792) / 3) / 1000;
+	else
+		TunePosition = (TunePosition * 448) / 1000;
+
+	TunePosition = ((TunePosition + 6) / 12) * 12;
+
+	pr_info("TunePosition = %u\n", TunePosition);
+
+	data[0] = ((TunePosition >> 16) & 0xFF);
+	data[1] = ((TunePosition >>  8) & 0xFF);
+	data[2] = (TunePosition & 0xFF);
+	data[3] = 0x02;
+	data[4] = (state->DataSliceID & 0xFF);
+	data[5] = (state->plp & 0xFF);
+	writeregst(state, 0x50, 0x7A, data, sizeof(data));
+	writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */
+}
+
+static void Stop(struct cxd_state *state)
+{
+
+	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
+}
+
+static void ShutDown(struct cxd_state *state)
+{
+	switch (state->state) {
+	case ActiveT2:
+		ActiveT2_to_Sleep(state);
+		break;
+	case ActiveC2:
+		ActiveC2_to_Sleep(state);
+		break;
+	default:
+		Active_to_Sleep(state);
+		break;
+	}
+}
+
+static int gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+
+	return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01);
+}
+
+static void release(struct dvb_frontend *fe)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+
+	Stop(state);
+	ShutDown(state);
+	kfree(state);
+}
+
+static int Start(struct cxd_state *state, u32 IntermediateFrequency)
+{
+	enum EDemodState newDemodState = Unknown;
+	u32 iffreq;
+
+	if (state->state < Sleep)
+		return -EINVAL;
+
+	iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000);
+
+	switch (state->omode) {
+	case OM_DVBT:
+		if (state->type == CXD2838)
+			return -EINVAL;
+		newDemodState = ActiveT;
+		break;
+	case OM_DVBT2:
+		if (state->type == CXD2838)
+			return -EINVAL;
+		newDemodState = ActiveT2;
+		break;
+	case OM_DVBC:
+	case OM_QAM_ITU_C:
+		if (state->type == CXD2838)
+			return -EINVAL;
+		newDemodState = ActiveC;
+		break;
+	case OM_DVBC2:
+		if (state->type != CXD2843)
+			return -EINVAL;
+		newDemodState = ActiveC2;
+		break;
+	case OM_ISDBT:
+		if (state->type != CXD2838)
+			return -EINVAL;
+		newDemodState = ActiveIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	state->LockTimeout = 0;
+	state->TSLockTimeout = 0;
+	state->L1PostTimeout = 0;
+	state->last_status = 0;
+	state->FirstTimeLock = 1;
+	state->LastBERNominator = 0;
+	state->LastBERDenominator = 1;
+	state->BERScaleMax = 19;
+
+	if (state->state == newDemodState) {
+		writeregt(state, 0x00, 0xC3, 0x01);   /* Disable TS Output */
+		switch (newDemodState) {
+		case ActiveT:
+			/* Stick with HP ( 0x01 = LP ) */
+			writeregt(state, 0x10, 0x67, 0x00);
+			BandSettingT(state, iffreq);
+			state->BERScaleMax = 18;
+			break;
+		case ActiveT2:
+			T2_SetParameters(state);
+			BandSettingT2(state, iffreq);
+			state->BERScaleMax = 12;
+			break;
+		case ActiveC:
+			BandSettingC(state, iffreq);
+			state->BERScaleMax = 19;
+			break;
+		case ActiveC2:
+			BandSettingC2(state, iffreq);
+			C2_ReleasePreset(state);
+			C2_DemodSetting2(state);
+			break;
+		case ActiveIT:
+			BandSettingIT(state, iffreq);
+			break;
+		default:
+			break;
+		}
+	} else {
+		if (state->state > Sleep) {
+			switch (state->state) {
+			case ActiveT2:
+				ActiveT2_to_Sleep(state);
+				break;
+			case ActiveC2:
+				ActiveC2_to_Sleep(state);
+				break;
+			default:
+				Active_to_Sleep(state);
+				break;
+			}
+		}
+		switch (newDemodState) {
+		case ActiveT:
+			/* Stick with HP ( 0x01 = LP ) */
+			writeregt(state, 0x10, 0x67, 0x00);
+			Sleep_to_ActiveT(state, iffreq);
+			state->BERScaleMax = 18;
+			break;
+		case ActiveT2:
+			T2_SetParameters(state);
+			Sleep_to_ActiveT2(state, iffreq);
+			state->BERScaleMax = 12;
+			break;
+		case ActiveC:
+			Sleep_to_ActiveC(state, iffreq);
+			state->BERScaleMax = 19;
+			break;
+		case ActiveC2:
+			Sleep_to_ActiveC2(state, iffreq);
+			C2_ReleasePreset(state);
+			C2_DemodSetting2(state);
+			break;
+		case ActiveIT:
+			Sleep_to_ActiveIT(state, iffreq);
+			break;
+		default:
+			break;
+		}
+	}
+	state->state = newDemodState;
+	writeregt(state, 0x00, 0xFE, 0x01);   /* SW Reset */
+	writeregt(state, 0x00, 0xC3, 0x00);   /* Enable TS Output */
+
+	return 0;
+}
+
+static int set_parameters(struct dvb_frontend *fe)
+{
+	int stat;
+	struct cxd_state *state = fe->demodulator_priv;
+	u32 IF;
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+		state->omode = OM_DVBC;
+		break;
+	case SYS_DVBC2:
+		state->omode = OM_DVBC2;
+		break;
+	case SYS_DVBT:
+		state->omode = OM_DVBT;
+		break;
+	case SYS_DVBT2:
+		state->omode = OM_DVBT2;
+		break;
+	case SYS_ISDBT:
+		state->omode = OM_ISDBT;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
+	state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000;
+	if (fe->dtv_property_cache.stream_id == 0xffffffff) {
+		state->DataSliceID = 0xffffffff;
+		state->plp = 0xffffffff;
+	} else {
+		state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8)
+			& 0xff;
+		state->plp = fe->dtv_property_cache.stream_id & 0xff;
+	}
+	/* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	stat = Start(state, IF);
+	return stat;
+}
+
+
+static void init(struct cxd_state *state)
+{
+	u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */
+
+	state->omode = OM_NONE;
+	state->state   = Unknown;
+
+	writeregx(state, 0xFF, 0x02, 0x00);
+	usleep_range(4000, 5000);
+	writeregx(state, 0x00, 0x15, 0x01);
+	if (state->type != CXD2838)
+		writeregx(state, 0x00, 0x17, 0x01);
+	usleep_range(4000, 5000);
+
+	writeregx(state, 0x00, 0x10, 0x01);
+
+	writeregsx(state, 0x00, 0x13, data, 2);
+	writeregx(state, 0x00, 0x15, 0x00);
+	usleep_range(3000, 4000);
+	writeregx(state, 0x00, 0x10, 0x00);
+	usleep_range(2000, 3000);
+
+	state->curbankx = 0xFF;
+	state->curbankt = 0xFF;
+
+	writeregt(state, 0x00, 0x43, 0x0A);
+	writeregt(state, 0x00, 0x41, 0x0A);
+	if (state->type == CXD2838)
+		writeregt(state, 0x60, 0x5A, 0x00);
+
+	writebitst(state, 0x10, 0xCB, 0x00, 0x40);
+	writeregt(state, 0x10, 0xCD, state->IF_FS);
+
+	writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98);
+	writebitst(state, 0x00, 0xC5, 0x01, 0x07);
+	writebitst(state, 0x00, 0xCB, 0x00, 0x01);
+	writebitst(state, 0x00, 0xC6, 0x00, 0x1D);
+	writebitst(state, 0x00, 0xC8, 0x01, 0x1D);
+	writebitst(state, 0x00, 0xC9, 0x00, 0x1D);
+	writebitst(state, 0x00, 0x83, 0x00, 0x07);
+	writeregt(state, 0x00, 0x84, 0x00);
+	writebitst(state, 0x00, 0xD3,
+		   (state->type == CXD2838) ? 0x01 : 0x00, 0x01);
+	writebitst(state, 0x00, 0xDE, 0x00, 0x01);
+
+	state->state = Sleep;
+}
+
+
+static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg)
+{
+	state->adrt = cfg->adr;
+	state->adrx = cfg->adr + 0x02;
+	state->curbankt = 0xff;
+	state->curbankx = 0xff;
+	mutex_init(&state->mutex);
+
+	state->SerialMode = cfg->parallel ? 0 : 1;
+	state->ContinuousClock = 1;
+	state->SerialClockFrequency =
+		(cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ?
+		cfg->ts_clock :  1; /* 1 = fastest (82 MBit/s), 5 = slowest */
+	state->SerialClockFrequency = 1;
+	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */
+	state->IF_FS = 0x50;
+}
+
+static int get_tune_settings(struct dvb_frontend *fe,
+			     struct dvb_frontend_tune_settings *sets)
+{
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		/*return c_get_tune_settings(fe, sets);*/
+	default:
+		/* DVB-T: Use info.frequency_stepsize. */
+		return -EINVAL;
+	}
+}
+
+static int read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+	u8 rdata;
+
+	*status = 0;
+	switch (state->state) {
+	case ActiveC:
+		readregst(state, 0x40, 0x88, &rdata, 1);
+		if (rdata & 0x02)
+			break;
+		if (rdata & 0x01) {
+			*status |= 0x07;
+			readregst(state, 0x40, 0x10, &rdata, 1);
+			if (rdata & 0x20)
+				*status |= 0x1f;
+		}
+		break;
+	case ActiveT:
+		readregst(state, 0x10, 0x10, &rdata, 1);
+		if (rdata & 0x10)
+			break;
+		if ((rdata & 0x07) == 0x06) {
+			*status |= 0x07;
+			if (rdata & 0x20)
+				*status |= 0x1f;
+		}
+		break;
+	case ActiveT2:
+		readregst(state, 0x20, 0x10, &rdata, 1);
+		if (rdata & 0x10)
+			break;
+		if ((rdata & 0x07) == 0x06) {
+			*status |= 0x07;
+			if (rdata & 0x20)
+				*status |= 0x08;
+		}
+		if (*status & 0x08) {
+			readregst(state, 0x22, 0x12, &rdata, 1);
+			if (rdata & 0x01)
+				*status |= 0x10;
+		}
+		break;
+	case ActiveC2:
+		readregst(state, 0x20, 0x10, &rdata, 1);
+		if (rdata & 0x10)
+			break;
+		if ((rdata & 0x07) == 0x06) {
+			*status |= 0x07;
+			if (rdata & 0x20)
+				*status |= 0x18;
+		}
+		if ((*status & 0x10) && state->FirstTimeLock) {
+			u8 data;
+
+			/* Change1stTrial */
+			readregst(state, 0x28, 0xE6, &rdata, 1);
+			data = rdata & 1;
+			readregst(state, 0x50, 0x15, &rdata, 1);
+			data |= ((rdata & 0x18) >> 2);
+			/*writebitst(state, 0x50,0x6F,rdata,0x07);*/
+			state->FirstTimeLock = 0;
+		}
+		break;
+	case ActiveIT:
+		readregst(state, 0x60, 0x10, &rdata, 1);
+		if (rdata & 0x10)
+			break;
+		if (rdata & 0x02) {
+			*status |= 0x07;
+			if (rdata & 0x01)
+				*status |= 0x18;
+		}
+		break;
+	default:
+		break;
+	}
+	state->last_status = *status;
+	return 0;
+}
+
+static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d)
+{
+	u8 BERRegs[3];
+	u8 Scale;
+
+	*n = 0;
+	*d = 1;
+
+	readregst(state, 0x10, 0x62, BERRegs, 3);
+	readregst(state, 0x10, 0x60, &Scale, 1);
+	Scale &= 0x1F;
+
+	if (BERRegs[0] & 0x80) {
+		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
+			(((u32) BERRegs[1]) << 8) | BERRegs[2];
+		state->LastBERDenominator = 1632 << Scale;
+		if (state->LastBERNominator < 256 &&
+		    Scale < state->BERScaleMax) {
+			writebitst(state, 0x10, 0x60, Scale + 1, 0x1F);
+		} else if (state->LastBERNominator > 512 && Scale > 11)
+			writebitst(state, 0x10, 0x60, Scale - 1, 0x1F);
+	}
+	*n = state->LastBERNominator;
+	*d = state->LastBERDenominator;
+
+	return 0;
+}
+
+static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d)
+{
+	*n = 0;
+	*d = 1;
+	return 0;
+}
+
+static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d)
+{
+	u8 BERRegs[3];
+	u8 Scale;
+
+	*n = 0;
+	*d = 1;
+
+	readregst(state, 0x40, 0x62, BERRegs, 3);
+	readregst(state, 0x40, 0x60, &Scale, 1);
+	Scale &= 0x1F;
+
+	if (BERRegs[0] & 0x80) {
+		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
+			(((u32) BERRegs[1]) << 8) | BERRegs[2];
+		state->LastBERDenominator = 1632 << Scale;
+		if (state->LastBERNominator < 256 &&
+		    Scale < state->BERScaleMax) {
+			writebitst(state, 0x40, 0x60, Scale + 1, 0x1F);
+		} else if (state->LastBERNominator > 512 && Scale > 11)
+			writebitst(state, 0x40, 0x60, Scale - 1, 0x1F);
+	}
+	*n = state->LastBERNominator;
+	*d = state->LastBERDenominator;
+
+	return 0;
+}
+
+static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d)
+{
+	*n = 0;
+	*d = 1;
+	return 0;
+}
+
+static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d)
+{
+	*n = 0;
+	*d = 1;
+	return 0;
+}
+
+static int read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+	u32 n, d;
+	int s = 0;
+
+	*ber = 0;
+	switch (state->state) {
+	case ActiveT:
+		s = get_ber_t(state, &n, &d);
+		break;
+	case ActiveT2:
+		s = get_ber_t2(state, &n, &d);
+		break;
+	case ActiveC:
+		s = get_ber_c(state, &n, &d);
+		break;
+	case ActiveC2:
+		s = get_ber_c2(state, &n, &d);
+		break;
+	case ActiveIT:
+		s = get_ber_it(state, &n, &d);
+		break;
+	default:
+		break;
+	}
+	if (s)
+		return s;
+
+	return 0;
+}
+
+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	if (fe->ops.tuner_ops.get_rf_strength)
+		fe->ops.tuner_ops.get_rf_strength(fe, strength);
+	else
+		*strength = 0;
+	return 0;
+}
+
+static s32 Log10x100(u32 x)
+{
+	static u32 LookupTable[100] = {
+		101157945, 103514217, 105925373, 108392691, 110917482,
+		113501082, 116144861, 118850223, 121618600, 124451461,
+		127350308, 130316678, 133352143, 136458314, 139636836,
+		142889396, 146217717, 149623566, 153108746, 156675107,
+		160324539, 164058977, 167880402, 171790839, 175792361,
+		179887092, 184077200, 188364909, 192752491, 197242274,
+		201836636, 206538016, 211348904, 216271852, 221309471,
+		226464431, 231739465, 237137371, 242661010, 248313311,
+		254097271, 260015956, 266072506, 272270131, 278612117,
+		285101827, 291742701, 298538262, 305492111, 312607937,
+		319889511, 327340695, 334965439, 342767787, 350751874,
+		358921935, 367282300, 375837404, 384591782, 393550075,
+		402717034, 412097519, 421696503, 431519077, 441570447,
+		451855944, 462381021, 473151259, 484172368, 495450191,
+		506990708, 518800039, 530884444, 543250331, 555904257,
+		568852931, 582103218, 595662144, 609536897, 623734835,
+		638263486, 653130553, 668343918, 683911647, 699841996,
+		716143410, 732824533, 749894209, 767361489, 785235635,
+		803526122, 822242650, 841395142, 860993752, 881048873,
+		901571138, 922571427, 944060876, 966050879, 988553095,
+	};
+	s32 y;
+	int i;
+
+	if (x == 0)
+		return 0;
+	y = 800;
+	if (x >= 1000000000) {
+		x /= 10;
+		y += 100;
+	}
+
+	while (x < 100000000) {
+		x *= 10;
+		y -= 100;
+	}
+	i = 0;
+	while (i < 100 && x > LookupTable[i])
+		i += 1;
+	y += i;
+	return y;
+}
+
+#if 0
+static void GetPLPIds(struct cxd_state *state, u32 nValues,
+		      u8 *Values, u32 *Returned)
+{
+	u8 nPids = 0;
+
+	*Returned = 0;
+	if (state->state != ActiveT2)
+		return;
+	if (state->last_status != 0x1f)
+		return;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x22, 0x7F, &nPids, 1);
+
+	Values[0] = nPids;
+	if (nPids >= nValues)
+		nPids = nValues - 1;
+
+	readregst_unlocked(state, 0x22, 0x80, &Values[1],
+			   nPids > 128 ? 128 : nPids);
+
+	if (nPids > 128)
+		readregst_unlocked(state, 0x23, 0x10, &Values[129],
+				   nPids - 128);
+
+	*Returned = nPids + 1;
+
+	unfreeze_regst(state);
+}
+#endif
+
+static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u32 reg;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data));
+	unfreeze_regst(state);
+
+	reg = (Data[0] << 8) | Data[1];
+	if (reg > 51441)
+		reg = 51441;
+
+	if (state->bw == 8) {
+		if (reg > 1143)
+			reg = 1143;
+		*SignalToNoise = (Log10x100(reg) -
+				  Log10x100(1200 - reg)) + 220;
+	} else
+		*SignalToNoise = Log10x100(reg) - 90;
+}
+
+static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u32 reg;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
+	unfreeze_regst(state);
+
+	reg = (Data[0] << 8) | Data[1];
+	if (reg > 51441)
+		reg = 51441;
+
+	*SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384;
+}
+
+
+static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u32 reg;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
+	unfreeze_regst(state);
+
+	reg = (Data[0] << 8) | Data[1];
+	if (reg > 10876)
+		reg = 10876;
+
+	*SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320;
+}
+
+static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u32 reg;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data));
+	unfreeze_regst(state);
+
+	reg = (Data[0] << 8) | Data[1];
+	if (reg > 4996)
+		reg = 4996;
+
+	*SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285;
+}
+
+static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u8 Constellation = 0;
+	u32 reg;
+
+	*SignalToNoise = 0;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x40, 0x19, &Constellation, 1);
+	readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data));
+	unfreeze_regst(state);
+
+	reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]);
+	if (reg == 0)
+		return;
+
+	switch (Constellation & 0x07) {
+	case 0: /* QAM 16 */
+	case 2: /* QAM 64 */
+	case 4: /* QAM 256 */
+		if (reg < 126)
+			reg = 126;
+		*SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000;
+		break;
+	case 1: /* QAM 32 */
+	case 3: /* QAM 128 */
+		if (reg < 69)
+			reg = 69;
+		*SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000;
+		break;
+	}
+}
+
+static int read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+	u32 SNR = 0;
+
+	*snr = 0;
+	if (state->last_status != 0x1f)
+		return 0;
+
+	switch (state->state) {
+	case ActiveC:
+		GetSignalToNoiseC(state, &SNR);
+		break;
+	case ActiveC2:
+		GetSignalToNoiseC2(state, &SNR);
+		break;
+	case ActiveT:
+		GetSignalToNoiseT(state, &SNR);
+		break;
+	case ActiveT2:
+		GetSignalToNoiseT2(state, &SNR);
+		break;
+	case ActiveIT:
+		GetSignalToNoiseIT(state, &SNR);
+		break;
+	default:
+		break;
+	}
+	*snr = SNR;
+	return 0;
+}
+
+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int tune(struct dvb_frontend *fe, bool re_tune,
+		unsigned int mode_flags,
+		unsigned int *delay, fe_status_t *status)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+	int r;
+
+	if (re_tune) {
+		r = set_parameters(fe);
+		if (r)
+			return r;
+		state->tune_time = jiffies;
+
+	}
+	if (*status & FE_HAS_LOCK)
+		return 0;
+	/* *delay = 50; */
+	r = read_status(fe, status);
+	if (r)
+		return r;
+	return 0;
+}
+
+static enum dvbfe_search search(struct dvb_frontend *fe)
+{
+	int r;
+	u32 loops = 20, i;
+	fe_status_t status;
+
+	r = set_parameters(fe);
+
+	for (i = 0; i < loops; i++)  {
+		msleep(50);
+		r = read_status(fe, &status);
+		if (r)
+			return DVBFE_ALGO_SEARCH_ERROR;
+		if (status & FE_HAS_LOCK)
+			break;
+	}
+
+	if (status & FE_HAS_LOCK)
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	else
+		return DVBFE_ALGO_SEARCH_AGAIN;
+}
+
+static int get_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
+static int get_fe_t(struct cxd_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u8 tps[7];
+
+	read_tps(state, tps);
+
+/*  TPSData[0] [7:6]  CNST[1:0]
+    TPSData[0] [5:3]  HIER[2:0]
+    TPSData[0] [2:0]  HRATE[2:0]
+*/
+	switch ((tps[0] >> 6) & 0x03) {
+	case 0:
+		p->modulation = QPSK;
+		break;
+	case 1:
+		p->modulation = QAM_16;
+		break;
+	case 2:
+		p->modulation = QAM_64;
+		break;
+	}
+	switch ((tps[0] >> 3) & 0x07) {
+	case 0:
+		p->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy = HIERARCHY_4;
+		break;
+	}
+	switch ((tps[0] >> 0) & 0x07) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+/*  TPSData[1] [7:5]  LRATE[2:0]
+    TPSData[1] [4:3]  GI[1:0]
+    TPSData[1] [2:1]  MODE[1:0]
+*/
+	switch ((tps[1] >> 5) & 0x07) {
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
+	}
+	switch ((tps[1] >> 3) & 0x03) {
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+	switch ((tps[1] >> 1) & 0x03) {
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	return 0;
+}
+
+static int get_fe_c(struct cxd_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u8 qam;
+
+	freeze_regst(state);
+	readregst_unlocked(state, 0x40, 0x19, &qam, 1);
+	unfreeze_regst(state);
+	p->modulation = qam & 0x07;
+	return 0;
+}
+
+static int get_frontend(struct dvb_frontend *fe)
+{
+	struct cxd_state *state = fe->demodulator_priv;
+
+	if (state->last_status != 0x1f)
+		return 0;
+
+	switch (state->state) {
+	case ActiveT:
+		get_fe_t(state);
+		break;
+	case ActiveT2:
+		break;
+	case ActiveC:
+		get_fe_c(state);
+		break;
+	case ActiveC2:
+		break;
+	case ActiveIT:
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static struct dvb_frontend_ops common_ops_2843 = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 },
+	.info = {
+		.name = "CXD2843 DVB-C/C2 DVB-T/T2",
+		.frequency_stepsize = 166667,	/* DVB-T only */
+		.frequency_min = 47000000,	/* DVB-T: 47125000 */
+		.frequency_max = 865000000,	/* DVB-C: 862000000 */
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = /* DVB-C */
+			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO |
+			/* DVB-T */
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER | FE_CAN_MUTE_TS
+	},
+	.release = release,
+	.i2c_gate_ctrl = gate_ctrl,
+	.set_frontend = set_parameters,
+
+	.get_tune_settings = get_tune_settings,
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+	.get_frontend = get_frontend,
+#ifdef USE_ALGO
+	.get_frontend_algo = get_algo,
+	.search = search,
+	.tune = tune,
+#endif
+};
+
+static struct dvb_frontend_ops common_ops_2837 = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 },
+	.info = {
+		.name = "CXD2837 DVB-C DVB-T/T2",
+		.frequency_stepsize = 166667,	/* DVB-T only */
+		.frequency_min = 47000000,	/* DVB-T: 47125000 */
+		.frequency_max = 865000000,	/* DVB-C: 862000000 */
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = /* DVB-C */
+			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO |
+			/* DVB-T */
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER | FE_CAN_MUTE_TS
+	},
+	.release = release,
+	.i2c_gate_ctrl = gate_ctrl,
+	.set_frontend = set_parameters,
+
+	.get_tune_settings = get_tune_settings,
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+	.get_frontend = get_frontend,
+#ifdef USE_ALGO
+	.get_frontend_algo = get_algo,
+	.search = search,
+	.tune = tune,
+#endif
+};
+
+static struct dvb_frontend_ops common_ops_2838 = {
+	.delsys = { SYS_ISDBT },
+	.info = {
+		.name = "CXD2838 ISDB-T",
+		.frequency_stepsize = 166667,
+		.frequency_min = 47000000,
+		.frequency_max = 865000000,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER | FE_CAN_MUTE_TS
+	},
+	.release = release,
+	.i2c_gate_ctrl = gate_ctrl,
+	.set_frontend = set_parameters,
+
+	.get_tune_settings = get_tune_settings,
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+#ifdef USE_ALGO
+	.get_frontend_algo = get_algo,
+	.search = search,
+	.tune = tune,
+#endif
+};
+
+static int probe(struct cxd_state *state)
+{
+	u8 ChipID = 0x00;
+	int status;
+
+	status = readregst(state, 0x00, 0xFD, &ChipID, 1);
+
+	if (status)
+		status = readregsx(state, 0x00, 0xFD, &ChipID, 1);
+	if (status)
+		return status;
+
+	/*printk("ChipID  = %02X\n", ChipID);*/
+	switch (ChipID) {
+	case 0xa4:
+		state->type = CXD2843;
+		memcpy(&state->frontend.ops, &common_ops_2843,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	case 0xb1:
+		state->type = CXD2837;
+		memcpy(&state->frontend.ops, &common_ops_2837,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	case 0xb0:
+		state->type = CXD2838;
+		memcpy(&state->frontend.ops, &common_ops_2838,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	default:
+		return -1;
+	}
+	state->frontend.demodulator_priv = state;
+	return 0;
+}
+
+struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
+				    struct cxd2843_cfg *cfg)
+{
+	struct cxd_state *state = NULL;
+
+	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->i2c = i2c;
+	init_state(state, cfg);
+	if (probe(state) == 0) {
+		init(state);
+		return &state->frontend;
+	}
+	pr_err("cxd2843: not found\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(cxd2843_attach);
+
+MODULE_DESCRIPTION("CXD2843/37/38 driver");
+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h
new file mode 100644
index 0000000..f3e355b
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2843.h
@@ -0,0 +1,30 @@
+#ifndef _CXD2843_H_
+#define _CXD2843_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct cxd2843_cfg {
+	u8  adr;
+	u32 ts_clock;
+	u8  parallel;
+};
+
+#if defined(CONFIG_DVB_CXD2843) || \
+	(defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
+					   struct cxd2843_cfg *cfg);
+
+#else
+
+static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
+					   struct cxd2843_cfg *cfg)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif
+
+#endif
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] ddbridge: add support for DVB-C/C2/T/T2 extension card
  2014-07-31 22:33 [PATCH 1/4] tda18212: add support for slave chip version Antti Palosaari
  2014-07-31 22:33 ` [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard Antti Palosaari
  2014-07-31 22:33 ` [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver Antti Palosaari
@ 2014-07-31 22:33 ` Antti Palosaari
  2 siblings, 0 replies; 7+ messages in thread
From: Antti Palosaari @ 2014-07-31 22:33 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Add support for DD DuoFlex C/C2/T/T2 Expansion card. These are for
card revision that has Sony CXD2843ER, CXD2837ER or CXD2838ER
ISDB-T demodulator.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/pci/ddbridge/Kconfig         |   2 +
 drivers/media/pci/ddbridge/ddbridge-core.c | 127 +++++++++++++++++++++++++++++
 drivers/media/pci/ddbridge/ddbridge.h      |   3 +
 3 files changed, 132 insertions(+)

diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig
index 44e5dc1..15f33a2 100644
--- a/drivers/media/pci/ddbridge/Kconfig
+++ b/drivers/media/pci/ddbridge/Kconfig
@@ -6,6 +6,8 @@ config DVB_DDBRIDGE
 	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  Support for cards with the Digital Devices PCI express bridge:
 	  - Octopus PCIe Bridge
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index da8f848..9f5837f 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -43,6 +43,8 @@
 #include "stv090x.h"
 #include "lnbh24.h"
 #include "drxk.h"
+#include "cxd2843.h"
+#include "tda18212.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -78,6 +80,21 @@ static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
 	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
 }
 
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0,
+			      .buf = data, .len = len};
+
+	return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, u8 reg, u8 val)
+{
+	u8 msg[2] = {reg, val};
+
+	return i2c_write(adap, adr, msg, 2);
+}
+
 static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
 {
 	struct ddb *dev = i2c->dev;
@@ -592,6 +609,30 @@ static int demod_attach_drxk(struct ddb_input *input)
 	return 0;
 }
 
+static int demod_attach_cxd2843(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+	struct cxd2843_cfg cxd2843_0 = {
+		.adr = 0x6c,
+	};
+	struct cxd2843_cfg cxd2843_1 = {
+		.adr = 0x6d,
+	};
+
+	fe = input->fe = dvb_attach(cxd2843_attach, i2c,
+				  (input->nr & 1) ?
+				  &cxd2843_1 : &cxd2843_0);
+	if (!input->fe) {
+		pr_err("No cxd2837/38/43 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	return 0;
+}
+
 static int tuner_attach_tda18271(struct ddb_input *input)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
@@ -609,6 +650,47 @@ static int tuner_attach_tda18271(struct ddb_input *input)
 	return 0;
 }
 
+static struct tda18212_config tda18212_config_60 = {
+	.i2c_address = 0x60,
+	.if_dvbt_6 = 3550,
+	.if_dvbt_7 = 3700,
+	.if_dvbt_8 = 4150,
+	.if_dvbt2_6 = 3250,
+	.if_dvbt2_7 = 4000,
+	.if_dvbt2_8 = 4000,
+	.if_dvbc = 5000,
+};
+
+static struct tda18212_config tda18212_config_63 = {
+	.i2c_address = 0x63,
+	.if_dvbt_6 = 3550,
+	.if_dvbt_7 = 3700,
+	.if_dvbt_8 = 4150,
+	.if_dvbt2_6 = 3250,
+	.if_dvbt2_7 = 4000,
+	.if_dvbt2_8 = 4000,
+	.if_dvbc = 5000,
+};
+
+static int tuner_attach_tda18212(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+	struct tda18212_config *config;
+
+	if (input->nr & 1)
+		config = &tda18212_config_63;
+	else
+		config = &tda18212_config_60;
+
+	fe = dvb_attach(tda18212_attach, input->fe, i2c, config);
+	if (!fe) {
+		pr_err("No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
 /******************************************************************************/
 /******************************************************************************/
 /******************************************************************************/
@@ -887,6 +969,18 @@ static int dvb_input_attach(struct ddb_input *input)
 			       sizeof(struct dvb_tuner_ops));
 		}
 		break;
+	case DDB_TUNER_DVBCT2_SONY:
+	case DDB_TUNER_DVBC2T2_SONY:
+	case DDB_TUNER_ISDBT_SONY:
+		if (demod_attach_cxd2843(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212(input) < 0)
+			return -ENODEV;
+		if (input->fe) {
+			if (dvb_register_frontend(adap, input->fe) < 0)
+				return -ENODEV;
+		}
+		break;
 	}
 	input->attached = 5;
 	return 0;
@@ -1170,10 +1264,24 @@ static int port_has_drxks(struct ddb_port *port)
 	return 1;
 }
 
+static int port_has_cxd28xx(struct ddb_port *port, u8 *id)
+{
+	int status;
+
+	status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0);
+	if (status)
+		return 0;
+	status = i2c_read_reg(&port->i2c->adap, 0x6e, 0xfd, id);
+	if (status)
+		return 0;
+	return 1;
+}
+
 static void ddb_port_probe(struct ddb_port *port)
 {
 	struct ddb *dev = port->dev;
 	char *modname = "NO MODULE";
+	u8 id;
 
 	port->class = DDB_PORT_NONE;
 
@@ -1196,6 +1304,25 @@ static void ddb_port_probe(struct ddb_port *port)
 		port->class = DDB_PORT_TUNER;
 		port->type = DDB_TUNER_DVBCT_TR;
 		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_cxd28xx(port, &id)) {
+		switch (id) {
+		case 0xa4:
+			modname = "DUAL DVB-C2T2 CXD2843";
+			port->type = DDB_TUNER_DVBC2T2_SONY;
+			break;
+		case 0xb1:
+			modname = "DUAL DVB-CT2 CXD2837";
+			port->type = DDB_TUNER_DVBCT2_SONY;
+			break;
+		case 0xb0:
+			modname = "DUAL ISDB-T CXD2838";
+			port->type = DDB_TUNER_ISDBT_SONY;
+			break;
+		default:
+			return;
+		}
+		port->class = DDB_PORT_TUNER;
+		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
 	}
 	printk(KERN_INFO "Port %d (TAB %d): %s\n",
 			 port->nr, port->nr+1, modname);
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
index 8b1b41d..04c56c2 100644
--- a/drivers/media/pci/ddbridge/ddbridge.h
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -147,6 +147,9 @@ struct ddb_port {
 #define DDB_TUNER_DVBS_ST_AA    2
 #define DDB_TUNER_DVBCT_TR     16
 #define DDB_TUNER_DVBCT_ST     17
+#define DDB_TUNER_DVBCT2_SONY  18
+#define DDB_TUNER_ISDBT_SONY   19
+#define DDB_TUNER_DVBC2T2_SONY 20
 	u32                    adr;
 
 	struct ddb_input      *input[2];
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard
  2014-07-31 22:33 ` [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard Antti Palosaari
@ 2014-09-23 11:39   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2014-09-23 11:39 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Em Fri,  1 Aug 2014 01:33:06 +0300
Antti Palosaari <crope@iki.fi> escreveu:

> Just add delivery system for DVB-C2 standard. Other parameters
> should be added later.

The best is to add the parameters altogether, as:

1) We need to add the corresponding bits at the docbook;
2) We need to add support for it at libdvbv5.

Regards,
Mauro
> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  include/uapi/linux/dvb/frontend.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h
> index c56d77c..98648eb 100644
> --- a/include/uapi/linux/dvb/frontend.h
> +++ b/include/uapi/linux/dvb/frontend.h
> @@ -410,6 +410,7 @@ typedef enum fe_delivery_system {
>  	SYS_DVBT2,
>  	SYS_TURBO,
>  	SYS_DVBC_ANNEX_C,
> +	SYS_DVBC2,
>  } fe_delivery_system_t;
>  
>  /* backward compatibility */

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver
  2014-07-31 22:33 ` [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver Antti Palosaari
@ 2014-09-23 11:47   ` Mauro Carvalho Chehab
  2014-09-23 12:04     ` Antti Palosaari
  0 siblings, 1 reply; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2014-09-23 11:47 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Em Fri,  1 Aug 2014 01:33:07 +0300
Antti Palosaari <crope@iki.fi> escreveu:

> Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
> Driver taken from Digital Devices Linux driver package
> dddvb-0.9.15a.

Tried to ping you about that todad on IRC. For now, I'm seeing this as a
RFC patch, right?

It seems that there are some work to be done to make this to follow our
CodingStyle, like CamelCase enums and integers in uppercase, removing the
GNU address, etc.

Also, you'll likely want to convert it to use the REGMAP API.

So, for now I'll be tagging this as RFC at patchwork, together with the
corresponding patch series.

Regards,
Mauro

> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/dvb-frontends/Kconfig   |    8 +
>  drivers/media/dvb-frontends/Makefile  |    1 +
>  drivers/media/dvb-frontends/cxd2843.c | 2025 +++++++++++++++++++++++++++++++++
>  drivers/media/dvb-frontends/cxd2843.h |   30 +
>  4 files changed, 2064 insertions(+)
>  create mode 100644 drivers/media/dvb-frontends/cxd2843.c
>  create mode 100644 drivers/media/dvb-frontends/cxd2843.h
> 
> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> index fe0ddcc..5475f59 100644
> --- a/drivers/media/dvb-frontends/Kconfig
> +++ b/drivers/media/dvb-frontends/Kconfig
> @@ -72,6 +72,14 @@ config DVB_SI2165
>  
>  	  Say Y when you want to support this frontend.
>  
> +config DVB_CXD2843
> +	tristate "Sony CXD2843"
> +	depends on DVB_CORE && I2C
> +	default m if !MEDIA_SUBDRV_AUTOSELECT
> +	help
> +	  Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
> +	  Say Y when you want to support this frontend.
> +
>  comment "DVB-S (satellite) frontends"
>  	depends on DVB_CORE
>  
> diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
> index edf103d..9a9f131 100644
> --- a/drivers/media/dvb-frontends/Makefile
> +++ b/drivers/media/dvb-frontends/Makefile
> @@ -103,6 +103,7 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
>  obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
>  obj-$(CONFIG_DVB_STV0367) += stv0367.o
>  obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
> +obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
>  obj-$(CONFIG_DVB_DRXK) += drxk.o
>  obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
>  obj-$(CONFIG_DVB_SI2165) += si2165.o
> diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
> new file mode 100644
> index 0000000..10fc240
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/cxd2843.c
> @@ -0,0 +1,2025 @@
> +/*
> + * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator.
> + * Also supports the CXD2837ER DVB-T/T2/C and the
> + * CXD2838ER ISDB-T demodulator.
> + *
> + * Copyright (C) 2013-2014 Digital Devices GmbH
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 only, as published by the Free Software Foundation.
> + *
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> + * 02110-1301, USA
> + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/firmware.h>
> +#include <linux/i2c.h>
> +#include <linux/version.h>
> +#include <linux/mutex.h>
> +#include <asm/div64.h>
> +
> +#include "dvb_frontend.h"
> +#include "cxd2843.h"
> +
> +#define USE_ALGO 1
> +
> +enum EDemodType { CXD2843, CXD2837, CXD2838 };
> +enum EDemodState { Unknown, Shutdown, Sleep, ActiveT,
> +		   ActiveT2, ActiveC, ActiveC2, ActiveIT };
> +enum ET2Profile { T2P_Base, T2P_Lite };
> +enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC,
> +	     OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT };



> +
> +struct cxd_state {
> +	struct dvb_frontend   frontend;
> +	struct i2c_adapter   *i2c;
> +	struct mutex          mutex;
> +
> +	u8  adrt;
> +	u8  curbankt;
> +
> +	u8  adrx;
> +	u8  curbankx;
> +
> +	enum EDemodType  type;
> +	enum EDemodState state;
> +	enum ET2Profile T2Profile;
> +	enum omode omode;
> +
> +	u8    IF_FS;
> +	int   ContinuousClock;
> +	int   SerialMode;
> +	u8    SerialClockFrequency;
> +
> +	u32   LockTimeout;
> +	u32   TSLockTimeout;
> +	u32   L1PostTimeout;
> +	u32   DataSliceID;
> +	int   FirstTimeLock;
> +	u32   plp;
> +	u32   last_status;
> +
> +	u32   bandwidth;
> +	u32   bw;
> +
> +	unsigned long tune_time;
> +
> +	u32   LastBERNominator;
> +	u32   LastBERDenominator;
> +	u8    BERScaleMax;
> +};
> +
> +static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
> +{
> +	struct i2c_msg msg = {
> +		.addr = adr, .flags = 0, .buf = data, .len = len};
> +
> +	if (i2c_transfer(adap, &msg, 1) != 1) {
> +		pr_err("cxd2843: i2c_write error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int writeregs(struct cxd_state *state, u8 adr, u8 reg,
> +		     u8 *regd, u16 len)
> +{
> +	u8 data[len + 1];
> +
> +	data[0] = reg;
> +	memcpy(data + 1, regd, len);
> +	return i2c_write(state->i2c, adr, data, len + 1);
> +}
> +
> +static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat)
> +{
> +	u8 mm[2] = {reg, dat};
> +
> +	return i2c_write(state->i2c, adr, mm, 2);
> +}
> +
> +static int i2c_read(struct i2c_adapter *adap,
> +		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
> +{
> +	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
> +				     .buf = msg, .len = len},
> +				   { .addr = adr, .flags = I2C_M_RD,
> +				     .buf = answ, .len = alen } };
> +	if (i2c_transfer(adap, msgs, 2) != 2) {
> +		pr_err("cxd2843: i2c_read error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int readregs(struct cxd_state *state, u8 adr, u8 reg,
> +		    u8 *val, int count)
> +{
> +	return i2c_read(state->i2c, adr, &reg, 1, val, count);
> +}
> +
> +static int readregst_unlocked(struct cxd_state *cxd, u8 bank,
> +			      u8 Address, u8 *pValue, u16 count)
> +{
> +	int status = 0;
> +
> +	if (bank != 0xFF && cxd->curbankt != bank) {
> +		status = writereg(cxd, cxd->adrt, 0, bank);
> +		if (status < 0) {
> +			cxd->curbankt = 0xFF;
> +			return status;
> +		}
> +		cxd->curbankt = bank;
> +	}
> +	status = readregs(cxd, cxd->adrt, Address, pValue, count);
> +	return status;
> +}
> +
> +static int readregst(struct cxd_state *cxd, u8 Bank,
> +		     u8 Address, u8 *pValue, u16 count)
> +{
> +	int status;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = readregst_unlocked(cxd, Bank, Address, pValue, count);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank,
> +			      u8 Address, u8 *pValue, u16 count)
> +{
> +	int status = 0;
> +
> +	if (Bank != 0xFF && cxd->curbankx != Bank) {
> +		status = writereg(cxd, cxd->adrx, 0, Bank);
> +		if (status < 0) {
> +			cxd->curbankx = 0xFF;
> +			return status;
> +		}
> +		cxd->curbankx = Bank;
> +	}
> +	status = readregs(cxd, cxd->adrx, Address, pValue, count);
> +	return status;
> +}
> +
> +static int readregsx(struct cxd_state *cxd, u8 Bank,
> +		     u8 Address, u8 *pValue, u16 count)
> +{
> +	int status;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = readregsx_unlocked(cxd, Bank, Address, pValue, count);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank,
> +			       u8 Address, u8 *pValue, u16 count)
> +{
> +	int status = 0;
> +
> +	if (Bank != 0xFF && cxd->curbankx != Bank) {
> +		status = writereg(cxd, cxd->adrx, 0, Bank);
> +		if (status < 0) {
> +			cxd->curbankx = 0xFF;
> +			return status;
> +		}
> +		cxd->curbankx = Bank;
> +	}
> +	status = writeregs(cxd, cxd->adrx, Address, pValue, count);
> +	return status;
> +}
> +
> +static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address,
> +		      u8 *pValue, u16 count)
> +{
> +	int status;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = writeregsx_unlocked(cxd, Bank, Address, pValue, count);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
> +{
> +	return writeregsx(cxd, Bank, Address, &val, 1);
> +}
> +
> +static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank,
> +			       u8 Address, u8 *pValue, u16 count)
> +{
> +	int status = 0;
> +
> +	if (Bank != 0xFF && cxd->curbankt != Bank) {
> +		status = writereg(cxd, cxd->adrt, 0, Bank);
> +		if (status < 0) {
> +			cxd->curbankt = 0xFF;
> +			return status;
> +		}
> +		cxd->curbankt = Bank;
> +	}
> +	status = writeregs(cxd, cxd->adrt, Address, pValue, count);
> +	return status;
> +}
> +
> +static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address,
> +		      u8 *pValue, u16 count)
> +{
> +	int status;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = writeregst_unlocked(cxd, Bank, Address, pValue, count);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
> +{
> +	return writeregst(cxd, Bank, Address, &val, 1);
> +}
> +
> +static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address,
> +		      u8 Value, u8 Mask)
> +{
> +	int status = 0;
> +	u8 tmp;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1);
> +	if (status < 0)
> +		return status;
> +	tmp = (tmp & ~Mask) | Value;
> +	status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address,
> +		      u8 Value, u8 Mask)
> +{
> +	int status = 0;
> +	u8 Tmp = 0x00;
> +
> +	mutex_lock(&cxd->mutex);
> +	status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1);
> +	if (status < 0)
> +		return status;
> +	Tmp = (Tmp & ~Mask) | Value;
> +	status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static int freeze_regst(struct cxd_state *cxd)
> +{
> +	mutex_lock(&cxd->mutex);
> +	return writereg(cxd, cxd->adrt, 1, 1);
> +}
> +
> +static int unfreeze_regst(struct cxd_state *cxd)
> +{
> +	int status = 0;
> +
> +	status = writereg(cxd, cxd->adrt, 1, 0);
> +	mutex_unlock(&cxd->mutex);
> +	return status;
> +}
> +
> +static inline u32 MulDiv32(u32 a, u32 b, u32 c)
> +{
> +	u64 tmp64;
> +
> +	tmp64 = (u64)a * (u64)b;
> +	do_div(tmp64, c);
> +
> +	return (u32) tmp64;
> +}
> +
> +/* TPSData[0] [7:6]  CNST[1:0] */
> +/* TPSData[0] [5:3]  HIER[2:0] */
> +/* TPSData[0] [2:0]  HRATE[2:0] */
> +/* TPSData[1] [7:5]  LRATE[2:0] */
> +/* TPSData[1] [4:3]  GI[1:0] */
> +/* TPSData[1] [2:1]  MODE[1:0] */
> +/* TPSData[2] [7:6]  FNUM[1:0] */
> +/* TPSData[2] [5:0]  LENGTH_INDICATOR[5:0] */
> +/* TPSData[3] [7:0]  CELLID[15:8] */
> +/* TPSData[4] [7:0]  CELLID[7:0] */
> +/* TPSData[5] [5:0]  RESERVE_EVEN[5:0] */
> +/* TPSData[6] [5:0]  RESERVE_ODD[5:0] */
> +
> +static int read_tps(struct cxd_state *state, u8 *tps)
> +{
> +	if (state->last_status != 0x1f)
> +		return 0;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x10, 0x2f, tps, 7);
> +	unfreeze_regst(state);
> +	return 0;
> +}
> +
> +static void Active_to_Sleep(struct cxd_state *state)
> +{
> +	if (state->state <= Sleep)
> +		return;
> +
> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
> +	state->state = Sleep;
> +}
> +
> +static void ActiveT2_to_Sleep(struct cxd_state *state)
> +{
> +	if (state->state <= Sleep)
> +		return;
> +
> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
> +
> +	writeregt(state, 0x13, 0x83, 0x40);
> +	writeregt(state, 0x13, 0x86, 0x21);
> +	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
> +	writeregt(state, 0x13, 0x9F, 0xFB);
> +
> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
> +	state->state = Sleep;
> +}
> +
> +static void ActiveC2_to_Sleep(struct cxd_state *state)
> +{
> +	if (state->state <= Sleep)
> +		return;
> +
> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
> +
> +	writeregt(state, 0x20, 0xC2, 0x11);
> +	writebitst(state, 0x25, 0x6A, 0x02, 0x03);
> +	{
> +		static u8 data[3] = { 0x07, 0x61, 0x36 };
> +		writeregst(state, 0x25, 0x89, data, sizeof(data));
> +	}
> +	writebitst(state, 0x25, 0xCB, 0x05, 0x07);
> +	{
> +		static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 };
> +		writeregst(state, 0x25, 0xDC, data, sizeof(data));
> +	}
> +	writeregt(state, 0x25, 0xE2, 0x2F);
> +	writeregt(state, 0x25, 0xE5, 0x2F);
> +	writebitst(state, 0x27, 0x20, 0x00, 0x01);
> +	writebitst(state, 0x27, 0x35, 0x00, 0x01);
> +	writebitst(state, 0x27, 0xD9, 0x19, 0x3F);
> +	writebitst(state, 0x2A, 0x78, 0x01, 0x07);
> +	writeregt(state, 0x2A, 0x86, 0x08);
> +	writeregt(state, 0x2A, 0x88, 0x14);
> +	writebitst(state, 0x2B, 0x2B, 0x00, 0x1F);
> +	{
> +		u8 data[2] = { 0x75, 0x75 };
> +		writeregst(state, 0x2D, 0x24, data, sizeof(data));
> +	}
> +
> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
> +	state->state = Sleep;
> +}
> +
> +static int ConfigureTS(struct cxd_state *state,
> +		       enum EDemodState newDemodState)
> +{
> +	int status = 0;
> +	u8 OSERCKMODE = state->SerialMode ?  1 : 0;
> +	u8 OSERDUTYMODE = state->SerialMode ?  1 : 0;
> +	u8 OTSCKPERIOD = 8;
> +	u8 OREG_CKSEL_TSIF = state->SerialMode ?
> +		state->SerialClockFrequency : 0;
> +
> +	if (state->SerialMode && state->SerialClockFrequency >= 3) {
> +		OSERCKMODE = 2;
> +		OSERDUTYMODE = 2;
> +		OTSCKPERIOD = 16;
> +		OREG_CKSEL_TSIF = state->SerialClockFrequency - 3;
> +	}
> +	writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */
> +	writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */
> +	writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */
> +	writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */
> +	/* OREG_CKSEL_TSIF */
> +	writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03);
> +	writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */
> +
> +	if (newDemodState == ActiveT)
> +		writebitst(state, 0x10, 0x66, 0x01, 0x01);
> +	if (newDemodState == ActiveC)
> +		writebitst(state, 0x40, 0x66, 0x01, 0x01);
> +
> +	return status;
> +}
> +
> +static void BandSettingT(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
> +
> +	switch (state->bw) {
> +	default:
> +	case 8:
> +	{
> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		u8 CL_data[] = { 0x01, 0xE0 };
> +		u8 NF_data[] = { 0x01, 0x02 };
> +
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
> +		break;
> +	}
> +	case 7:
> +	{
> +		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
> +		u8 CL_data[] = { 0x12, 0xF8 };
> +		u8 NF_data[] = { 0x00, 0x03 };
> +
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
> +		break;
> +	}
> +	case 6:
> +	{
> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		u8 CL_data[] = { 0x1F, 0xDC };
> +		u8 NF_data[] = { 0x00, 0x03 };
> +
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
> +		break;
> +	}
> +	case 5:
> +	{
> +		static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
> +		static u8 CL_data[] = { 0x26, 0x3C };
> +		static u8 NF_data[] = { 0x00, 0x03 };
> +
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
> +		break;
> +	}
> +	}
> +}
> +
> +static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq)
> +{
> +	ConfigureTS(state, ActiveT);
> +	writeregx(state, 0x00, 0x17, 0x01);   /* Mode */
> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
> +	{
> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
> +	}
> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
> +
> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */
> +	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
> +
> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
> +
> +	writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */
> +	writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */
> +	writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */
> +
> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
> +
> +	BandSettingT(state, iffreq);
> +
> +	writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */
> +
> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
> +}
> +
> +static void BandSettingT2(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff,
> +			 iffreq & 0xff};
> +
> +	switch (state->bw) {
> +	default:
> +	case 8:
> +	{
> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		/* Timing recovery */
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		/* Add EQ Optimisation for tuner here */
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		/* System Bandwidth */
> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
> +	}
> +	break;
> +	case 7:
> +	{
> +		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
> +	}
> +	break;
> +	case 6:
> +	{
> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
> +	}
> +	break;
> +	case 5:
> +	{
> +		u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
> +	}
> +	break;
> +	case 2: /* 1.7 MHz */
> +	{
> +		u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC };
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x03, 0x07);
> +	}
> +	break;
> +	}
> +}
> +
> +
> +static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq)
> +{
> +	ConfigureTS(state, ActiveT2);
> +
> +	writeregx(state, 0x00, 0x17, 0x02);   /* Mode */
> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
> +
> +	{
> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
> +	}
> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
> +
> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
> +	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
> +
> +	writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */
> +	writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */
> +
> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
> +
> +	writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */
> +	writeregt(state, 0x13, 0x86, 0x34);
> +	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
> +	writeregt(state, 0x13, 0x9F, 0xD8);
> +
> +	BandSettingT2(state, iffreq);
> +
> +	writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */
> +
> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
> +}
> +
> +
> +static void BandSettingC(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 data[3];
> +
> +	data[0] = (iffreq >> 16) & 0xFF;
> +	data[1] = (iffreq >>  8) & 0xFF;
> +	data[2] = (iffreq) & 0xFF;
> +	writeregst(state, 0x10, 0xB6, data, 3);
> +}
> +
> +static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq)
> +{
> +	ConfigureTS(state, ActiveC);
> +
> +	writeregx(state, 0x00, 0x17, 0x04);   /* Mode */
> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
> +
> +	{
> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
> +	}
> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
> +
> +	writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */
> +	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
> +
> +	writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */
> +
> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
> +
> +	BandSettingC(state, iffreq);
> +
> +	writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */
> +
> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
> +}
> +
> +static void BandSettingC2(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
> +
> +	switch (state->bw) {
> +	default:
> +	case 8:
> +	{
> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		u8 data[2] = { 0x11, 0x9E };
> +
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
> +		writeregst(state, 0x50, 0xEC, data, sizeof(data));
> +		writeregt(state, 0x50, 0xEF, 0x11);
> +		writeregt(state, 0x50, 0xF1, 0x9E);
> +	}
> +	break;
> +	case 6:
> +	{
> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		u8 data[2] = { 0x17, 0x70 };
> +
> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
> +		writeregst(state, 0x50, 0xEC, data, sizeof(data));
> +		writeregt(state, 0x50, 0xEF, 0x17);
> +		writeregt(state, 0x50, 0xF1, 0x70);
> +	}
> +	break;
> +	}
> +}
> +
> +static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq)
> +{
> +	ConfigureTS(state, ActiveC2);
> +
> +	writeregx(state, 0x00, 0x17, 0x05);   /* Mode */
> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
> +
> +	{
> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
> +		writeregst(state, 0x00, 0x43, data, sizeof(data));
> +		/* Enable ADC 2+3 */
> +	}
> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
> +
> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
> +	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
> +
> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
> +
> +	writeregt(state, 0x20, 0xC2, 0x00);
> +	writebitst(state, 0x25, 0x6A, 0x00, 0x03);
> +	{
> +		u8 data[3] = { 0x0C, 0xD1, 0x40 };
> +		writeregst(state, 0x25, 0x89, data, sizeof(data));
> +	}
> +	writebitst(state, 0x25, 0xCB, 0x01, 0x07);
> +	{
> +		u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 };
> +		writeregst(state, 0x25, 0xDC, data, sizeof(data));
> +	}
> +	writeregt(state, 0x25, 0xE2, 0x30);
> +	writeregt(state, 0x25, 0xE5, 0x30);
> +	writebitst(state, 0x27, 0x20, 0x01, 0x01);
> +	writebitst(state, 0x27, 0x35, 0x01, 0x01);
> +	writebitst(state, 0x27, 0xD9, 0x18, 0x3F);
> +	writebitst(state, 0x2A, 0x78, 0x00, 0x07);
> +	writeregt(state, 0x2A, 0x86, 0x20);
> +	writeregt(state, 0x2A, 0x88, 0x32);
> +	writebitst(state, 0x2B, 0x2B, 0x10, 0x1F);
> +	{
> +		u8 data[2] = { 0x01, 0x01 };
> +		writeregst(state, 0x2D, 0x24, data, sizeof(data));
> +	}
> +
> +	BandSettingC2(state, iffreq);
> +
> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
> +}
> +
> +
> +static void BandSettingIT(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
> +
> +	switch (state->bw) {
> +	default:
> +	case 8:
> +	{
> +		u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */
> +		u8 CL_data[] = { 0x15, 0xA8 };
> +
> +		/*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		/* Add EQ Optimisation for tuner here */
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +
> +		writeregt(state, 0x10, 0xD7, 0x00);   /* System Bandwidth */
> +		/*u8 CL_data[] = { 0x13, 0xFC }; */
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +	}
> +	break;
> +	case 7:
> +	{
> +		u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 };
> +		u8 CL_data[] = { 0x1B, 0x5D };
> +
> +		/*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +
> +		writeregt(state, 0x10, 0xD7, 0x02);
> +		/*static u8 CL_data[] = { 0x1A, 0xFA };*/
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +	}
> +	break;
> +	case 6:
> +	{
> +		u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 };
> +		u8 CL_data[] = { 0x1F, 0xEC };
> +		/*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */
> +		/*u8 CL_data[] = { 0x1F, 0x79 }; */
> +
> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
> +		writeregt(state, 0x10, 0xD7, 0x04);
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
> +	}
> +	break;
> +	}
> +}
> +
> +static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq)
> +{
> +	u8 data2[3] = { 0xB9, 0xBA, 0x63 };  /* 20.5/41 MHz */
> +	/*u8 data2[3] = { 0xB7,0x1B,0x00 }; */  /* 24 MHz */
> +	u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */
> +	/*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */
> +
> +	pr_info("%s\n", __func__);
> +
> +	ConfigureTS(state, ActiveIT);
> +
> +	/* writeregx(state, 0x00,0x17,0x01); */  /* 2838 has only one Mode */
> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
> +
> +	{
> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz, 24 MHz */
> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
> +	}
> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
> +
> +	writeregst(state, 0x60, 0xA8, data2, sizeof(data2));
> +
> +	writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data));
> +
> +	writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */
> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
> +
> +	BandSettingIT(state, iffreq);
> +
> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
> +}
> +
> +static void T2_SetParameters(struct cxd_state *state)
> +{
> +	u8 Profile = 0x01;    /* Profile Base */
> +	u8 notT2time = 12;    /* early unlock detection time */
> +
> +	if (state->T2Profile == T2P_Lite) {
> +		Profile = 0x05;
> +		notT2time = 40;
> +	}
> +
> +	if (state->plp != 0xffffffff) {
> +		state->T2Profile = ((state->plp & 0x100) != 0) ?
> +			T2P_Lite : T2P_Base;
> +		writeregt(state, 0x23, 0xAF, state->plp);
> +		writeregt(state, 0x23, 0xAD, 0x01);
> +	} else {
> +		state->T2Profile = T2P_Base;
> +		writeregt(state, 0x23, 0xAD, 0x00);
> +	}
> +
> +	writebitst(state, 0x2E, 0x10, Profile, 0x07);
> +	writeregt(state, 0x2B, 0x19, notT2time);
> +}
> +
> +static void C2_ReleasePreset(struct cxd_state *state)
> +{
> +	{
> +		static u8 data[2] = { 0x02, 0x80};
> +		writeregst(state, 0x27, 0xF4, data, sizeof(data));
> +	}
> +	writebitst(state, 0x27, 0x51, 0x40, 0xF0);
> +	writebitst(state, 0x27, 0x73, 0x07, 0x0F);
> +	writebitst(state, 0x27, 0x74, 0x19, 0x3F);
> +	writebitst(state, 0x27, 0x75, 0x19, 0x3F);
> +	writebitst(state, 0x27, 0x76, 0x19, 0x3F);
> +	if (state->bw == 6) {
> +		static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA};
> +		writeregst(state, 0x20, 0x9F, data, sizeof(data));
> +	} else {
> +		static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00};
> +		writeregst(state, 0x20, 0x9F, data, sizeof(data));
> +	}
> +	writebitst(state, 0x27, 0xC9, 0x07, 0x07);
> +	writebitst(state, 0x20, 0xC2, 0x11, 0x33);
> +	{
> +		static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8,
> +				       0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 };
> +		writeregst(state, 0x2A, 0x20, data, sizeof(data));
> +	}
> +	{
> +		static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 };
> +		writeregst(state, 0x50, 0x6B, data, sizeof(data));
> +	}
> +	writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */
> +}
> +
> +static void C2_DemodSetting2(struct cxd_state *state)
> +{
> +	u8 data[6];
> +	u32 TunePosition =
> +		state->frontend.dtv_property_cache.frequency / 1000;
> +
> +	if (state->bw == 6)
> +		TunePosition = ((TunePosition * 1792) / 3) / 1000;
> +	else
> +		TunePosition = (TunePosition * 448) / 1000;
> +
> +	TunePosition = ((TunePosition + 6) / 12) * 12;
> +
> +	pr_info("TunePosition = %u\n", TunePosition);
> +
> +	data[0] = ((TunePosition >> 16) & 0xFF);
> +	data[1] = ((TunePosition >>  8) & 0xFF);
> +	data[2] = (TunePosition & 0xFF);
> +	data[3] = 0x02;
> +	data[4] = (state->DataSliceID & 0xFF);
> +	data[5] = (state->plp & 0xFF);
> +	writeregst(state, 0x50, 0x7A, data, sizeof(data));
> +	writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */
> +}
> +
> +static void Stop(struct cxd_state *state)
> +{
> +
> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
> +}
> +
> +static void ShutDown(struct cxd_state *state)
> +{
> +	switch (state->state) {
> +	case ActiveT2:
> +		ActiveT2_to_Sleep(state);
> +		break;
> +	case ActiveC2:
> +		ActiveC2_to_Sleep(state);
> +		break;
> +	default:
> +		Active_to_Sleep(state);
> +		break;
> +	}
> +}
> +
> +static int gate_ctrl(struct dvb_frontend *fe, int enable)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +
> +	return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01);
> +}
> +
> +static void release(struct dvb_frontend *fe)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +
> +	Stop(state);
> +	ShutDown(state);
> +	kfree(state);
> +}
> +
> +static int Start(struct cxd_state *state, u32 IntermediateFrequency)
> +{
> +	enum EDemodState newDemodState = Unknown;
> +	u32 iffreq;
> +
> +	if (state->state < Sleep)
> +		return -EINVAL;
> +
> +	iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000);
> +
> +	switch (state->omode) {
> +	case OM_DVBT:
> +		if (state->type == CXD2838)
> +			return -EINVAL;
> +		newDemodState = ActiveT;
> +		break;
> +	case OM_DVBT2:
> +		if (state->type == CXD2838)
> +			return -EINVAL;
> +		newDemodState = ActiveT2;
> +		break;
> +	case OM_DVBC:
> +	case OM_QAM_ITU_C:
> +		if (state->type == CXD2838)
> +			return -EINVAL;
> +		newDemodState = ActiveC;
> +		break;
> +	case OM_DVBC2:
> +		if (state->type != CXD2843)
> +			return -EINVAL;
> +		newDemodState = ActiveC2;
> +		break;
> +	case OM_ISDBT:
> +		if (state->type != CXD2838)
> +			return -EINVAL;
> +		newDemodState = ActiveIT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	state->LockTimeout = 0;
> +	state->TSLockTimeout = 0;
> +	state->L1PostTimeout = 0;
> +	state->last_status = 0;
> +	state->FirstTimeLock = 1;
> +	state->LastBERNominator = 0;
> +	state->LastBERDenominator = 1;
> +	state->BERScaleMax = 19;
> +
> +	if (state->state == newDemodState) {
> +		writeregt(state, 0x00, 0xC3, 0x01);   /* Disable TS Output */
> +		switch (newDemodState) {
> +		case ActiveT:
> +			/* Stick with HP ( 0x01 = LP ) */
> +			writeregt(state, 0x10, 0x67, 0x00);
> +			BandSettingT(state, iffreq);
> +			state->BERScaleMax = 18;
> +			break;
> +		case ActiveT2:
> +			T2_SetParameters(state);
> +			BandSettingT2(state, iffreq);
> +			state->BERScaleMax = 12;
> +			break;
> +		case ActiveC:
> +			BandSettingC(state, iffreq);
> +			state->BERScaleMax = 19;
> +			break;
> +		case ActiveC2:
> +			BandSettingC2(state, iffreq);
> +			C2_ReleasePreset(state);
> +			C2_DemodSetting2(state);
> +			break;
> +		case ActiveIT:
> +			BandSettingIT(state, iffreq);
> +			break;
> +		default:
> +			break;
> +		}
> +	} else {
> +		if (state->state > Sleep) {
> +			switch (state->state) {
> +			case ActiveT2:
> +				ActiveT2_to_Sleep(state);
> +				break;
> +			case ActiveC2:
> +				ActiveC2_to_Sleep(state);
> +				break;
> +			default:
> +				Active_to_Sleep(state);
> +				break;
> +			}
> +		}
> +		switch (newDemodState) {
> +		case ActiveT:
> +			/* Stick with HP ( 0x01 = LP ) */
> +			writeregt(state, 0x10, 0x67, 0x00);
> +			Sleep_to_ActiveT(state, iffreq);
> +			state->BERScaleMax = 18;
> +			break;
> +		case ActiveT2:
> +			T2_SetParameters(state);
> +			Sleep_to_ActiveT2(state, iffreq);
> +			state->BERScaleMax = 12;
> +			break;
> +		case ActiveC:
> +			Sleep_to_ActiveC(state, iffreq);
> +			state->BERScaleMax = 19;
> +			break;
> +		case ActiveC2:
> +			Sleep_to_ActiveC2(state, iffreq);
> +			C2_ReleasePreset(state);
> +			C2_DemodSetting2(state);
> +			break;
> +		case ActiveIT:
> +			Sleep_to_ActiveIT(state, iffreq);
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +	state->state = newDemodState;
> +	writeregt(state, 0x00, 0xFE, 0x01);   /* SW Reset */
> +	writeregt(state, 0x00, 0xC3, 0x00);   /* Enable TS Output */
> +
> +	return 0;
> +}
> +
> +static int set_parameters(struct dvb_frontend *fe)
> +{
> +	int stat;
> +	struct cxd_state *state = fe->demodulator_priv;
> +	u32 IF;
> +
> +	switch (fe->dtv_property_cache.delivery_system) {
> +	case SYS_DVBC_ANNEX_A:
> +		state->omode = OM_DVBC;
> +		break;
> +	case SYS_DVBC2:
> +		state->omode = OM_DVBC2;
> +		break;
> +	case SYS_DVBT:
> +		state->omode = OM_DVBT;
> +		break;
> +	case SYS_DVBT2:
> +		state->omode = OM_DVBT2;
> +		break;
> +	case SYS_ISDBT:
> +		state->omode = OM_ISDBT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (fe->ops.tuner_ops.set_params)
> +		fe->ops.tuner_ops.set_params(fe);
> +	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
> +	state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000;
> +	if (fe->dtv_property_cache.stream_id == 0xffffffff) {
> +		state->DataSliceID = 0xffffffff;
> +		state->plp = 0xffffffff;
> +	} else {
> +		state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8)
> +			& 0xff;
> +		state->plp = fe->dtv_property_cache.stream_id & 0xff;
> +	}
> +	/* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */
> +	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
> +	stat = Start(state, IF);
> +	return stat;
> +}
> +
> +
> +static void init(struct cxd_state *state)
> +{
> +	u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */
> +
> +	state->omode = OM_NONE;
> +	state->state   = Unknown;
> +
> +	writeregx(state, 0xFF, 0x02, 0x00);
> +	usleep_range(4000, 5000);
> +	writeregx(state, 0x00, 0x15, 0x01);
> +	if (state->type != CXD2838)
> +		writeregx(state, 0x00, 0x17, 0x01);
> +	usleep_range(4000, 5000);
> +
> +	writeregx(state, 0x00, 0x10, 0x01);
> +
> +	writeregsx(state, 0x00, 0x13, data, 2);
> +	writeregx(state, 0x00, 0x15, 0x00);
> +	usleep_range(3000, 4000);
> +	writeregx(state, 0x00, 0x10, 0x00);
> +	usleep_range(2000, 3000);
> +
> +	state->curbankx = 0xFF;
> +	state->curbankt = 0xFF;
> +
> +	writeregt(state, 0x00, 0x43, 0x0A);
> +	writeregt(state, 0x00, 0x41, 0x0A);
> +	if (state->type == CXD2838)
> +		writeregt(state, 0x60, 0x5A, 0x00);
> +
> +	writebitst(state, 0x10, 0xCB, 0x00, 0x40);
> +	writeregt(state, 0x10, 0xCD, state->IF_FS);
> +
> +	writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98);
> +	writebitst(state, 0x00, 0xC5, 0x01, 0x07);
> +	writebitst(state, 0x00, 0xCB, 0x00, 0x01);
> +	writebitst(state, 0x00, 0xC6, 0x00, 0x1D);
> +	writebitst(state, 0x00, 0xC8, 0x01, 0x1D);
> +	writebitst(state, 0x00, 0xC9, 0x00, 0x1D);
> +	writebitst(state, 0x00, 0x83, 0x00, 0x07);
> +	writeregt(state, 0x00, 0x84, 0x00);
> +	writebitst(state, 0x00, 0xD3,
> +		   (state->type == CXD2838) ? 0x01 : 0x00, 0x01);
> +	writebitst(state, 0x00, 0xDE, 0x00, 0x01);
> +
> +	state->state = Sleep;
> +}
> +
> +
> +static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg)
> +{
> +	state->adrt = cfg->adr;
> +	state->adrx = cfg->adr + 0x02;
> +	state->curbankt = 0xff;
> +	state->curbankx = 0xff;
> +	mutex_init(&state->mutex);
> +
> +	state->SerialMode = cfg->parallel ? 0 : 1;
> +	state->ContinuousClock = 1;
> +	state->SerialClockFrequency =
> +		(cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ?
> +		cfg->ts_clock :  1; /* 1 = fastest (82 MBit/s), 5 = slowest */
> +	state->SerialClockFrequency = 1;
> +	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */
> +	state->IF_FS = 0x50;
> +}
> +
> +static int get_tune_settings(struct dvb_frontend *fe,
> +			     struct dvb_frontend_tune_settings *sets)
> +{
> +	switch (fe->dtv_property_cache.delivery_system) {
> +	case SYS_DVBC_ANNEX_A:
> +	case SYS_DVBC_ANNEX_C:
> +		/*return c_get_tune_settings(fe, sets);*/
> +	default:
> +		/* DVB-T: Use info.frequency_stepsize. */
> +		return -EINVAL;
> +	}
> +}
> +
> +static int read_status(struct dvb_frontend *fe, fe_status_t *status)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +	u8 rdata;
> +
> +	*status = 0;
> +	switch (state->state) {
> +	case ActiveC:
> +		readregst(state, 0x40, 0x88, &rdata, 1);
> +		if (rdata & 0x02)
> +			break;
> +		if (rdata & 0x01) {
> +			*status |= 0x07;
> +			readregst(state, 0x40, 0x10, &rdata, 1);
> +			if (rdata & 0x20)
> +				*status |= 0x1f;
> +		}
> +		break;
> +	case ActiveT:
> +		readregst(state, 0x10, 0x10, &rdata, 1);
> +		if (rdata & 0x10)
> +			break;
> +		if ((rdata & 0x07) == 0x06) {
> +			*status |= 0x07;
> +			if (rdata & 0x20)
> +				*status |= 0x1f;
> +		}
> +		break;
> +	case ActiveT2:
> +		readregst(state, 0x20, 0x10, &rdata, 1);
> +		if (rdata & 0x10)
> +			break;
> +		if ((rdata & 0x07) == 0x06) {
> +			*status |= 0x07;
> +			if (rdata & 0x20)
> +				*status |= 0x08;
> +		}
> +		if (*status & 0x08) {
> +			readregst(state, 0x22, 0x12, &rdata, 1);
> +			if (rdata & 0x01)
> +				*status |= 0x10;
> +		}
> +		break;
> +	case ActiveC2:
> +		readregst(state, 0x20, 0x10, &rdata, 1);
> +		if (rdata & 0x10)
> +			break;
> +		if ((rdata & 0x07) == 0x06) {
> +			*status |= 0x07;
> +			if (rdata & 0x20)
> +				*status |= 0x18;
> +		}
> +		if ((*status & 0x10) && state->FirstTimeLock) {
> +			u8 data;
> +
> +			/* Change1stTrial */
> +			readregst(state, 0x28, 0xE6, &rdata, 1);
> +			data = rdata & 1;
> +			readregst(state, 0x50, 0x15, &rdata, 1);
> +			data |= ((rdata & 0x18) >> 2);
> +			/*writebitst(state, 0x50,0x6F,rdata,0x07);*/
> +			state->FirstTimeLock = 0;
> +		}
> +		break;
> +	case ActiveIT:
> +		readregst(state, 0x60, 0x10, &rdata, 1);
> +		if (rdata & 0x10)
> +			break;
> +		if (rdata & 0x02) {
> +			*status |= 0x07;
> +			if (rdata & 0x01)
> +				*status |= 0x18;
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +	state->last_status = *status;
> +	return 0;
> +}
> +
> +static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d)
> +{
> +	u8 BERRegs[3];
> +	u8 Scale;
> +
> +	*n = 0;
> +	*d = 1;
> +
> +	readregst(state, 0x10, 0x62, BERRegs, 3);
> +	readregst(state, 0x10, 0x60, &Scale, 1);
> +	Scale &= 0x1F;
> +
> +	if (BERRegs[0] & 0x80) {
> +		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
> +			(((u32) BERRegs[1]) << 8) | BERRegs[2];
> +		state->LastBERDenominator = 1632 << Scale;
> +		if (state->LastBERNominator < 256 &&
> +		    Scale < state->BERScaleMax) {
> +			writebitst(state, 0x10, 0x60, Scale + 1, 0x1F);
> +		} else if (state->LastBERNominator > 512 && Scale > 11)
> +			writebitst(state, 0x10, 0x60, Scale - 1, 0x1F);
> +	}
> +	*n = state->LastBERNominator;
> +	*d = state->LastBERDenominator;
> +
> +	return 0;
> +}
> +
> +static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d)
> +{
> +	*n = 0;
> +	*d = 1;
> +	return 0;
> +}
> +
> +static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d)
> +{
> +	u8 BERRegs[3];
> +	u8 Scale;
> +
> +	*n = 0;
> +	*d = 1;
> +
> +	readregst(state, 0x40, 0x62, BERRegs, 3);
> +	readregst(state, 0x40, 0x60, &Scale, 1);
> +	Scale &= 0x1F;
> +
> +	if (BERRegs[0] & 0x80) {
> +		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
> +			(((u32) BERRegs[1]) << 8) | BERRegs[2];
> +		state->LastBERDenominator = 1632 << Scale;
> +		if (state->LastBERNominator < 256 &&
> +		    Scale < state->BERScaleMax) {
> +			writebitst(state, 0x40, 0x60, Scale + 1, 0x1F);
> +		} else if (state->LastBERNominator > 512 && Scale > 11)
> +			writebitst(state, 0x40, 0x60, Scale - 1, 0x1F);
> +	}
> +	*n = state->LastBERNominator;
> +	*d = state->LastBERDenominator;
> +
> +	return 0;
> +}
> +
> +static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d)
> +{
> +	*n = 0;
> +	*d = 1;
> +	return 0;
> +}
> +
> +static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d)
> +{
> +	*n = 0;
> +	*d = 1;
> +	return 0;
> +}
> +
> +static int read_ber(struct dvb_frontend *fe, u32 *ber)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +	u32 n, d;
> +	int s = 0;
> +
> +	*ber = 0;
> +	switch (state->state) {
> +	case ActiveT:
> +		s = get_ber_t(state, &n, &d);
> +		break;
> +	case ActiveT2:
> +		s = get_ber_t2(state, &n, &d);
> +		break;
> +	case ActiveC:
> +		s = get_ber_c(state, &n, &d);
> +		break;
> +	case ActiveC2:
> +		s = get_ber_c2(state, &n, &d);
> +		break;
> +	case ActiveIT:
> +		s = get_ber_it(state, &n, &d);
> +		break;
> +	default:
> +		break;
> +	}
> +	if (s)
> +		return s;
> +
> +	return 0;
> +}
> +
> +static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
> +{
> +	if (fe->ops.tuner_ops.get_rf_strength)
> +		fe->ops.tuner_ops.get_rf_strength(fe, strength);
> +	else
> +		*strength = 0;
> +	return 0;
> +}
> +
> +static s32 Log10x100(u32 x)
> +{
> +	static u32 LookupTable[100] = {
> +		101157945, 103514217, 105925373, 108392691, 110917482,
> +		113501082, 116144861, 118850223, 121618600, 124451461,
> +		127350308, 130316678, 133352143, 136458314, 139636836,
> +		142889396, 146217717, 149623566, 153108746, 156675107,
> +		160324539, 164058977, 167880402, 171790839, 175792361,
> +		179887092, 184077200, 188364909, 192752491, 197242274,
> +		201836636, 206538016, 211348904, 216271852, 221309471,
> +		226464431, 231739465, 237137371, 242661010, 248313311,
> +		254097271, 260015956, 266072506, 272270131, 278612117,
> +		285101827, 291742701, 298538262, 305492111, 312607937,
> +		319889511, 327340695, 334965439, 342767787, 350751874,
> +		358921935, 367282300, 375837404, 384591782, 393550075,
> +		402717034, 412097519, 421696503, 431519077, 441570447,
> +		451855944, 462381021, 473151259, 484172368, 495450191,
> +		506990708, 518800039, 530884444, 543250331, 555904257,
> +		568852931, 582103218, 595662144, 609536897, 623734835,
> +		638263486, 653130553, 668343918, 683911647, 699841996,
> +		716143410, 732824533, 749894209, 767361489, 785235635,
> +		803526122, 822242650, 841395142, 860993752, 881048873,
> +		901571138, 922571427, 944060876, 966050879, 988553095,
> +	};
> +	s32 y;
> +	int i;
> +
> +	if (x == 0)
> +		return 0;
> +	y = 800;
> +	if (x >= 1000000000) {
> +		x /= 10;
> +		y += 100;
> +	}
> +
> +	while (x < 100000000) {
> +		x *= 10;
> +		y -= 100;
> +	}
> +	i = 0;
> +	while (i < 100 && x > LookupTable[i])
> +		i += 1;
> +	y += i;
> +	return y;
> +}
> +
> +#if 0
> +static void GetPLPIds(struct cxd_state *state, u32 nValues,
> +		      u8 *Values, u32 *Returned)
> +{
> +	u8 nPids = 0;
> +
> +	*Returned = 0;
> +	if (state->state != ActiveT2)
> +		return;
> +	if (state->last_status != 0x1f)
> +		return;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x22, 0x7F, &nPids, 1);
> +
> +	Values[0] = nPids;
> +	if (nPids >= nValues)
> +		nPids = nValues - 1;
> +
> +	readregst_unlocked(state, 0x22, 0x80, &Values[1],
> +			   nPids > 128 ? 128 : nPids);
> +
> +	if (nPids > 128)
> +		readregst_unlocked(state, 0x23, 0x10, &Values[129],
> +				   nPids - 128);
> +
> +	*Returned = nPids + 1;
> +
> +	unfreeze_regst(state);
> +}
> +#endif
> +
> +static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u32 reg;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data));
> +	unfreeze_regst(state);
> +
> +	reg = (Data[0] << 8) | Data[1];
> +	if (reg > 51441)
> +		reg = 51441;
> +
> +	if (state->bw == 8) {
> +		if (reg > 1143)
> +			reg = 1143;
> +		*SignalToNoise = (Log10x100(reg) -
> +				  Log10x100(1200 - reg)) + 220;
> +	} else
> +		*SignalToNoise = Log10x100(reg) - 90;
> +}
> +
> +static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u32 reg;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
> +	unfreeze_regst(state);
> +
> +	reg = (Data[0] << 8) | Data[1];
> +	if (reg > 51441)
> +		reg = 51441;
> +
> +	*SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384;
> +}
> +
> +
> +static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u32 reg;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
> +	unfreeze_regst(state);
> +
> +	reg = (Data[0] << 8) | Data[1];
> +	if (reg > 10876)
> +		reg = 10876;
> +
> +	*SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320;
> +}
> +
> +static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u32 reg;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data));
> +	unfreeze_regst(state);
> +
> +	reg = (Data[0] << 8) | Data[1];
> +	if (reg > 4996)
> +		reg = 4996;
> +
> +	*SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285;
> +}
> +
> +static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u8 Constellation = 0;
> +	u32 reg;
> +
> +	*SignalToNoise = 0;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x40, 0x19, &Constellation, 1);
> +	readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data));
> +	unfreeze_regst(state);
> +
> +	reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]);
> +	if (reg == 0)
> +		return;
> +
> +	switch (Constellation & 0x07) {
> +	case 0: /* QAM 16 */
> +	case 2: /* QAM 64 */
> +	case 4: /* QAM 256 */
> +		if (reg < 126)
> +			reg = 126;
> +		*SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000;
> +		break;
> +	case 1: /* QAM 32 */
> +	case 3: /* QAM 128 */
> +		if (reg < 69)
> +			reg = 69;
> +		*SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000;
> +		break;
> +	}
> +}
> +
> +static int read_snr(struct dvb_frontend *fe, u16 *snr)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +	u32 SNR = 0;
> +
> +	*snr = 0;
> +	if (state->last_status != 0x1f)
> +		return 0;
> +
> +	switch (state->state) {
> +	case ActiveC:
> +		GetSignalToNoiseC(state, &SNR);
> +		break;
> +	case ActiveC2:
> +		GetSignalToNoiseC2(state, &SNR);
> +		break;
> +	case ActiveT:
> +		GetSignalToNoiseT(state, &SNR);
> +		break;
> +	case ActiveT2:
> +		GetSignalToNoiseT2(state, &SNR);
> +		break;
> +	case ActiveIT:
> +		GetSignalToNoiseIT(state, &SNR);
> +		break;
> +	default:
> +		break;
> +	}
> +	*snr = SNR;
> +	return 0;
> +}
> +
> +static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
> +{
> +	*ucblocks = 0;
> +	return 0;
> +}
> +
> +static int tune(struct dvb_frontend *fe, bool re_tune,
> +		unsigned int mode_flags,
> +		unsigned int *delay, fe_status_t *status)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +	int r;
> +
> +	if (re_tune) {
> +		r = set_parameters(fe);
> +		if (r)
> +			return r;
> +		state->tune_time = jiffies;
> +
> +	}
> +	if (*status & FE_HAS_LOCK)
> +		return 0;
> +	/* *delay = 50; */
> +	r = read_status(fe, status);
> +	if (r)
> +		return r;
> +	return 0;
> +}
> +
> +static enum dvbfe_search search(struct dvb_frontend *fe)
> +{
> +	int r;
> +	u32 loops = 20, i;
> +	fe_status_t status;
> +
> +	r = set_parameters(fe);
> +
> +	for (i = 0; i < loops; i++)  {
> +		msleep(50);
> +		r = read_status(fe, &status);
> +		if (r)
> +			return DVBFE_ALGO_SEARCH_ERROR;
> +		if (status & FE_HAS_LOCK)
> +			break;
> +	}
> +
> +	if (status & FE_HAS_LOCK)
> +		return DVBFE_ALGO_SEARCH_SUCCESS;
> +	else
> +		return DVBFE_ALGO_SEARCH_AGAIN;
> +}
> +
> +static int get_algo(struct dvb_frontend *fe)
> +{
> +	return DVBFE_ALGO_HW;
> +}
> +
> +static int get_fe_t(struct cxd_state *state)
> +{
> +	struct dvb_frontend *fe = &state->frontend;
> +	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
> +	u8 tps[7];
> +
> +	read_tps(state, tps);
> +
> +/*  TPSData[0] [7:6]  CNST[1:0]
> +    TPSData[0] [5:3]  HIER[2:0]
> +    TPSData[0] [2:0]  HRATE[2:0]
> +*/
> +	switch ((tps[0] >> 6) & 0x03) {
> +	case 0:
> +		p->modulation = QPSK;
> +		break;
> +	case 1:
> +		p->modulation = QAM_16;
> +		break;
> +	case 2:
> +		p->modulation = QAM_64;
> +		break;
> +	}
> +	switch ((tps[0] >> 3) & 0x07) {
> +	case 0:
> +		p->hierarchy = HIERARCHY_NONE;
> +		break;
> +	case 1:
> +		p->hierarchy = HIERARCHY_1;
> +		break;
> +	case 2:
> +		p->hierarchy = HIERARCHY_2;
> +		break;
> +	case 3:
> +		p->hierarchy = HIERARCHY_4;
> +		break;
> +	}
> +	switch ((tps[0] >> 0) & 0x07) {
> +	case 0:
> +		p->code_rate_HP = FEC_1_2;
> +		break;
> +	case 1:
> +		p->code_rate_HP = FEC_2_3;
> +		break;
> +	case 2:
> +		p->code_rate_HP = FEC_3_4;
> +		break;
> +	case 3:
> +		p->code_rate_HP = FEC_5_6;
> +		break;
> +	case 4:
> +		p->code_rate_HP = FEC_7_8;
> +		break;
> +	}
> +
> +/*  TPSData[1] [7:5]  LRATE[2:0]
> +    TPSData[1] [4:3]  GI[1:0]
> +    TPSData[1] [2:1]  MODE[1:0]
> +*/
> +	switch ((tps[1] >> 5) & 0x07) {
> +	case 0:
> +		p->code_rate_LP = FEC_1_2;
> +		break;
> +	case 1:
> +		p->code_rate_LP = FEC_2_3;
> +		break;
> +	case 2:
> +		p->code_rate_LP = FEC_3_4;
> +		break;
> +	case 3:
> +		p->code_rate_LP = FEC_5_6;
> +		break;
> +	case 4:
> +		p->code_rate_LP = FEC_7_8;
> +		break;
> +	}
> +	switch ((tps[1] >> 3) & 0x03) {
> +	case 0:
> +		p->guard_interval = GUARD_INTERVAL_1_32;
> +		break;
> +	case 1:
> +		p->guard_interval = GUARD_INTERVAL_1_16;
> +		break;
> +	case 2:
> +		p->guard_interval = GUARD_INTERVAL_1_8;
> +		break;
> +	case 3:
> +		p->guard_interval = GUARD_INTERVAL_1_4;
> +		break;
> +	}
> +	switch ((tps[1] >> 1) & 0x03) {
> +	case 0:
> +		p->transmission_mode = TRANSMISSION_MODE_2K;
> +		break;
> +	case 1:
> +		p->transmission_mode = TRANSMISSION_MODE_8K;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int get_fe_c(struct cxd_state *state)
> +{
> +	struct dvb_frontend *fe = &state->frontend;
> +	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
> +	u8 qam;
> +
> +	freeze_regst(state);
> +	readregst_unlocked(state, 0x40, 0x19, &qam, 1);
> +	unfreeze_regst(state);
> +	p->modulation = qam & 0x07;
> +	return 0;
> +}
> +
> +static int get_frontend(struct dvb_frontend *fe)
> +{
> +	struct cxd_state *state = fe->demodulator_priv;
> +
> +	if (state->last_status != 0x1f)
> +		return 0;
> +
> +	switch (state->state) {
> +	case ActiveT:
> +		get_fe_t(state);
> +		break;
> +	case ActiveT2:
> +		break;
> +	case ActiveC:
> +		get_fe_c(state);
> +		break;
> +	case ActiveC2:
> +		break;
> +	case ActiveIT:
> +		break;
> +	default:
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static struct dvb_frontend_ops common_ops_2843 = {
> +	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 },
> +	.info = {
> +		.name = "CXD2843 DVB-C/C2 DVB-T/T2",
> +		.frequency_stepsize = 166667,	/* DVB-T only */
> +		.frequency_min = 47000000,	/* DVB-T: 47125000 */
> +		.frequency_max = 865000000,	/* DVB-C: 862000000 */
> +		.symbol_rate_min = 870000,
> +		.symbol_rate_max = 11700000,
> +		.caps = /* DVB-C */
> +			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
> +			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
> +			FE_CAN_FEC_AUTO |
> +			/* DVB-T */
> +			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
> +			FE_CAN_TRANSMISSION_MODE_AUTO |
> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
> +	},
> +	.release = release,
> +	.i2c_gate_ctrl = gate_ctrl,
> +	.set_frontend = set_parameters,
> +
> +	.get_tune_settings = get_tune_settings,
> +	.read_status = read_status,
> +	.read_ber = read_ber,
> +	.read_signal_strength = read_signal_strength,
> +	.read_snr = read_snr,
> +	.read_ucblocks = read_ucblocks,
> +	.get_frontend = get_frontend,
> +#ifdef USE_ALGO
> +	.get_frontend_algo = get_algo,
> +	.search = search,
> +	.tune = tune,
> +#endif
> +};
> +
> +static struct dvb_frontend_ops common_ops_2837 = {
> +	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 },
> +	.info = {
> +		.name = "CXD2837 DVB-C DVB-T/T2",
> +		.frequency_stepsize = 166667,	/* DVB-T only */
> +		.frequency_min = 47000000,	/* DVB-T: 47125000 */
> +		.frequency_max = 865000000,	/* DVB-C: 862000000 */
> +		.symbol_rate_min = 870000,
> +		.symbol_rate_max = 11700000,
> +		.caps = /* DVB-C */
> +			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
> +			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
> +			FE_CAN_FEC_AUTO |
> +			/* DVB-T */
> +			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
> +			FE_CAN_TRANSMISSION_MODE_AUTO |
> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
> +	},
> +	.release = release,
> +	.i2c_gate_ctrl = gate_ctrl,
> +	.set_frontend = set_parameters,
> +
> +	.get_tune_settings = get_tune_settings,
> +	.read_status = read_status,
> +	.read_ber = read_ber,
> +	.read_signal_strength = read_signal_strength,
> +	.read_snr = read_snr,
> +	.read_ucblocks = read_ucblocks,
> +	.get_frontend = get_frontend,
> +#ifdef USE_ALGO
> +	.get_frontend_algo = get_algo,
> +	.search = search,
> +	.tune = tune,
> +#endif
> +};
> +
> +static struct dvb_frontend_ops common_ops_2838 = {
> +	.delsys = { SYS_ISDBT },
> +	.info = {
> +		.name = "CXD2838 ISDB-T",
> +		.frequency_stepsize = 166667,
> +		.frequency_min = 47000000,
> +		.frequency_max = 865000000,
> +		.symbol_rate_min = 870000,
> +		.symbol_rate_max = 11700000,
> +		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
> +			FE_CAN_TRANSMISSION_MODE_AUTO |
> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
> +	},
> +	.release = release,
> +	.i2c_gate_ctrl = gate_ctrl,
> +	.set_frontend = set_parameters,
> +
> +	.get_tune_settings = get_tune_settings,
> +	.read_status = read_status,
> +	.read_ber = read_ber,
> +	.read_signal_strength = read_signal_strength,
> +	.read_snr = read_snr,
> +	.read_ucblocks = read_ucblocks,
> +#ifdef USE_ALGO
> +	.get_frontend_algo = get_algo,
> +	.search = search,
> +	.tune = tune,
> +#endif
> +};
> +
> +static int probe(struct cxd_state *state)
> +{
> +	u8 ChipID = 0x00;
> +	int status;
> +
> +	status = readregst(state, 0x00, 0xFD, &ChipID, 1);
> +
> +	if (status)
> +		status = readregsx(state, 0x00, 0xFD, &ChipID, 1);
> +	if (status)
> +		return status;
> +
> +	/*printk("ChipID  = %02X\n", ChipID);*/
> +	switch (ChipID) {
> +	case 0xa4:
> +		state->type = CXD2843;
> +		memcpy(&state->frontend.ops, &common_ops_2843,
> +		       sizeof(struct dvb_frontend_ops));
> +		break;
> +	case 0xb1:
> +		state->type = CXD2837;
> +		memcpy(&state->frontend.ops, &common_ops_2837,
> +		       sizeof(struct dvb_frontend_ops));
> +		break;
> +	case 0xb0:
> +		state->type = CXD2838;
> +		memcpy(&state->frontend.ops, &common_ops_2838,
> +		       sizeof(struct dvb_frontend_ops));
> +		break;
> +	default:
> +		return -1;
> +	}
> +	state->frontend.demodulator_priv = state;
> +	return 0;
> +}
> +
> +struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
> +				    struct cxd2843_cfg *cfg)
> +{
> +	struct cxd_state *state = NULL;
> +
> +	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL);
> +	if (!state)
> +		return NULL;
> +
> +	state->i2c = i2c;
> +	init_state(state, cfg);
> +	if (probe(state) == 0) {
> +		init(state);
> +		return &state->frontend;
> +	}
> +	pr_err("cxd2843: not found\n");
> +	kfree(state);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(cxd2843_attach);
> +
> +MODULE_DESCRIPTION("CXD2843/37/38 driver");
> +MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h
> new file mode 100644
> index 0000000..f3e355b
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/cxd2843.h
> @@ -0,0 +1,30 @@
> +#ifndef _CXD2843_H_
> +#define _CXD2843_H_
> +
> +#include <linux/types.h>
> +#include <linux/i2c.h>
> +
> +struct cxd2843_cfg {
> +	u8  adr;
> +	u32 ts_clock;
> +	u8  parallel;
> +};
> +
> +#if defined(CONFIG_DVB_CXD2843) || \
> +	(defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE))
> +
> +extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
> +					   struct cxd2843_cfg *cfg);
> +
> +#else
> +
> +static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
> +					   struct cxd2843_cfg *cfg)
> +{
> +	pr_warn("%s: driver disabled by Kconfig\n", __func__);
> +	return NULL;
> +}
> +
> +#endif
> +
> +#endif

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver
  2014-09-23 11:47   ` Mauro Carvalho Chehab
@ 2014-09-23 12:04     ` Antti Palosaari
  0 siblings, 0 replies; 7+ messages in thread
From: Antti Palosaari @ 2014-09-23 12:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media

Consider it is a RFC. There is tons of things to do, review and fix 
issues. There is issues like missing DVB-C2 API, I2C model, style issues 
etc.

regards
Antti

On 09/23/2014 02:47 PM, Mauro Carvalho Chehab wrote:
> Em Fri,  1 Aug 2014 01:33:07 +0300
> Antti Palosaari <crope@iki.fi> escreveu:
>
>> Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
>> Driver taken from Digital Devices Linux driver package
>> dddvb-0.9.15a.
>
> Tried to ping you about that todad on IRC. For now, I'm seeing this as a
> RFC patch, right?
>
> It seems that there are some work to be done to make this to follow our
> CodingStyle, like CamelCase enums and integers in uppercase, removing the
> GNU address, etc.
>
> Also, you'll likely want to convert it to use the REGMAP API.
>
> So, for now I'll be tagging this as RFC at patchwork, together with the
> corresponding patch series.
>
> Regards,
> Mauro
>
>>
>> Signed-off-by: Antti Palosaari <crope@iki.fi>
>> ---
>>   drivers/media/dvb-frontends/Kconfig   |    8 +
>>   drivers/media/dvb-frontends/Makefile  |    1 +
>>   drivers/media/dvb-frontends/cxd2843.c | 2025 +++++++++++++++++++++++++++++++++
>>   drivers/media/dvb-frontends/cxd2843.h |   30 +
>>   4 files changed, 2064 insertions(+)
>>   create mode 100644 drivers/media/dvb-frontends/cxd2843.c
>>   create mode 100644 drivers/media/dvb-frontends/cxd2843.h
>>
>> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
>> index fe0ddcc..5475f59 100644
>> --- a/drivers/media/dvb-frontends/Kconfig
>> +++ b/drivers/media/dvb-frontends/Kconfig
>> @@ -72,6 +72,14 @@ config DVB_SI2165
>>
>>   	  Say Y when you want to support this frontend.
>>
>> +config DVB_CXD2843
>> +	tristate "Sony CXD2843"
>> +	depends on DVB_CORE && I2C
>> +	default m if !MEDIA_SUBDRV_AUTOSELECT
>> +	help
>> +	  Sony CXD2843 DVB-C/C2/T/T2 demodulator driver.
>> +	  Say Y when you want to support this frontend.
>> +
>>   comment "DVB-S (satellite) frontends"
>>   	depends on DVB_CORE
>>
>> diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
>> index edf103d..9a9f131 100644
>> --- a/drivers/media/dvb-frontends/Makefile
>> +++ b/drivers/media/dvb-frontends/Makefile
>> @@ -103,6 +103,7 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
>>   obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
>>   obj-$(CONFIG_DVB_STV0367) += stv0367.o
>>   obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
>> +obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
>>   obj-$(CONFIG_DVB_DRXK) += drxk.o
>>   obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
>>   obj-$(CONFIG_DVB_SI2165) += si2165.o
>> diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
>> new file mode 100644
>> index 0000000..10fc240
>> --- /dev/null
>> +++ b/drivers/media/dvb-frontends/cxd2843.c
>> @@ -0,0 +1,2025 @@
>> +/*
>> + * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator.
>> + * Also supports the CXD2837ER DVB-T/T2/C and the
>> + * CXD2838ER ISDB-T demodulator.
>> + *
>> + * Copyright (C) 2013-2014 Digital Devices GmbH
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * version 2 only, as published by the Free Software Foundation.
>> + *
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> + * 02110-1301, USA
>> + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/moduleparam.h>
>> +#include <linux/init.h>
>> +#include <linux/delay.h>
>> +#include <linux/firmware.h>
>> +#include <linux/i2c.h>
>> +#include <linux/version.h>
>> +#include <linux/mutex.h>
>> +#include <asm/div64.h>
>> +
>> +#include "dvb_frontend.h"
>> +#include "cxd2843.h"
>> +
>> +#define USE_ALGO 1
>> +
>> +enum EDemodType { CXD2843, CXD2837, CXD2838 };
>> +enum EDemodState { Unknown, Shutdown, Sleep, ActiveT,
>> +		   ActiveT2, ActiveC, ActiveC2, ActiveIT };
>> +enum ET2Profile { T2P_Base, T2P_Lite };
>> +enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC,
>> +	     OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT };
>
>
>
>> +
>> +struct cxd_state {
>> +	struct dvb_frontend   frontend;
>> +	struct i2c_adapter   *i2c;
>> +	struct mutex          mutex;
>> +
>> +	u8  adrt;
>> +	u8  curbankt;
>> +
>> +	u8  adrx;
>> +	u8  curbankx;
>> +
>> +	enum EDemodType  type;
>> +	enum EDemodState state;
>> +	enum ET2Profile T2Profile;
>> +	enum omode omode;
>> +
>> +	u8    IF_FS;
>> +	int   ContinuousClock;
>> +	int   SerialMode;
>> +	u8    SerialClockFrequency;
>> +
>> +	u32   LockTimeout;
>> +	u32   TSLockTimeout;
>> +	u32   L1PostTimeout;
>> +	u32   DataSliceID;
>> +	int   FirstTimeLock;
>> +	u32   plp;
>> +	u32   last_status;
>> +
>> +	u32   bandwidth;
>> +	u32   bw;
>> +
>> +	unsigned long tune_time;
>> +
>> +	u32   LastBERNominator;
>> +	u32   LastBERDenominator;
>> +	u8    BERScaleMax;
>> +};
>> +
>> +static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
>> +{
>> +	struct i2c_msg msg = {
>> +		.addr = adr, .flags = 0, .buf = data, .len = len};
>> +
>> +	if (i2c_transfer(adap, &msg, 1) != 1) {
>> +		pr_err("cxd2843: i2c_write error\n");
>> +		return -1;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int writeregs(struct cxd_state *state, u8 adr, u8 reg,
>> +		     u8 *regd, u16 len)
>> +{
>> +	u8 data[len + 1];
>> +
>> +	data[0] = reg;
>> +	memcpy(data + 1, regd, len);
>> +	return i2c_write(state->i2c, adr, data, len + 1);
>> +}
>> +
>> +static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat)
>> +{
>> +	u8 mm[2] = {reg, dat};
>> +
>> +	return i2c_write(state->i2c, adr, mm, 2);
>> +}
>> +
>> +static int i2c_read(struct i2c_adapter *adap,
>> +		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
>> +{
>> +	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
>> +				     .buf = msg, .len = len},
>> +				   { .addr = adr, .flags = I2C_M_RD,
>> +				     .buf = answ, .len = alen } };
>> +	if (i2c_transfer(adap, msgs, 2) != 2) {
>> +		pr_err("cxd2843: i2c_read error\n");
>> +		return -1;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int readregs(struct cxd_state *state, u8 adr, u8 reg,
>> +		    u8 *val, int count)
>> +{
>> +	return i2c_read(state->i2c, adr, &reg, 1, val, count);
>> +}
>> +
>> +static int readregst_unlocked(struct cxd_state *cxd, u8 bank,
>> +			      u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status = 0;
>> +
>> +	if (bank != 0xFF && cxd->curbankt != bank) {
>> +		status = writereg(cxd, cxd->adrt, 0, bank);
>> +		if (status < 0) {
>> +			cxd->curbankt = 0xFF;
>> +			return status;
>> +		}
>> +		cxd->curbankt = bank;
>> +	}
>> +	status = readregs(cxd, cxd->adrt, Address, pValue, count);
>> +	return status;
>> +}
>> +
>> +static int readregst(struct cxd_state *cxd, u8 Bank,
>> +		     u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = readregst_unlocked(cxd, Bank, Address, pValue, count);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank,
>> +			      u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status = 0;
>> +
>> +	if (Bank != 0xFF && cxd->curbankx != Bank) {
>> +		status = writereg(cxd, cxd->adrx, 0, Bank);
>> +		if (status < 0) {
>> +			cxd->curbankx = 0xFF;
>> +			return status;
>> +		}
>> +		cxd->curbankx = Bank;
>> +	}
>> +	status = readregs(cxd, cxd->adrx, Address, pValue, count);
>> +	return status;
>> +}
>> +
>> +static int readregsx(struct cxd_state *cxd, u8 Bank,
>> +		     u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = readregsx_unlocked(cxd, Bank, Address, pValue, count);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank,
>> +			       u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status = 0;
>> +
>> +	if (Bank != 0xFF && cxd->curbankx != Bank) {
>> +		status = writereg(cxd, cxd->adrx, 0, Bank);
>> +		if (status < 0) {
>> +			cxd->curbankx = 0xFF;
>> +			return status;
>> +		}
>> +		cxd->curbankx = Bank;
>> +	}
>> +	status = writeregs(cxd, cxd->adrx, Address, pValue, count);
>> +	return status;
>> +}
>> +
>> +static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address,
>> +		      u8 *pValue, u16 count)
>> +{
>> +	int status;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = writeregsx_unlocked(cxd, Bank, Address, pValue, count);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
>> +{
>> +	return writeregsx(cxd, Bank, Address, &val, 1);
>> +}
>> +
>> +static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank,
>> +			       u8 Address, u8 *pValue, u16 count)
>> +{
>> +	int status = 0;
>> +
>> +	if (Bank != 0xFF && cxd->curbankt != Bank) {
>> +		status = writereg(cxd, cxd->adrt, 0, Bank);
>> +		if (status < 0) {
>> +			cxd->curbankt = 0xFF;
>> +			return status;
>> +		}
>> +		cxd->curbankt = Bank;
>> +	}
>> +	status = writeregs(cxd, cxd->adrt, Address, pValue, count);
>> +	return status;
>> +}
>> +
>> +static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address,
>> +		      u8 *pValue, u16 count)
>> +{
>> +	int status;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = writeregst_unlocked(cxd, Bank, Address, pValue, count);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val)
>> +{
>> +	return writeregst(cxd, Bank, Address, &val, 1);
>> +}
>> +
>> +static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address,
>> +		      u8 Value, u8 Mask)
>> +{
>> +	int status = 0;
>> +	u8 tmp;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1);
>> +	if (status < 0)
>> +		return status;
>> +	tmp = (tmp & ~Mask) | Value;
>> +	status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address,
>> +		      u8 Value, u8 Mask)
>> +{
>> +	int status = 0;
>> +	u8 Tmp = 0x00;
>> +
>> +	mutex_lock(&cxd->mutex);
>> +	status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1);
>> +	if (status < 0)
>> +		return status;
>> +	Tmp = (Tmp & ~Mask) | Value;
>> +	status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static int freeze_regst(struct cxd_state *cxd)
>> +{
>> +	mutex_lock(&cxd->mutex);
>> +	return writereg(cxd, cxd->adrt, 1, 1);
>> +}
>> +
>> +static int unfreeze_regst(struct cxd_state *cxd)
>> +{
>> +	int status = 0;
>> +
>> +	status = writereg(cxd, cxd->adrt, 1, 0);
>> +	mutex_unlock(&cxd->mutex);
>> +	return status;
>> +}
>> +
>> +static inline u32 MulDiv32(u32 a, u32 b, u32 c)
>> +{
>> +	u64 tmp64;
>> +
>> +	tmp64 = (u64)a * (u64)b;
>> +	do_div(tmp64, c);
>> +
>> +	return (u32) tmp64;
>> +}
>> +
>> +/* TPSData[0] [7:6]  CNST[1:0] */
>> +/* TPSData[0] [5:3]  HIER[2:0] */
>> +/* TPSData[0] [2:0]  HRATE[2:0] */
>> +/* TPSData[1] [7:5]  LRATE[2:0] */
>> +/* TPSData[1] [4:3]  GI[1:0] */
>> +/* TPSData[1] [2:1]  MODE[1:0] */
>> +/* TPSData[2] [7:6]  FNUM[1:0] */
>> +/* TPSData[2] [5:0]  LENGTH_INDICATOR[5:0] */
>> +/* TPSData[3] [7:0]  CELLID[15:8] */
>> +/* TPSData[4] [7:0]  CELLID[7:0] */
>> +/* TPSData[5] [5:0]  RESERVE_EVEN[5:0] */
>> +/* TPSData[6] [5:0]  RESERVE_ODD[5:0] */
>> +
>> +static int read_tps(struct cxd_state *state, u8 *tps)
>> +{
>> +	if (state->last_status != 0x1f)
>> +		return 0;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x10, 0x2f, tps, 7);
>> +	unfreeze_regst(state);
>> +	return 0;
>> +}
>> +
>> +static void Active_to_Sleep(struct cxd_state *state)
>> +{
>> +	if (state->state <= Sleep)
>> +		return;
>> +
>> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
>> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
>> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
>> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
>> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
>> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
>> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
>> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
>> +	state->state = Sleep;
>> +}
>> +
>> +static void ActiveT2_to_Sleep(struct cxd_state *state)
>> +{
>> +	if (state->state <= Sleep)
>> +		return;
>> +
>> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
>> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
>> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
>> +
>> +	writeregt(state, 0x13, 0x83, 0x40);
>> +	writeregt(state, 0x13, 0x86, 0x21);
>> +	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
>> +	writeregt(state, 0x13, 0x9F, 0xFB);
>> +
>> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
>> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
>> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
>> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
>> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
>> +	state->state = Sleep;
>> +}
>> +
>> +static void ActiveC2_to_Sleep(struct cxd_state *state)
>> +{
>> +	if (state->state <= Sleep)
>> +		return;
>> +
>> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
>> +	writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */
>> +	writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */
>> +
>> +	writeregt(state, 0x20, 0xC2, 0x11);
>> +	writebitst(state, 0x25, 0x6A, 0x02, 0x03);
>> +	{
>> +		static u8 data[3] = { 0x07, 0x61, 0x36 };
>> +		writeregst(state, 0x25, 0x89, data, sizeof(data));
>> +	}
>> +	writebitst(state, 0x25, 0xCB, 0x05, 0x07);
>> +	{
>> +		static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 };
>> +		writeregst(state, 0x25, 0xDC, data, sizeof(data));
>> +	}
>> +	writeregt(state, 0x25, 0xE2, 0x2F);
>> +	writeregt(state, 0x25, 0xE5, 0x2F);
>> +	writebitst(state, 0x27, 0x20, 0x00, 0x01);
>> +	writebitst(state, 0x27, 0x35, 0x00, 0x01);
>> +	writebitst(state, 0x27, 0xD9, 0x19, 0x3F);
>> +	writebitst(state, 0x2A, 0x78, 0x01, 0x07);
>> +	writeregt(state, 0x2A, 0x86, 0x08);
>> +	writeregt(state, 0x2A, 0x88, 0x14);
>> +	writebitst(state, 0x2B, 0x2B, 0x00, 0x1F);
>> +	{
>> +		u8 data[2] = { 0x75, 0x75 };
>> +		writeregst(state, 0x2D, 0x24, data, sizeof(data));
>> +	}
>> +
>> +	writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */
>> +	writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */
>> +	writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */
>> +	writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */
>> +	writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */
>> +	state->state = Sleep;
>> +}
>> +
>> +static int ConfigureTS(struct cxd_state *state,
>> +		       enum EDemodState newDemodState)
>> +{
>> +	int status = 0;
>> +	u8 OSERCKMODE = state->SerialMode ?  1 : 0;
>> +	u8 OSERDUTYMODE = state->SerialMode ?  1 : 0;
>> +	u8 OTSCKPERIOD = 8;
>> +	u8 OREG_CKSEL_TSIF = state->SerialMode ?
>> +		state->SerialClockFrequency : 0;
>> +
>> +	if (state->SerialMode && state->SerialClockFrequency >= 3) {
>> +		OSERCKMODE = 2;
>> +		OSERDUTYMODE = 2;
>> +		OTSCKPERIOD = 16;
>> +		OREG_CKSEL_TSIF = state->SerialClockFrequency - 3;
>> +	}
>> +	writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */
>> +	writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */
>> +	writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */
>> +	writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */
>> +	/* OREG_CKSEL_TSIF */
>> +	writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03);
>> +	writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */
>> +
>> +	if (newDemodState == ActiveT)
>> +		writebitst(state, 0x10, 0x66, 0x01, 0x01);
>> +	if (newDemodState == ActiveC)
>> +		writebitst(state, 0x40, 0x66, 0x01, 0x01);
>> +
>> +	return status;
>> +}
>> +
>> +static void BandSettingT(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
>> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
>> +
>> +	switch (state->bw) {
>> +	default:
>> +	case 8:
>> +	{
>> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
>> +		u8 CL_data[] = { 0x01, 0xE0 };
>> +		u8 NF_data[] = { 0x01, 0x02 };
>> +
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
>> +		break;
>> +	}
>> +	case 7:
>> +	{
>> +		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
>> +		u8 CL_data[] = { 0x12, 0xF8 };
>> +		u8 NF_data[] = { 0x00, 0x03 };
>> +
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
>> +		break;
>> +	}
>> +	case 6:
>> +	{
>> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
>> +		u8 CL_data[] = { 0x1F, 0xDC };
>> +		u8 NF_data[] = { 0x00, 0x03 };
>> +
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
>> +		break;
>> +	}
>> +	case 5:
>> +	{
>> +		static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
>> +		static u8 CL_data[] = { 0x26, 0x3C };
>> +		static u8 NF_data[] = { 0x00, 0x03 };
>> +
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +		writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data));
>> +		break;
>> +	}
>> +	}
>> +}
>> +
>> +static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq)
>> +{
>> +	ConfigureTS(state, ActiveT);
>> +	writeregx(state, 0x00, 0x17, 0x01);   /* Mode */
>> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
>> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
>> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
>> +	{
>> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
>> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
>> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
>> +	}
>> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
>> +
>> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */
>> +	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
>> +
>> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
>> +
>> +	writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */
>> +	writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */
>> +	writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */
>> +
>> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
>> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
>> +
>> +	BandSettingT(state, iffreq);
>> +
>> +	writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */
>> +
>> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
>> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
>> +}
>> +
>> +static void BandSettingT2(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff,
>> +			 iffreq & 0xff};
>> +
>> +	switch (state->bw) {
>> +	default:
>> +	case 8:
>> +	{
>> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
>> +		/* Timing recovery */
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		/* Add EQ Optimisation for tuner here */
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		/* System Bandwidth */
>> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
>> +	}
>> +	break;
>> +	case 7:
>> +	{
>> +		u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x02, 0x07);
>> +	}
>> +	break;
>> +	case 6:
>> +	{
>> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
>> +	}
>> +	break;
>> +	case 5:
>> +	{
>> +		u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x06, 0x07);
>> +	}
>> +	break;
>> +	case 2: /* 1.7 MHz */
>> +	{
>> +		u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC };
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x03, 0x07);
>> +	}
>> +	break;
>> +	}
>> +}
>> +
>> +
>> +static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq)
>> +{
>> +	ConfigureTS(state, ActiveT2);
>> +
>> +	writeregx(state, 0x00, 0x17, 0x02);   /* Mode */
>> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
>> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
>> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
>> +
>> +	{
>> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
>> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
>> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
>> +	}
>> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
>> +
>> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
>> +	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
>> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
>> +
>> +	writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */
>> +	writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */
>> +
>> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
>> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
>> +
>> +	writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */
>> +	writeregt(state, 0x13, 0x86, 0x34);
>> +	writebitst(state, 0x13, 0x9E, 0x09, 0x0F);
>> +	writeregt(state, 0x13, 0x9F, 0xD8);
>> +
>> +	BandSettingT2(state, iffreq);
>> +
>> +	writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */
>> +
>> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
>> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
>> +}
>> +
>> +
>> +static void BandSettingC(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 data[3];
>> +
>> +	data[0] = (iffreq >> 16) & 0xFF;
>> +	data[1] = (iffreq >>  8) & 0xFF;
>> +	data[2] = (iffreq) & 0xFF;
>> +	writeregst(state, 0x10, 0xB6, data, 3);
>> +}
>> +
>> +static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq)
>> +{
>> +	ConfigureTS(state, ActiveC);
>> +
>> +	writeregx(state, 0x00, 0x17, 0x04);   /* Mode */
>> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
>> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
>> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
>> +
>> +	{
>> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
>> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
>> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
>> +	}
>> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
>> +
>> +	writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */
>> +	writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */
>> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
>> +
>> +	writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */
>> +
>> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
>> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
>> +
>> +	BandSettingC(state, iffreq);
>> +
>> +	writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */
>> +
>> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
>> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
>> +}
>> +
>> +static void BandSettingC2(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
>> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
>> +
>> +	switch (state->bw) {
>> +	default:
>> +	case 8:
>> +	{
>> +		u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
>> +		u8 data[2] = { 0x11, 0x9E };
>> +
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x00, 0x07);
>> +		writeregst(state, 0x50, 0xEC, data, sizeof(data));
>> +		writeregt(state, 0x50, 0xEF, 0x11);
>> +		writeregt(state, 0x50, 0xF1, 0x9E);
>> +	}
>> +	break;
>> +	case 6:
>> +	{
>> +		u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
>> +		u8 data[2] = { 0x17, 0x70 };
>> +
>> +		writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writebitst(state, 0x10, 0xD7, 0x04, 0x07);
>> +		writeregst(state, 0x50, 0xEC, data, sizeof(data));
>> +		writeregt(state, 0x50, 0xEF, 0x17);
>> +		writeregt(state, 0x50, 0xF1, 0x70);
>> +	}
>> +	break;
>> +	}
>> +}
>> +
>> +static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq)
>> +{
>> +	ConfigureTS(state, ActiveC2);
>> +
>> +	writeregx(state, 0x00, 0x17, 0x05);   /* Mode */
>> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
>> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
>> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
>> +
>> +	{
>> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz */
>> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
>> +		writeregst(state, 0x00, 0x43, data, sizeof(data));
>> +		/* Enable ADC 2+3 */
>> +	}
>> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
>> +
>> +	writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC  coarse gain */
>> +	writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */
>> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
>> +
>> +	writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */
>> +	writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/
>> +
>> +	writeregt(state, 0x20, 0xC2, 0x00);
>> +	writebitst(state, 0x25, 0x6A, 0x00, 0x03);
>> +	{
>> +		u8 data[3] = { 0x0C, 0xD1, 0x40 };
>> +		writeregst(state, 0x25, 0x89, data, sizeof(data));
>> +	}
>> +	writebitst(state, 0x25, 0xCB, 0x01, 0x07);
>> +	{
>> +		u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 };
>> +		writeregst(state, 0x25, 0xDC, data, sizeof(data));
>> +	}
>> +	writeregt(state, 0x25, 0xE2, 0x30);
>> +	writeregt(state, 0x25, 0xE5, 0x30);
>> +	writebitst(state, 0x27, 0x20, 0x01, 0x01);
>> +	writebitst(state, 0x27, 0x35, 0x01, 0x01);
>> +	writebitst(state, 0x27, 0xD9, 0x18, 0x3F);
>> +	writebitst(state, 0x2A, 0x78, 0x00, 0x07);
>> +	writeregt(state, 0x2A, 0x86, 0x20);
>> +	writeregt(state, 0x2A, 0x88, 0x32);
>> +	writebitst(state, 0x2B, 0x2B, 0x10, 0x1F);
>> +	{
>> +		u8 data[2] = { 0x01, 0x01 };
>> +		writeregst(state, 0x2D, 0x24, data, sizeof(data));
>> +	}
>> +
>> +	BandSettingC2(state, iffreq);
>> +
>> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
>> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
>> +}
>> +
>> +
>> +static void BandSettingIT(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 IF_data[3] = { (iffreq >> 16) & 0xff,
>> +			  (iffreq >> 8) & 0xff, iffreq & 0xff};
>> +
>> +	switch (state->bw) {
>> +	default:
>> +	case 8:
>> +	{
>> +		u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */
>> +		u8 CL_data[] = { 0x15, 0xA8 };
>> +
>> +		/*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		/* Add EQ Optimisation for tuner here */
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +
>> +		writeregt(state, 0x10, 0xD7, 0x00);   /* System Bandwidth */
>> +		/*u8 CL_data[] = { 0x13, 0xFC }; */
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +	}
>> +	break;
>> +	case 7:
>> +	{
>> +		u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 };
>> +		u8 CL_data[] = { 0x1B, 0x5D };
>> +
>> +		/*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +
>> +		writeregt(state, 0x10, 0xD7, 0x02);
>> +		/*static u8 CL_data[] = { 0x1A, 0xFA };*/
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +	}
>> +	break;
>> +	case 6:
>> +	{
>> +		u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 };
>> +		u8 CL_data[] = { 0x1F, 0xEC };
>> +		/*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */
>> +		/*u8 CL_data[] = { 0x1F, 0x79 }; */
>> +
>> +		writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data));
>> +		writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data));
>> +		writeregt(state, 0x10, 0xD7, 0x04);
>> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));
>> +	}
>> +	break;
>> +	}
>> +}
>> +
>> +static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq)
>> +{
>> +	u8 data2[3] = { 0xB9, 0xBA, 0x63 };  /* 20.5/41 MHz */
>> +	/*u8 data2[3] = { 0xB7,0x1B,0x00 }; */  /* 24 MHz */
>> +	u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */
>> +	/*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */
>> +
>> +	pr_info("%s\n", __func__);
>> +
>> +	ConfigureTS(state, ActiveIT);
>> +
>> +	/* writeregx(state, 0x00,0x17,0x01); */  /* 2838 has only one Mode */
>> +	writeregt(state, 0x00, 0x2C, 0x01);   /* Demod Clock */
>> +	writeregt(state, 0x00, 0x2F, 0x00);   /* Disable RF Monitor */
>> +	writeregt(state, 0x00, 0x30, 0x00);   /* Enable ADC Clock */
>> +	writeregt(state, 0x00, 0x41, 0x1A);   /* Enable ADC1 */
>> +
>> +	{
>> +		u8 data[2] = { 0x09, 0x54 };  /* 20.5 MHz, 24 MHz */
>> +		/*u8 data[2] = { 0x0A, 0xD4 }; */  /* 41 MHz */
>> +		writeregst(state, 0x00, 0x43, data, 2);   /* Enable ADC 2+3 */
>> +	}
>> +	writeregx(state, 0x00, 0x18, 0x00);   /* Enable ADC 4 */
>> +
>> +	writeregst(state, 0x60, 0xA8, data2, sizeof(data2));
>> +
>> +	writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data));
>> +
>> +	writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */
>> +	writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */
>> +
>> +	BandSettingIT(state, iffreq);
>> +
>> +	writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */
>> +	writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */
>> +}
>> +
>> +static void T2_SetParameters(struct cxd_state *state)
>> +{
>> +	u8 Profile = 0x01;    /* Profile Base */
>> +	u8 notT2time = 12;    /* early unlock detection time */
>> +
>> +	if (state->T2Profile == T2P_Lite) {
>> +		Profile = 0x05;
>> +		notT2time = 40;
>> +	}
>> +
>> +	if (state->plp != 0xffffffff) {
>> +		state->T2Profile = ((state->plp & 0x100) != 0) ?
>> +			T2P_Lite : T2P_Base;
>> +		writeregt(state, 0x23, 0xAF, state->plp);
>> +		writeregt(state, 0x23, 0xAD, 0x01);
>> +	} else {
>> +		state->T2Profile = T2P_Base;
>> +		writeregt(state, 0x23, 0xAD, 0x00);
>> +	}
>> +
>> +	writebitst(state, 0x2E, 0x10, Profile, 0x07);
>> +	writeregt(state, 0x2B, 0x19, notT2time);
>> +}
>> +
>> +static void C2_ReleasePreset(struct cxd_state *state)
>> +{
>> +	{
>> +		static u8 data[2] = { 0x02, 0x80};
>> +		writeregst(state, 0x27, 0xF4, data, sizeof(data));
>> +	}
>> +	writebitst(state, 0x27, 0x51, 0x40, 0xF0);
>> +	writebitst(state, 0x27, 0x73, 0x07, 0x0F);
>> +	writebitst(state, 0x27, 0x74, 0x19, 0x3F);
>> +	writebitst(state, 0x27, 0x75, 0x19, 0x3F);
>> +	writebitst(state, 0x27, 0x76, 0x19, 0x3F);
>> +	if (state->bw == 6) {
>> +		static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA};
>> +		writeregst(state, 0x20, 0x9F, data, sizeof(data));
>> +	} else {
>> +		static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00};
>> +		writeregst(state, 0x20, 0x9F, data, sizeof(data));
>> +	}
>> +	writebitst(state, 0x27, 0xC9, 0x07, 0x07);
>> +	writebitst(state, 0x20, 0xC2, 0x11, 0x33);
>> +	{
>> +		static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8,
>> +				       0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 };
>> +		writeregst(state, 0x2A, 0x20, data, sizeof(data));
>> +	}
>> +	{
>> +		static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 };
>> +		writeregst(state, 0x50, 0x6B, data, sizeof(data));
>> +	}
>> +	writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */
>> +}
>> +
>> +static void C2_DemodSetting2(struct cxd_state *state)
>> +{
>> +	u8 data[6];
>> +	u32 TunePosition =
>> +		state->frontend.dtv_property_cache.frequency / 1000;
>> +
>> +	if (state->bw == 6)
>> +		TunePosition = ((TunePosition * 1792) / 3) / 1000;
>> +	else
>> +		TunePosition = (TunePosition * 448) / 1000;
>> +
>> +	TunePosition = ((TunePosition + 6) / 12) * 12;
>> +
>> +	pr_info("TunePosition = %u\n", TunePosition);
>> +
>> +	data[0] = ((TunePosition >> 16) & 0xFF);
>> +	data[1] = ((TunePosition >>  8) & 0xFF);
>> +	data[2] = (TunePosition & 0xFF);
>> +	data[3] = 0x02;
>> +	data[4] = (state->DataSliceID & 0xFF);
>> +	data[5] = (state->plp & 0xFF);
>> +	writeregst(state, 0x50, 0x7A, data, sizeof(data));
>> +	writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */
>> +}
>> +
>> +static void Stop(struct cxd_state *state)
>> +{
>> +
>> +	writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */
>> +}
>> +
>> +static void ShutDown(struct cxd_state *state)
>> +{
>> +	switch (state->state) {
>> +	case ActiveT2:
>> +		ActiveT2_to_Sleep(state);
>> +		break;
>> +	case ActiveC2:
>> +		ActiveC2_to_Sleep(state);
>> +		break;
>> +	default:
>> +		Active_to_Sleep(state);
>> +		break;
>> +	}
>> +}
>> +
>> +static int gate_ctrl(struct dvb_frontend *fe, int enable)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +
>> +	return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01);
>> +}
>> +
>> +static void release(struct dvb_frontend *fe)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +
>> +	Stop(state);
>> +	ShutDown(state);
>> +	kfree(state);
>> +}
>> +
>> +static int Start(struct cxd_state *state, u32 IntermediateFrequency)
>> +{
>> +	enum EDemodState newDemodState = Unknown;
>> +	u32 iffreq;
>> +
>> +	if (state->state < Sleep)
>> +		return -EINVAL;
>> +
>> +	iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000);
>> +
>> +	switch (state->omode) {
>> +	case OM_DVBT:
>> +		if (state->type == CXD2838)
>> +			return -EINVAL;
>> +		newDemodState = ActiveT;
>> +		break;
>> +	case OM_DVBT2:
>> +		if (state->type == CXD2838)
>> +			return -EINVAL;
>> +		newDemodState = ActiveT2;
>> +		break;
>> +	case OM_DVBC:
>> +	case OM_QAM_ITU_C:
>> +		if (state->type == CXD2838)
>> +			return -EINVAL;
>> +		newDemodState = ActiveC;
>> +		break;
>> +	case OM_DVBC2:
>> +		if (state->type != CXD2843)
>> +			return -EINVAL;
>> +		newDemodState = ActiveC2;
>> +		break;
>> +	case OM_ISDBT:
>> +		if (state->type != CXD2838)
>> +			return -EINVAL;
>> +		newDemodState = ActiveIT;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	state->LockTimeout = 0;
>> +	state->TSLockTimeout = 0;
>> +	state->L1PostTimeout = 0;
>> +	state->last_status = 0;
>> +	state->FirstTimeLock = 1;
>> +	state->LastBERNominator = 0;
>> +	state->LastBERDenominator = 1;
>> +	state->BERScaleMax = 19;
>> +
>> +	if (state->state == newDemodState) {
>> +		writeregt(state, 0x00, 0xC3, 0x01);   /* Disable TS Output */
>> +		switch (newDemodState) {
>> +		case ActiveT:
>> +			/* Stick with HP ( 0x01 = LP ) */
>> +			writeregt(state, 0x10, 0x67, 0x00);
>> +			BandSettingT(state, iffreq);
>> +			state->BERScaleMax = 18;
>> +			break;
>> +		case ActiveT2:
>> +			T2_SetParameters(state);
>> +			BandSettingT2(state, iffreq);
>> +			state->BERScaleMax = 12;
>> +			break;
>> +		case ActiveC:
>> +			BandSettingC(state, iffreq);
>> +			state->BERScaleMax = 19;
>> +			break;
>> +		case ActiveC2:
>> +			BandSettingC2(state, iffreq);
>> +			C2_ReleasePreset(state);
>> +			C2_DemodSetting2(state);
>> +			break;
>> +		case ActiveIT:
>> +			BandSettingIT(state, iffreq);
>> +			break;
>> +		default:
>> +			break;
>> +		}
>> +	} else {
>> +		if (state->state > Sleep) {
>> +			switch (state->state) {
>> +			case ActiveT2:
>> +				ActiveT2_to_Sleep(state);
>> +				break;
>> +			case ActiveC2:
>> +				ActiveC2_to_Sleep(state);
>> +				break;
>> +			default:
>> +				Active_to_Sleep(state);
>> +				break;
>> +			}
>> +		}
>> +		switch (newDemodState) {
>> +		case ActiveT:
>> +			/* Stick with HP ( 0x01 = LP ) */
>> +			writeregt(state, 0x10, 0x67, 0x00);
>> +			Sleep_to_ActiveT(state, iffreq);
>> +			state->BERScaleMax = 18;
>> +			break;
>> +		case ActiveT2:
>> +			T2_SetParameters(state);
>> +			Sleep_to_ActiveT2(state, iffreq);
>> +			state->BERScaleMax = 12;
>> +			break;
>> +		case ActiveC:
>> +			Sleep_to_ActiveC(state, iffreq);
>> +			state->BERScaleMax = 19;
>> +			break;
>> +		case ActiveC2:
>> +			Sleep_to_ActiveC2(state, iffreq);
>> +			C2_ReleasePreset(state);
>> +			C2_DemodSetting2(state);
>> +			break;
>> +		case ActiveIT:
>> +			Sleep_to_ActiveIT(state, iffreq);
>> +			break;
>> +		default:
>> +			break;
>> +		}
>> +	}
>> +	state->state = newDemodState;
>> +	writeregt(state, 0x00, 0xFE, 0x01);   /* SW Reset */
>> +	writeregt(state, 0x00, 0xC3, 0x00);   /* Enable TS Output */
>> +
>> +	return 0;
>> +}
>> +
>> +static int set_parameters(struct dvb_frontend *fe)
>> +{
>> +	int stat;
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +	u32 IF;
>> +
>> +	switch (fe->dtv_property_cache.delivery_system) {
>> +	case SYS_DVBC_ANNEX_A:
>> +		state->omode = OM_DVBC;
>> +		break;
>> +	case SYS_DVBC2:
>> +		state->omode = OM_DVBC2;
>> +		break;
>> +	case SYS_DVBT:
>> +		state->omode = OM_DVBT;
>> +		break;
>> +	case SYS_DVBT2:
>> +		state->omode = OM_DVBT2;
>> +		break;
>> +	case SYS_ISDBT:
>> +		state->omode = OM_ISDBT;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +	if (fe->ops.tuner_ops.set_params)
>> +		fe->ops.tuner_ops.set_params(fe);
>> +	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
>> +	state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000;
>> +	if (fe->dtv_property_cache.stream_id == 0xffffffff) {
>> +		state->DataSliceID = 0xffffffff;
>> +		state->plp = 0xffffffff;
>> +	} else {
>> +		state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8)
>> +			& 0xff;
>> +		state->plp = fe->dtv_property_cache.stream_id & 0xff;
>> +	}
>> +	/* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */
>> +	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
>> +	stat = Start(state, IF);
>> +	return stat;
>> +}
>> +
>> +
>> +static void init(struct cxd_state *state)
>> +{
>> +	u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */
>> +
>> +	state->omode = OM_NONE;
>> +	state->state   = Unknown;
>> +
>> +	writeregx(state, 0xFF, 0x02, 0x00);
>> +	usleep_range(4000, 5000);
>> +	writeregx(state, 0x00, 0x15, 0x01);
>> +	if (state->type != CXD2838)
>> +		writeregx(state, 0x00, 0x17, 0x01);
>> +	usleep_range(4000, 5000);
>> +
>> +	writeregx(state, 0x00, 0x10, 0x01);
>> +
>> +	writeregsx(state, 0x00, 0x13, data, 2);
>> +	writeregx(state, 0x00, 0x15, 0x00);
>> +	usleep_range(3000, 4000);
>> +	writeregx(state, 0x00, 0x10, 0x00);
>> +	usleep_range(2000, 3000);
>> +
>> +	state->curbankx = 0xFF;
>> +	state->curbankt = 0xFF;
>> +
>> +	writeregt(state, 0x00, 0x43, 0x0A);
>> +	writeregt(state, 0x00, 0x41, 0x0A);
>> +	if (state->type == CXD2838)
>> +		writeregt(state, 0x60, 0x5A, 0x00);
>> +
>> +	writebitst(state, 0x10, 0xCB, 0x00, 0x40);
>> +	writeregt(state, 0x10, 0xCD, state->IF_FS);
>> +
>> +	writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98);
>> +	writebitst(state, 0x00, 0xC5, 0x01, 0x07);
>> +	writebitst(state, 0x00, 0xCB, 0x00, 0x01);
>> +	writebitst(state, 0x00, 0xC6, 0x00, 0x1D);
>> +	writebitst(state, 0x00, 0xC8, 0x01, 0x1D);
>> +	writebitst(state, 0x00, 0xC9, 0x00, 0x1D);
>> +	writebitst(state, 0x00, 0x83, 0x00, 0x07);
>> +	writeregt(state, 0x00, 0x84, 0x00);
>> +	writebitst(state, 0x00, 0xD3,
>> +		   (state->type == CXD2838) ? 0x01 : 0x00, 0x01);
>> +	writebitst(state, 0x00, 0xDE, 0x00, 0x01);
>> +
>> +	state->state = Sleep;
>> +}
>> +
>> +
>> +static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg)
>> +{
>> +	state->adrt = cfg->adr;
>> +	state->adrx = cfg->adr + 0x02;
>> +	state->curbankt = 0xff;
>> +	state->curbankx = 0xff;
>> +	mutex_init(&state->mutex);
>> +
>> +	state->SerialMode = cfg->parallel ? 0 : 1;
>> +	state->ContinuousClock = 1;
>> +	state->SerialClockFrequency =
>> +		(cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ?
>> +		cfg->ts_clock :  1; /* 1 = fastest (82 MBit/s), 5 = slowest */
>> +	state->SerialClockFrequency = 1;
>> +	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */
>> +	state->IF_FS = 0x50;
>> +}
>> +
>> +static int get_tune_settings(struct dvb_frontend *fe,
>> +			     struct dvb_frontend_tune_settings *sets)
>> +{
>> +	switch (fe->dtv_property_cache.delivery_system) {
>> +	case SYS_DVBC_ANNEX_A:
>> +	case SYS_DVBC_ANNEX_C:
>> +		/*return c_get_tune_settings(fe, sets);*/
>> +	default:
>> +		/* DVB-T: Use info.frequency_stepsize. */
>> +		return -EINVAL;
>> +	}
>> +}
>> +
>> +static int read_status(struct dvb_frontend *fe, fe_status_t *status)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +	u8 rdata;
>> +
>> +	*status = 0;
>> +	switch (state->state) {
>> +	case ActiveC:
>> +		readregst(state, 0x40, 0x88, &rdata, 1);
>> +		if (rdata & 0x02)
>> +			break;
>> +		if (rdata & 0x01) {
>> +			*status |= 0x07;
>> +			readregst(state, 0x40, 0x10, &rdata, 1);
>> +			if (rdata & 0x20)
>> +				*status |= 0x1f;
>> +		}
>> +		break;
>> +	case ActiveT:
>> +		readregst(state, 0x10, 0x10, &rdata, 1);
>> +		if (rdata & 0x10)
>> +			break;
>> +		if ((rdata & 0x07) == 0x06) {
>> +			*status |= 0x07;
>> +			if (rdata & 0x20)
>> +				*status |= 0x1f;
>> +		}
>> +		break;
>> +	case ActiveT2:
>> +		readregst(state, 0x20, 0x10, &rdata, 1);
>> +		if (rdata & 0x10)
>> +			break;
>> +		if ((rdata & 0x07) == 0x06) {
>> +			*status |= 0x07;
>> +			if (rdata & 0x20)
>> +				*status |= 0x08;
>> +		}
>> +		if (*status & 0x08) {
>> +			readregst(state, 0x22, 0x12, &rdata, 1);
>> +			if (rdata & 0x01)
>> +				*status |= 0x10;
>> +		}
>> +		break;
>> +	case ActiveC2:
>> +		readregst(state, 0x20, 0x10, &rdata, 1);
>> +		if (rdata & 0x10)
>> +			break;
>> +		if ((rdata & 0x07) == 0x06) {
>> +			*status |= 0x07;
>> +			if (rdata & 0x20)
>> +				*status |= 0x18;
>> +		}
>> +		if ((*status & 0x10) && state->FirstTimeLock) {
>> +			u8 data;
>> +
>> +			/* Change1stTrial */
>> +			readregst(state, 0x28, 0xE6, &rdata, 1);
>> +			data = rdata & 1;
>> +			readregst(state, 0x50, 0x15, &rdata, 1);
>> +			data |= ((rdata & 0x18) >> 2);
>> +			/*writebitst(state, 0x50,0x6F,rdata,0x07);*/
>> +			state->FirstTimeLock = 0;
>> +		}
>> +		break;
>> +	case ActiveIT:
>> +		readregst(state, 0x60, 0x10, &rdata, 1);
>> +		if (rdata & 0x10)
>> +			break;
>> +		if (rdata & 0x02) {
>> +			*status |= 0x07;
>> +			if (rdata & 0x01)
>> +				*status |= 0x18;
>> +		}
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +	state->last_status = *status;
>> +	return 0;
>> +}
>> +
>> +static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d)
>> +{
>> +	u8 BERRegs[3];
>> +	u8 Scale;
>> +
>> +	*n = 0;
>> +	*d = 1;
>> +
>> +	readregst(state, 0x10, 0x62, BERRegs, 3);
>> +	readregst(state, 0x10, 0x60, &Scale, 1);
>> +	Scale &= 0x1F;
>> +
>> +	if (BERRegs[0] & 0x80) {
>> +		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
>> +			(((u32) BERRegs[1]) << 8) | BERRegs[2];
>> +		state->LastBERDenominator = 1632 << Scale;
>> +		if (state->LastBERNominator < 256 &&
>> +		    Scale < state->BERScaleMax) {
>> +			writebitst(state, 0x10, 0x60, Scale + 1, 0x1F);
>> +		} else if (state->LastBERNominator > 512 && Scale > 11)
>> +			writebitst(state, 0x10, 0x60, Scale - 1, 0x1F);
>> +	}
>> +	*n = state->LastBERNominator;
>> +	*d = state->LastBERDenominator;
>> +
>> +	return 0;
>> +}
>> +
>> +static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d)
>> +{
>> +	*n = 0;
>> +	*d = 1;
>> +	return 0;
>> +}
>> +
>> +static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d)
>> +{
>> +	u8 BERRegs[3];
>> +	u8 Scale;
>> +
>> +	*n = 0;
>> +	*d = 1;
>> +
>> +	readregst(state, 0x40, 0x62, BERRegs, 3);
>> +	readregst(state, 0x40, 0x60, &Scale, 1);
>> +	Scale &= 0x1F;
>> +
>> +	if (BERRegs[0] & 0x80) {
>> +		state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) |
>> +			(((u32) BERRegs[1]) << 8) | BERRegs[2];
>> +		state->LastBERDenominator = 1632 << Scale;
>> +		if (state->LastBERNominator < 256 &&
>> +		    Scale < state->BERScaleMax) {
>> +			writebitst(state, 0x40, 0x60, Scale + 1, 0x1F);
>> +		} else if (state->LastBERNominator > 512 && Scale > 11)
>> +			writebitst(state, 0x40, 0x60, Scale - 1, 0x1F);
>> +	}
>> +	*n = state->LastBERNominator;
>> +	*d = state->LastBERDenominator;
>> +
>> +	return 0;
>> +}
>> +
>> +static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d)
>> +{
>> +	*n = 0;
>> +	*d = 1;
>> +	return 0;
>> +}
>> +
>> +static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d)
>> +{
>> +	*n = 0;
>> +	*d = 1;
>> +	return 0;
>> +}
>> +
>> +static int read_ber(struct dvb_frontend *fe, u32 *ber)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +	u32 n, d;
>> +	int s = 0;
>> +
>> +	*ber = 0;
>> +	switch (state->state) {
>> +	case ActiveT:
>> +		s = get_ber_t(state, &n, &d);
>> +		break;
>> +	case ActiveT2:
>> +		s = get_ber_t2(state, &n, &d);
>> +		break;
>> +	case ActiveC:
>> +		s = get_ber_c(state, &n, &d);
>> +		break;
>> +	case ActiveC2:
>> +		s = get_ber_c2(state, &n, &d);
>> +		break;
>> +	case ActiveIT:
>> +		s = get_ber_it(state, &n, &d);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +	if (s)
>> +		return s;
>> +
>> +	return 0;
>> +}
>> +
>> +static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
>> +{
>> +	if (fe->ops.tuner_ops.get_rf_strength)
>> +		fe->ops.tuner_ops.get_rf_strength(fe, strength);
>> +	else
>> +		*strength = 0;
>> +	return 0;
>> +}
>> +
>> +static s32 Log10x100(u32 x)
>> +{
>> +	static u32 LookupTable[100] = {
>> +		101157945, 103514217, 105925373, 108392691, 110917482,
>> +		113501082, 116144861, 118850223, 121618600, 124451461,
>> +		127350308, 130316678, 133352143, 136458314, 139636836,
>> +		142889396, 146217717, 149623566, 153108746, 156675107,
>> +		160324539, 164058977, 167880402, 171790839, 175792361,
>> +		179887092, 184077200, 188364909, 192752491, 197242274,
>> +		201836636, 206538016, 211348904, 216271852, 221309471,
>> +		226464431, 231739465, 237137371, 242661010, 248313311,
>> +		254097271, 260015956, 266072506, 272270131, 278612117,
>> +		285101827, 291742701, 298538262, 305492111, 312607937,
>> +		319889511, 327340695, 334965439, 342767787, 350751874,
>> +		358921935, 367282300, 375837404, 384591782, 393550075,
>> +		402717034, 412097519, 421696503, 431519077, 441570447,
>> +		451855944, 462381021, 473151259, 484172368, 495450191,
>> +		506990708, 518800039, 530884444, 543250331, 555904257,
>> +		568852931, 582103218, 595662144, 609536897, 623734835,
>> +		638263486, 653130553, 668343918, 683911647, 699841996,
>> +		716143410, 732824533, 749894209, 767361489, 785235635,
>> +		803526122, 822242650, 841395142, 860993752, 881048873,
>> +		901571138, 922571427, 944060876, 966050879, 988553095,
>> +	};
>> +	s32 y;
>> +	int i;
>> +
>> +	if (x == 0)
>> +		return 0;
>> +	y = 800;
>> +	if (x >= 1000000000) {
>> +		x /= 10;
>> +		y += 100;
>> +	}
>> +
>> +	while (x < 100000000) {
>> +		x *= 10;
>> +		y -= 100;
>> +	}
>> +	i = 0;
>> +	while (i < 100 && x > LookupTable[i])
>> +		i += 1;
>> +	y += i;
>> +	return y;
>> +}
>> +
>> +#if 0
>> +static void GetPLPIds(struct cxd_state *state, u32 nValues,
>> +		      u8 *Values, u32 *Returned)
>> +{
>> +	u8 nPids = 0;
>> +
>> +	*Returned = 0;
>> +	if (state->state != ActiveT2)
>> +		return;
>> +	if (state->last_status != 0x1f)
>> +		return;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x22, 0x7F, &nPids, 1);
>> +
>> +	Values[0] = nPids;
>> +	if (nPids >= nValues)
>> +		nPids = nValues - 1;
>> +
>> +	readregst_unlocked(state, 0x22, 0x80, &Values[1],
>> +			   nPids > 128 ? 128 : nPids);
>> +
>> +	if (nPids > 128)
>> +		readregst_unlocked(state, 0x23, 0x10, &Values[129],
>> +				   nPids - 128);
>> +
>> +	*Returned = nPids + 1;
>> +
>> +	unfreeze_regst(state);
>> +}
>> +#endif
>> +
>> +static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise)
>> +{
>> +	u8 Data[2];
>> +	u32 reg;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data));
>> +	unfreeze_regst(state);
>> +
>> +	reg = (Data[0] << 8) | Data[1];
>> +	if (reg > 51441)
>> +		reg = 51441;
>> +
>> +	if (state->bw == 8) {
>> +		if (reg > 1143)
>> +			reg = 1143;
>> +		*SignalToNoise = (Log10x100(reg) -
>> +				  Log10x100(1200 - reg)) + 220;
>> +	} else
>> +		*SignalToNoise = Log10x100(reg) - 90;
>> +}
>> +
>> +static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise)
>> +{
>> +	u8 Data[2];
>> +	u32 reg;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
>> +	unfreeze_regst(state);
>> +
>> +	reg = (Data[0] << 8) | Data[1];
>> +	if (reg > 51441)
>> +		reg = 51441;
>> +
>> +	*SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384;
>> +}
>> +
>> +
>> +static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise)
>> +{
>> +	u8 Data[2];
>> +	u32 reg;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
>> +	unfreeze_regst(state);
>> +
>> +	reg = (Data[0] << 8) | Data[1];
>> +	if (reg > 10876)
>> +		reg = 10876;
>> +
>> +	*SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320;
>> +}
>> +
>> +static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise)
>> +{
>> +	u8 Data[2];
>> +	u32 reg;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data));
>> +	unfreeze_regst(state);
>> +
>> +	reg = (Data[0] << 8) | Data[1];
>> +	if (reg > 4996)
>> +		reg = 4996;
>> +
>> +	*SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285;
>> +}
>> +
>> +static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise)
>> +{
>> +	u8 Data[2];
>> +	u8 Constellation = 0;
>> +	u32 reg;
>> +
>> +	*SignalToNoise = 0;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x40, 0x19, &Constellation, 1);
>> +	readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data));
>> +	unfreeze_regst(state);
>> +
>> +	reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]);
>> +	if (reg == 0)
>> +		return;
>> +
>> +	switch (Constellation & 0x07) {
>> +	case 0: /* QAM 16 */
>> +	case 2: /* QAM 64 */
>> +	case 4: /* QAM 256 */
>> +		if (reg < 126)
>> +			reg = 126;
>> +		*SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000;
>> +		break;
>> +	case 1: /* QAM 32 */
>> +	case 3: /* QAM 128 */
>> +		if (reg < 69)
>> +			reg = 69;
>> +		*SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000;
>> +		break;
>> +	}
>> +}
>> +
>> +static int read_snr(struct dvb_frontend *fe, u16 *snr)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +	u32 SNR = 0;
>> +
>> +	*snr = 0;
>> +	if (state->last_status != 0x1f)
>> +		return 0;
>> +
>> +	switch (state->state) {
>> +	case ActiveC:
>> +		GetSignalToNoiseC(state, &SNR);
>> +		break;
>> +	case ActiveC2:
>> +		GetSignalToNoiseC2(state, &SNR);
>> +		break;
>> +	case ActiveT:
>> +		GetSignalToNoiseT(state, &SNR);
>> +		break;
>> +	case ActiveT2:
>> +		GetSignalToNoiseT2(state, &SNR);
>> +		break;
>> +	case ActiveIT:
>> +		GetSignalToNoiseIT(state, &SNR);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +	*snr = SNR;
>> +	return 0;
>> +}
>> +
>> +static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
>> +{
>> +	*ucblocks = 0;
>> +	return 0;
>> +}
>> +
>> +static int tune(struct dvb_frontend *fe, bool re_tune,
>> +		unsigned int mode_flags,
>> +		unsigned int *delay, fe_status_t *status)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +	int r;
>> +
>> +	if (re_tune) {
>> +		r = set_parameters(fe);
>> +		if (r)
>> +			return r;
>> +		state->tune_time = jiffies;
>> +
>> +	}
>> +	if (*status & FE_HAS_LOCK)
>> +		return 0;
>> +	/* *delay = 50; */
>> +	r = read_status(fe, status);
>> +	if (r)
>> +		return r;
>> +	return 0;
>> +}
>> +
>> +static enum dvbfe_search search(struct dvb_frontend *fe)
>> +{
>> +	int r;
>> +	u32 loops = 20, i;
>> +	fe_status_t status;
>> +
>> +	r = set_parameters(fe);
>> +
>> +	for (i = 0; i < loops; i++)  {
>> +		msleep(50);
>> +		r = read_status(fe, &status);
>> +		if (r)
>> +			return DVBFE_ALGO_SEARCH_ERROR;
>> +		if (status & FE_HAS_LOCK)
>> +			break;
>> +	}
>> +
>> +	if (status & FE_HAS_LOCK)
>> +		return DVBFE_ALGO_SEARCH_SUCCESS;
>> +	else
>> +		return DVBFE_ALGO_SEARCH_AGAIN;
>> +}
>> +
>> +static int get_algo(struct dvb_frontend *fe)
>> +{
>> +	return DVBFE_ALGO_HW;
>> +}
>> +
>> +static int get_fe_t(struct cxd_state *state)
>> +{
>> +	struct dvb_frontend *fe = &state->frontend;
>> +	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
>> +	u8 tps[7];
>> +
>> +	read_tps(state, tps);
>> +
>> +/*  TPSData[0] [7:6]  CNST[1:0]
>> +    TPSData[0] [5:3]  HIER[2:0]
>> +    TPSData[0] [2:0]  HRATE[2:0]
>> +*/
>> +	switch ((tps[0] >> 6) & 0x03) {
>> +	case 0:
>> +		p->modulation = QPSK;
>> +		break;
>> +	case 1:
>> +		p->modulation = QAM_16;
>> +		break;
>> +	case 2:
>> +		p->modulation = QAM_64;
>> +		break;
>> +	}
>> +	switch ((tps[0] >> 3) & 0x07) {
>> +	case 0:
>> +		p->hierarchy = HIERARCHY_NONE;
>> +		break;
>> +	case 1:
>> +		p->hierarchy = HIERARCHY_1;
>> +		break;
>> +	case 2:
>> +		p->hierarchy = HIERARCHY_2;
>> +		break;
>> +	case 3:
>> +		p->hierarchy = HIERARCHY_4;
>> +		break;
>> +	}
>> +	switch ((tps[0] >> 0) & 0x07) {
>> +	case 0:
>> +		p->code_rate_HP = FEC_1_2;
>> +		break;
>> +	case 1:
>> +		p->code_rate_HP = FEC_2_3;
>> +		break;
>> +	case 2:
>> +		p->code_rate_HP = FEC_3_4;
>> +		break;
>> +	case 3:
>> +		p->code_rate_HP = FEC_5_6;
>> +		break;
>> +	case 4:
>> +		p->code_rate_HP = FEC_7_8;
>> +		break;
>> +	}
>> +
>> +/*  TPSData[1] [7:5]  LRATE[2:0]
>> +    TPSData[1] [4:3]  GI[1:0]
>> +    TPSData[1] [2:1]  MODE[1:0]
>> +*/
>> +	switch ((tps[1] >> 5) & 0x07) {
>> +	case 0:
>> +		p->code_rate_LP = FEC_1_2;
>> +		break;
>> +	case 1:
>> +		p->code_rate_LP = FEC_2_3;
>> +		break;
>> +	case 2:
>> +		p->code_rate_LP = FEC_3_4;
>> +		break;
>> +	case 3:
>> +		p->code_rate_LP = FEC_5_6;
>> +		break;
>> +	case 4:
>> +		p->code_rate_LP = FEC_7_8;
>> +		break;
>> +	}
>> +	switch ((tps[1] >> 3) & 0x03) {
>> +	case 0:
>> +		p->guard_interval = GUARD_INTERVAL_1_32;
>> +		break;
>> +	case 1:
>> +		p->guard_interval = GUARD_INTERVAL_1_16;
>> +		break;
>> +	case 2:
>> +		p->guard_interval = GUARD_INTERVAL_1_8;
>> +		break;
>> +	case 3:
>> +		p->guard_interval = GUARD_INTERVAL_1_4;
>> +		break;
>> +	}
>> +	switch ((tps[1] >> 1) & 0x03) {
>> +	case 0:
>> +		p->transmission_mode = TRANSMISSION_MODE_2K;
>> +		break;
>> +	case 1:
>> +		p->transmission_mode = TRANSMISSION_MODE_8K;
>> +		break;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int get_fe_c(struct cxd_state *state)
>> +{
>> +	struct dvb_frontend *fe = &state->frontend;
>> +	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
>> +	u8 qam;
>> +
>> +	freeze_regst(state);
>> +	readregst_unlocked(state, 0x40, 0x19, &qam, 1);
>> +	unfreeze_regst(state);
>> +	p->modulation = qam & 0x07;
>> +	return 0;
>> +}
>> +
>> +static int get_frontend(struct dvb_frontend *fe)
>> +{
>> +	struct cxd_state *state = fe->demodulator_priv;
>> +
>> +	if (state->last_status != 0x1f)
>> +		return 0;
>> +
>> +	switch (state->state) {
>> +	case ActiveT:
>> +		get_fe_t(state);
>> +		break;
>> +	case ActiveT2:
>> +		break;
>> +	case ActiveC:
>> +		get_fe_c(state);
>> +		break;
>> +	case ActiveC2:
>> +		break;
>> +	case ActiveIT:
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static struct dvb_frontend_ops common_ops_2843 = {
>> +	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 },
>> +	.info = {
>> +		.name = "CXD2843 DVB-C/C2 DVB-T/T2",
>> +		.frequency_stepsize = 166667,	/* DVB-T only */
>> +		.frequency_min = 47000000,	/* DVB-T: 47125000 */
>> +		.frequency_max = 865000000,	/* DVB-C: 862000000 */
>> +		.symbol_rate_min = 870000,
>> +		.symbol_rate_max = 11700000,
>> +		.caps = /* DVB-C */
>> +			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
>> +			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
>> +			FE_CAN_FEC_AUTO |
>> +			/* DVB-T */
>> +			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
>> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
>> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
>> +			FE_CAN_TRANSMISSION_MODE_AUTO |
>> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
>> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
>> +	},
>> +	.release = release,
>> +	.i2c_gate_ctrl = gate_ctrl,
>> +	.set_frontend = set_parameters,
>> +
>> +	.get_tune_settings = get_tune_settings,
>> +	.read_status = read_status,
>> +	.read_ber = read_ber,
>> +	.read_signal_strength = read_signal_strength,
>> +	.read_snr = read_snr,
>> +	.read_ucblocks = read_ucblocks,
>> +	.get_frontend = get_frontend,
>> +#ifdef USE_ALGO
>> +	.get_frontend_algo = get_algo,
>> +	.search = search,
>> +	.tune = tune,
>> +#endif
>> +};
>> +
>> +static struct dvb_frontend_ops common_ops_2837 = {
>> +	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 },
>> +	.info = {
>> +		.name = "CXD2837 DVB-C DVB-T/T2",
>> +		.frequency_stepsize = 166667,	/* DVB-T only */
>> +		.frequency_min = 47000000,	/* DVB-T: 47125000 */
>> +		.frequency_max = 865000000,	/* DVB-C: 862000000 */
>> +		.symbol_rate_min = 870000,
>> +		.symbol_rate_max = 11700000,
>> +		.caps = /* DVB-C */
>> +			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
>> +			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
>> +			FE_CAN_FEC_AUTO |
>> +			/* DVB-T */
>> +			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
>> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
>> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
>> +			FE_CAN_TRANSMISSION_MODE_AUTO |
>> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
>> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
>> +	},
>> +	.release = release,
>> +	.i2c_gate_ctrl = gate_ctrl,
>> +	.set_frontend = set_parameters,
>> +
>> +	.get_tune_settings = get_tune_settings,
>> +	.read_status = read_status,
>> +	.read_ber = read_ber,
>> +	.read_signal_strength = read_signal_strength,
>> +	.read_snr = read_snr,
>> +	.read_ucblocks = read_ucblocks,
>> +	.get_frontend = get_frontend,
>> +#ifdef USE_ALGO
>> +	.get_frontend_algo = get_algo,
>> +	.search = search,
>> +	.tune = tune,
>> +#endif
>> +};
>> +
>> +static struct dvb_frontend_ops common_ops_2838 = {
>> +	.delsys = { SYS_ISDBT },
>> +	.info = {
>> +		.name = "CXD2838 ISDB-T",
>> +		.frequency_stepsize = 166667,
>> +		.frequency_min = 47000000,
>> +		.frequency_max = 865000000,
>> +		.symbol_rate_min = 870000,
>> +		.symbol_rate_max = 11700000,
>> +		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
>> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
>> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
>> +			FE_CAN_TRANSMISSION_MODE_AUTO |
>> +			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
>> +			FE_CAN_RECOVER | FE_CAN_MUTE_TS
>> +	},
>> +	.release = release,
>> +	.i2c_gate_ctrl = gate_ctrl,
>> +	.set_frontend = set_parameters,
>> +
>> +	.get_tune_settings = get_tune_settings,
>> +	.read_status = read_status,
>> +	.read_ber = read_ber,
>> +	.read_signal_strength = read_signal_strength,
>> +	.read_snr = read_snr,
>> +	.read_ucblocks = read_ucblocks,
>> +#ifdef USE_ALGO
>> +	.get_frontend_algo = get_algo,
>> +	.search = search,
>> +	.tune = tune,
>> +#endif
>> +};
>> +
>> +static int probe(struct cxd_state *state)
>> +{
>> +	u8 ChipID = 0x00;
>> +	int status;
>> +
>> +	status = readregst(state, 0x00, 0xFD, &ChipID, 1);
>> +
>> +	if (status)
>> +		status = readregsx(state, 0x00, 0xFD, &ChipID, 1);
>> +	if (status)
>> +		return status;
>> +
>> +	/*printk("ChipID  = %02X\n", ChipID);*/
>> +	switch (ChipID) {
>> +	case 0xa4:
>> +		state->type = CXD2843;
>> +		memcpy(&state->frontend.ops, &common_ops_2843,
>> +		       sizeof(struct dvb_frontend_ops));
>> +		break;
>> +	case 0xb1:
>> +		state->type = CXD2837;
>> +		memcpy(&state->frontend.ops, &common_ops_2837,
>> +		       sizeof(struct dvb_frontend_ops));
>> +		break;
>> +	case 0xb0:
>> +		state->type = CXD2838;
>> +		memcpy(&state->frontend.ops, &common_ops_2838,
>> +		       sizeof(struct dvb_frontend_ops));
>> +		break;
>> +	default:
>> +		return -1;
>> +	}
>> +	state->frontend.demodulator_priv = state;
>> +	return 0;
>> +}
>> +
>> +struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
>> +				    struct cxd2843_cfg *cfg)
>> +{
>> +	struct cxd_state *state = NULL;
>> +
>> +	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL);
>> +	if (!state)
>> +		return NULL;
>> +
>> +	state->i2c = i2c;
>> +	init_state(state, cfg);
>> +	if (probe(state) == 0) {
>> +		init(state);
>> +		return &state->frontend;
>> +	}
>> +	pr_err("cxd2843: not found\n");
>> +	kfree(state);
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(cxd2843_attach);
>> +
>> +MODULE_DESCRIPTION("CXD2843/37/38 driver");
>> +MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h
>> new file mode 100644
>> index 0000000..f3e355b
>> --- /dev/null
>> +++ b/drivers/media/dvb-frontends/cxd2843.h
>> @@ -0,0 +1,30 @@
>> +#ifndef _CXD2843_H_
>> +#define _CXD2843_H_
>> +
>> +#include <linux/types.h>
>> +#include <linux/i2c.h>
>> +
>> +struct cxd2843_cfg {
>> +	u8  adr;
>> +	u32 ts_clock;
>> +	u8  parallel;
>> +};
>> +
>> +#if defined(CONFIG_DVB_CXD2843) || \
>> +	(defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE))
>> +
>> +extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
>> +					   struct cxd2843_cfg *cfg);
>> +
>> +#else
>> +
>> +static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
>> +					   struct cxd2843_cfg *cfg)
>> +{
>> +	pr_warn("%s: driver disabled by Kconfig\n", __func__);
>> +	return NULL;
>> +}
>> +
>> +#endif
>> +
>> +#endif

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-09-23 12:04 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-31 22:33 [PATCH 1/4] tda18212: add support for slave chip version Antti Palosaari
2014-07-31 22:33 ` [PATCH 2/4] uapi: dvb: initial support for DVB-C2 standard Antti Palosaari
2014-09-23 11:39   ` Mauro Carvalho Chehab
2014-07-31 22:33 ` [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver Antti Palosaari
2014-09-23 11:47   ` Mauro Carvalho Chehab
2014-09-23 12:04     ` Antti Palosaari
2014-07-31 22:33 ` [PATCH 4/4] ddbridge: add support for DVB-C/C2/T/T2 extension card Antti Palosaari

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).