linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] DDBridge 0.9.10 driver updates
@ 2013-11-03  0:22 Maik Broemme
  2013-11-03  0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
                   ` (12 more replies)
  0 siblings, 13 replies; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:22 UTC (permalink / raw)
  To: Linux Media Mailing List

I've updated the current DDBridge to latest version 0.9.10 from Ralph
Metzler available at:

http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2

I've merged the driver to work with current v4l/dvb tree and I will
maintain the driver for v4l/dvb in future. The coming patch series is
the first version and I explicitly want to get feedback and hints if
some parts are merged at wrong places, etc... The following changes
were made:

  - MSI enabled by default (some issues left with i2c timeouts)
  - no support for Digital Devices Octonet
  - no support for DVB Netstream
  - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
  - removed unused registers to cleanup code (might be added later again
    if needed)

The following devices are supported by the driver update:

  - Octopus DVB adapter
  - Octopus V3 DVB adapter
  - Octopus LE DVB adapter
  - Octopus OEM
  - Octopus Mini
  - Cine S2 V6 DVB adapter
  - Cine S2 V6.5 DVB adapter
  - Octopus CI
  - Octopus CI single
  - DVBCT V6.1 DVB adapter
  - DVB-C modulator
  - SaTiX-S2 V3 DVB adapter

I might merge the Octonet and DVB Netstream drivers from Ralphs source
later once the current committed DDBridge driver updates are merged in
mainline.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>

Maik Broemme (12):
  dvb-frontends: Support for DVB-C2 to DVB frontends
  tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
  stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
  tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
  dvb-core: export dvb_usercopy and new DVB device constants
  ddbridge: Updated ddbridge registers
  ddbridge: Moved i2c interfaces into separate file
  ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
  ddbridge: Update ddbridge driver to version 0.9.10
  ddbridge: Update ddbridge header for 0.9.10 changes
  ddbridge: Kconfig and Makefile fixes to build latest ddbridge

 drivers/media/dvb-core/dvbdev.c              |    1 
 drivers/media/dvb-core/dvbdev.h              |    2 
 drivers/media/dvb-frontends/Kconfig          |   31 
 drivers/media/dvb-frontends/Makefile         |    3 
 drivers/media/dvb-frontends/cxd2843.c        | 1647 ++++++++++++
 drivers/media/dvb-frontends/cxd2843.h        |   47 
 drivers/media/dvb-frontends/stv0367dd.c      | 2329 ++++++++++++++++++
 drivers/media/dvb-frontends/stv0367dd.h      |   48 
 drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 +++++++++++++++++++++++++++
 drivers/media/dvb-frontends/tda18212dd.c     |  934 +++++++
 drivers/media/dvb-frontends/tda18212dd.h     |   37 
 drivers/media/pci/ddbridge/Kconfig           |   21 
 drivers/media/pci/ddbridge/Makefile          |    2 
 drivers/media/pci/ddbridge/ddbridge-core.c   | 3085 +++++++++++++++++-------
 drivers/media/pci/ddbridge/ddbridge-i2c.c    |  239 +
 drivers/media/pci/ddbridge/ddbridge-mod.c    | 1033 ++++++++
 drivers/media/pci/ddbridge/ddbridge-regs.h   |  273 +-
 drivers/media/pci/ddbridge/ddbridge.h        |  408 ++-
 include/uapi/linux/dvb/frontend.h            |    1 
 19 files changed, 12555 insertions(+), 1028 deletions(-)

--Maik

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

* [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
@ 2013-11-03  0:24 ` Maik Broemme
  2013-11-03  9:23   ` Mauro Carvalho Chehab
  2013-11-03  0:25 ` [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner Maik Broemme
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:24 UTC (permalink / raw)
  To: Linux Media Mailing List

Added support for DVB-C2 to DVB frontends. It will be required
by cxd2843 and tda18212dd (Digital Devices) frontends.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 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 */
-- 
1.8.4.2

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

* [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
  2013-11-03  0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
@ 2013-11-03  0:25 ` Maik Broemme
  2013-11-03  9:27   ` Mauro Carvalho Chehab
  2013-11-03  0:28 ` [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator Maik Broemme
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:25 UTC (permalink / raw)
  To: Linux Media Mailing List

Added (DD) to NXP TDA18271C2 silicon tuner as this tuner was
specifically added for Digital Devices ddbridge driver.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/dvb-frontends/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index bddbab4..6f99eb8 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -48,11 +48,11 @@ config DVB_DRXK
 	  Say Y when you want to support this frontend.
 
 config DVB_TDA18271C2DD
-	tristate "NXP TDA18271C2 silicon tuner"
+	tristate "NXP TDA18271C2 silicon tuner (DD)"
 	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
-	  NXP TDA18271 silicon tuner.
+	  NXP TDA18271 silicon tuner (Digital Devices driver).
 
 	  Say Y when you want to support this tuner.
 
-- 
1.8.4.2

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

* [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
  2013-11-03  0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
  2013-11-03  0:25 ` [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner Maik Broemme
@ 2013-11-03  0:28 ` Maik Broemme
  2013-11-03  9:29   ` Mauro Carvalho Chehab
  2013-11-03  0:31 ` [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner Maik Broemme
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:28 UTC (permalink / raw)
  To: Linux Media Mailing List

Added support for the STV 0367 DVB-C/T demodulator used by recent
Digital Devices hardware. This will allow update of ddbridge driver
to support newer devices like DVBCT V6.1 DVB adapter.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/dvb-frontends/Kconfig          |    9 +
 drivers/media/dvb-frontends/Makefile         |    1 +
 drivers/media/dvb-frontends/stv0367dd.c      | 2329 +++++++++++++++++
 drivers/media/dvb-frontends/stv0367dd.h      |   48 +
 drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 ++++++++++++++++++++++++++
 5 files changed, 5829 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/stv0367dd.c
 create mode 100644 drivers/media/dvb-frontends/stv0367dd.h
 create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 6f99eb8..7cac015 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -56,6 +56,15 @@ config DVB_TDA18271C2DD
 
 	  Say Y when you want to support this tuner.
 
+config DVB_STV0367DD
+        tristate "STV 0367 (DD)"
+        depends on DVB_CORE && I2C
+        default m if DVB_FE_CUSTOMISE
+        help
+          STV 0367 DVB-C/T demodulator (Digital Devices 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 f9cb43d..de100f1 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -97,6 +97,7 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
 obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
 obj-$(CONFIG_DVB_A8293) += a8293.o
 obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c
new file mode 100644
index 0000000..37c8e2d
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367dd.c
@@ -0,0 +1,2329 @@
+/*
+ *  stv0367dd.c: STV0367 DVB-C/T demodulator driver
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#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 <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0367dd.h"
+#include "stv0367dd_regs.h"
+
+enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C };
+enum {  QAM_MOD_QAM4 = 0,
+	QAM_MOD_QAM16,
+	QAM_MOD_QAM32,
+	QAM_MOD_QAM64,
+	QAM_MOD_QAM128,
+	QAM_MOD_QAM256,
+	QAM_MOD_QAM512,
+	QAM_MOD_QAM1024
+};
+
+enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED };
+
+enum {
+	QAM_FEC_A = 1,					/* J83 Annex A */
+	QAM_FEC_B = (1<<1),				/* J83 Annex B */
+	QAM_FEC_C = (1<<2)				/* J83 Annex C */
+};
+
+enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted };
+
+struct stv_state {
+#ifdef USE_API3
+	struct dvb_frontend c_frontend;
+	struct dvb_frontend t_frontend;
+#else
+	struct dvb_frontend frontend;
+#endif
+	fe_modulation_t modulation;
+	u32 symbol_rate;
+	u32 bandwidth;
+	struct device *dev;
+
+	struct i2c_adapter *i2c;
+	u8     adr;
+	void  *priv;
+
+	struct mutex mutex;
+	struct mutex ctlock;
+
+	u32 master_clock;
+	u32 adc_clock;
+	u8 ID;
+	u8 I2CRPT;
+	u32 omode;
+	u8  qam_inversion;
+
+	s32 IF;
+
+	s32    m_FECTimeOut;
+	s32    m_DemodTimeOut;
+	s32    m_SignalTimeOut;
+	s32    m_DemodLockTime;
+	s32    m_FFTTimeOut;
+	s32    m_TSTimeOut;
+
+	bool    m_bFirstTimeLock;
+
+	u8    m_Save_QAM_AGC_CTL;
+
+	enum EDemodState demod_state;
+
+	u8    m_OFDM_FFTMode;          // 0 = 2k, 1 = 8k, 2 = 4k
+	u8    m_OFDM_Modulation;   //
+	u8    m_OFDM_FEC;          //
+	u8    m_OFDM_Guard;
+
+	u32   ucblocks;
+	u32   ber;
+};
+
+struct init_table {
+	u16  adr;
+	u8   data;
+};
+
+struct init_table base_init[] = {
+	{ R367_IOCFG0,     0x80 },
+	{ R367_DAC0R,      0x00 },
+	{ R367_IOCFG1,     0x00 },
+	{ R367_DAC1R,      0x00 },
+	{ R367_IOCFG2,     0x00 },
+	{ R367_SDFR,       0x00 },
+	{ R367_AUX_CLK,    0x00 },
+	{ R367_FREESYS1,   0x00 },
+	{ R367_FREESYS2,   0x00 },
+	{ R367_FREESYS3,   0x00 },
+	{ R367_GPIO_CFG,   0x55 },
+	{ R367_GPIO_CMD,   0x01 },
+	{ R367_TSTRES,     0x00 },
+	{ R367_ANACTRL,    0x00 },
+	{ R367_TSTBUS,     0x00 },
+	{ R367_RF_AGC2,    0x20 },
+	{ R367_ANADIGCTRL, 0x0b },
+	{ R367_PLLMDIV,    0x01 },
+	{ R367_PLLNDIV,    0x08 },
+	{ R367_PLLSETUP,   0x18 },
+	{ R367_DUAL_AD12,  0x04 },
+	{ R367_TSTBIST,    0x00 },
+	{ 0x0000,          0x00 }
+};
+
+struct init_table qam_init[] = {
+	{ R367_QAM_CTRL_1,                  0x06 },// Orginal 0x04
+	{ R367_QAM_CTRL_2,                  0x03 },
+	{ R367_QAM_IT_STATUS1,              0x2b },
+	{ R367_QAM_IT_STATUS2,              0x08 },
+	{ R367_QAM_IT_EN1,                  0x00 },
+	{ R367_QAM_IT_EN2,                  0x00 },
+	{ R367_QAM_CTRL_STATUS,             0x04 },
+	{ R367_QAM_TEST_CTL,                0x00 },
+	{ R367_QAM_AGC_CTL,                 0x73 },
+	{ R367_QAM_AGC_IF_CFG,              0x50 },
+	{ R367_QAM_AGC_RF_CFG,              0x02 },// RF Freeze
+	{ R367_QAM_AGC_PWM_CFG,             0x03 },
+	{ R367_QAM_AGC_PWR_REF_L,           0x5a },
+	{ R367_QAM_AGC_PWR_REF_H,           0x00 },
+	{ R367_QAM_AGC_RF_TH_L,             0xff },
+	{ R367_QAM_AGC_RF_TH_H,             0x07 },
+	{ R367_QAM_AGC_IF_LTH_L,            0x00 },
+	{ R367_QAM_AGC_IF_LTH_H,            0x08 },
+	{ R367_QAM_AGC_IF_HTH_L,            0xff },
+	{ R367_QAM_AGC_IF_HTH_H,            0x07 },
+	{ R367_QAM_AGC_PWR_RD_L,            0xa0 },
+	{ R367_QAM_AGC_PWR_RD_M,            0xe9 },
+	{ R367_QAM_AGC_PWR_RD_H,            0x03 },
+	{ R367_QAM_AGC_PWM_IFCMD_L,         0xe4 },
+	{ R367_QAM_AGC_PWM_IFCMD_H,         0x00 },
+	{ R367_QAM_AGC_PWM_RFCMD_L,         0xff },
+	{ R367_QAM_AGC_PWM_RFCMD_H,         0x07 },
+	{ R367_QAM_IQDEM_CFG,               0x01 },
+	{ R367_QAM_MIX_NCO_LL,              0x22 },
+	{ R367_QAM_MIX_NCO_HL,              0x96 },
+	{ R367_QAM_MIX_NCO_HH,              0x55 },
+	{ R367_QAM_SRC_NCO_LL,              0xff },
+	{ R367_QAM_SRC_NCO_LH,              0x0c },
+	{ R367_QAM_SRC_NCO_HL,              0xf5 },
+	{ R367_QAM_SRC_NCO_HH,              0x20 },
+	{ R367_QAM_IQDEM_GAIN_SRC_L,        0x06 },
+	{ R367_QAM_IQDEM_GAIN_SRC_H,        0x01 },
+	{ R367_QAM_IQDEM_DCRM_CFG_LL,       0xfe },
+	{ R367_QAM_IQDEM_DCRM_CFG_LH,       0xff },
+	{ R367_QAM_IQDEM_DCRM_CFG_HL,       0x0f },
+	{ R367_QAM_IQDEM_DCRM_CFG_HH,       0x00 },
+	{ R367_QAM_IQDEM_ADJ_COEFF0,        0x34 },
+	{ R367_QAM_IQDEM_ADJ_COEFF1,        0xae },
+	{ R367_QAM_IQDEM_ADJ_COEFF2,        0x46 },
+	{ R367_QAM_IQDEM_ADJ_COEFF3,        0x77 },
+	{ R367_QAM_IQDEM_ADJ_COEFF4,        0x96 },
+	{ R367_QAM_IQDEM_ADJ_COEFF5,        0x69 },
+	{ R367_QAM_IQDEM_ADJ_COEFF6,        0xc7 },
+	{ R367_QAM_IQDEM_ADJ_COEFF7,        0x01 },
+	{ R367_QAM_IQDEM_ADJ_EN,            0x04 },
+	{ R367_QAM_IQDEM_ADJ_AGC_REF,       0x94 },
+	{ R367_QAM_ALLPASSFILT1,            0xc9 },
+	{ R367_QAM_ALLPASSFILT2,            0x2d },
+	{ R367_QAM_ALLPASSFILT3,            0xa3 },
+	{ R367_QAM_ALLPASSFILT4,            0xfb },
+	{ R367_QAM_ALLPASSFILT5,            0xf6 },
+	{ R367_QAM_ALLPASSFILT6,            0x45 },
+	{ R367_QAM_ALLPASSFILT7,            0x6f },
+	{ R367_QAM_ALLPASSFILT8,            0x7e },
+	{ R367_QAM_ALLPASSFILT9,            0x05 },
+	{ R367_QAM_ALLPASSFILT10,           0x0a },
+	{ R367_QAM_ALLPASSFILT11,           0x51 },
+	{ R367_QAM_TRL_AGC_CFG,             0x20 },
+	{ R367_QAM_TRL_LPF_CFG,             0x28 },
+	{ R367_QAM_TRL_LPF_ACQ_GAIN,        0x44 },
+	{ R367_QAM_TRL_LPF_TRK_GAIN,        0x22 },
+	{ R367_QAM_TRL_LPF_OUT_GAIN,        0x03 },
+	{ R367_QAM_TRL_LOCKDET_LTH,         0x04 },
+	{ R367_QAM_TRL_LOCKDET_HTH,         0x11 },
+	{ R367_QAM_TRL_LOCKDET_TRGVAL,      0x20 },
+	{ R367_QAM_IQ_QAM,			0x01 },
+	{ R367_QAM_FSM_STATE,               0xa0 },
+	{ R367_QAM_FSM_CTL,                 0x08 },
+	{ R367_QAM_FSM_STS,                 0x0c },
+	{ R367_QAM_FSM_SNR0_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR1_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR2_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR0_LTH,            0x00 },
+	{ R367_QAM_FSM_SNR1_LTH,            0x00 },
+	{ R367_QAM_FSM_EQA1_HTH,            0x00 },
+	{ R367_QAM_FSM_TEMPO,               0x32 },
+	{ R367_QAM_FSM_CONFIG,              0x03 },
+	{ R367_QAM_EQU_I_TESTTAP_L,         0x11 },
+	{ R367_QAM_EQU_I_TESTTAP_M,         0x00 },
+	{ R367_QAM_EQU_I_TESTTAP_H,         0x00 },
+	{ R367_QAM_EQU_TESTAP_CFG,          0x00 },
+	{ R367_QAM_EQU_Q_TESTTAP_L,         0xff },
+	{ R367_QAM_EQU_Q_TESTTAP_M,         0x00 },
+	{ R367_QAM_EQU_Q_TESTTAP_H,         0x00 },
+	{ R367_QAM_EQU_TAP_CTRL,            0x00 },
+	{ R367_QAM_EQU_CTR_CRL_CONTROL_L,   0x11 },
+	{ R367_QAM_EQU_CTR_CRL_CONTROL_H,   0x05 },
+	{ R367_QAM_EQU_CTR_HIPOW_L,         0x00 },
+	{ R367_QAM_EQU_CTR_HIPOW_H,         0x00 },
+	{ R367_QAM_EQU_I_EQU_LO,            0xef },
+	{ R367_QAM_EQU_I_EQU_HI,            0x00 },
+	{ R367_QAM_EQU_Q_EQU_LO,            0xee },
+	{ R367_QAM_EQU_Q_EQU_HI,            0x00 },
+	{ R367_QAM_EQU_MAPPER,              0xc5 },
+	{ R367_QAM_EQU_SWEEP_RATE,          0x80 },
+	{ R367_QAM_EQU_SNR_LO,              0x64 },
+	{ R367_QAM_EQU_SNR_HI,              0x03 },
+	{ R367_QAM_EQU_GAMMA_LO,            0x00 },
+	{ R367_QAM_EQU_GAMMA_HI,            0x00 },
+	{ R367_QAM_EQU_ERR_GAIN,            0x36 },
+	{ R367_QAM_EQU_RADIUS,              0xaa },
+	{ R367_QAM_EQU_FFE_MAINTAP,         0x00 },
+	{ R367_QAM_EQU_FFE_LEAKAGE,         0x63 },
+	{ R367_QAM_EQU_FFE_MAINTAP_POS,     0xdf },
+	{ R367_QAM_EQU_GAIN_WIDE,           0x88 },
+	{ R367_QAM_EQU_GAIN_NARROW,         0x41 },
+	{ R367_QAM_EQU_CTR_LPF_GAIN,        0xd1 },
+	{ R367_QAM_EQU_CRL_LPF_GAIN,        0xa7 },
+	{ R367_QAM_EQU_GLOBAL_GAIN,         0x06 },
+	{ R367_QAM_EQU_CRL_LD_SEN,          0x85 },
+	{ R367_QAM_EQU_CRL_LD_VAL,          0xe2 },
+	{ R367_QAM_EQU_CRL_TFR,             0x20 },
+	{ R367_QAM_EQU_CRL_BISTH_LO,        0x00 },
+	{ R367_QAM_EQU_CRL_BISTH_HI,        0x00 },
+	{ R367_QAM_EQU_SWEEP_RANGE_LO,      0x00 },
+	{ R367_QAM_EQU_SWEEP_RANGE_HI,      0x00 },
+	{ R367_QAM_EQU_CRL_LIMITER,         0x40 },
+	{ R367_QAM_EQU_MODULUS_MAP,         0x90 },
+	{ R367_QAM_EQU_PNT_GAIN,            0xa7 },
+	{ R367_QAM_FEC_AC_CTR_0,            0x16 },
+	{ R367_QAM_FEC_AC_CTR_1,            0x0b },
+	{ R367_QAM_FEC_AC_CTR_2,            0x88 },
+	{ R367_QAM_FEC_AC_CTR_3,            0x02 },
+	{ R367_QAM_FEC_STATUS,              0x12 },
+	{ R367_QAM_RS_COUNTER_0,            0x7d },
+	{ R367_QAM_RS_COUNTER_1,            0xd0 },
+	{ R367_QAM_RS_COUNTER_2,            0x19 },
+	{ R367_QAM_RS_COUNTER_3,            0x0b },
+	{ R367_QAM_RS_COUNTER_4,            0xa3 },
+	{ R367_QAM_RS_COUNTER_5,            0x00 },
+	{ R367_QAM_BERT_0,                  0x01 },
+	{ R367_QAM_BERT_1,                  0x25 },
+	{ R367_QAM_BERT_2,                  0x41 },
+	{ R367_QAM_BERT_3,                  0x39 },
+	{ R367_QAM_OUTFORMAT_0,             0xc2 },
+	{ R367_QAM_OUTFORMAT_1,             0x22 },
+	{ R367_QAM_SMOOTHER_2,              0x28 },
+	{ R367_QAM_TSMF_CTRL_0,             0x01 },
+	{ R367_QAM_TSMF_CTRL_1,             0xc6 },
+	{ R367_QAM_TSMF_CTRL_3,             0x43 },
+	{ R367_QAM_TS_ON_ID_0,              0x00 },
+	{ R367_QAM_TS_ON_ID_1,              0x00 },
+	{ R367_QAM_TS_ON_ID_2,              0x00 },
+	{ R367_QAM_TS_ON_ID_3,              0x00 },
+	{ R367_QAM_RE_STATUS_0,             0x00 },
+	{ R367_QAM_RE_STATUS_1,             0x00 },
+	{ R367_QAM_RE_STATUS_2,             0x00 },
+	{ R367_QAM_RE_STATUS_3,             0x00 },
+	{ R367_QAM_TS_STATUS_0,             0x00 },
+	{ R367_QAM_TS_STATUS_1,             0x00 },
+	{ R367_QAM_TS_STATUS_2,             0xa0 },
+	{ R367_QAM_TS_STATUS_3,             0x00 },
+	{ R367_QAM_T_O_ID_0,                0x00 },
+	{ R367_QAM_T_O_ID_1,                0x00 },
+	{ R367_QAM_T_O_ID_2,                0x00 },
+	{ R367_QAM_T_O_ID_3,                0x00 },
+	{ 0x0000, 0x00 } // EOT
+};
+
+struct init_table ofdm_init[] = {
+	//{R367_OFDM_ID                   ,0x60},
+	//{R367_OFDM_I2CRPT 				,0x22},
+	//{R367_OFDM_TOPCTRL				,0x02},
+	//{R367_OFDM_IOCFG0				,0x40},
+	//{R367_OFDM_DAC0R				,0x00},
+	//{R367_OFDM_IOCFG1				,0x00},
+	//{R367_OFDM_DAC1R				,0x00},
+	//{R367_OFDM_IOCFG2				,0x62},
+	//{R367_OFDM_SDFR 				,0x00},
+	//{R367_OFDM_STATUS				,0xf8},
+	//{R367_OFDM_AUX_CLK				,0x0a},
+	//{R367_OFDM_FREESYS1			,0x00},
+	//{R367_OFDM_FREESYS2			,0x00},
+	//{R367_OFDM_FREESYS3			,0x00},
+	//{R367_OFDM_GPIO_CFG			,0x55},
+	//{R367_OFDM_GPIO_CMD			,0x00},
+	{R367_OFDM_AGC2MAX				,0xff},
+	{R367_OFDM_AGC2MIN				,0x00},
+	{R367_OFDM_AGC1MAX				,0xff},
+	{R367_OFDM_AGC1MIN				,0x00},
+	{R367_OFDM_AGCR					,0xbc},
+	{R367_OFDM_AGC2TH				,0x00},
+	//{R367_OFDM_AGC12C				,0x01}, //Note: This defines AGC pins, also needed for QAM
+	{R367_OFDM_AGCCTRL1			,0x85},
+	{R367_OFDM_AGCCTRL2			,0x1f},
+	{R367_OFDM_AGC1VAL1			,0x00},
+	{R367_OFDM_AGC1VAL2			,0x00},
+	{R367_OFDM_AGC2VAL1			,0x6f},
+	{R367_OFDM_AGC2VAL2			,0x05},
+	{R367_OFDM_AGC2PGA				,0x00},
+	{R367_OFDM_OVF_RATE1			,0x00},
+	{R367_OFDM_OVF_RATE2			,0x00},
+	{R367_OFDM_GAIN_SRC1			,0x2b},
+	{R367_OFDM_GAIN_SRC2			,0x04},
+	{R367_OFDM_INC_DEROT1			,0x55},
+	{R367_OFDM_INC_DEROT2			,0x55},
+	{R367_OFDM_PPM_CPAMP_DIR		,0x2c},
+	{R367_OFDM_PPM_CPAMP_INV		,0x00},
+	{R367_OFDM_FREESTFE_1			,0x00},
+	{R367_OFDM_FREESTFE_2			,0x1c},
+	{R367_OFDM_DCOFFSET			,0x00},
+	{R367_OFDM_EN_PROCESS			,0x05},
+	{R367_OFDM_SDI_SMOOTHER		,0x80},
+	{R367_OFDM_FE_LOOP_OPEN		,0x1c},
+	{R367_OFDM_FREQOFF1			,0x00},
+	{R367_OFDM_FREQOFF2			,0x00},
+	{R367_OFDM_FREQOFF3			,0x00},
+	{R367_OFDM_TIMOFF1				,0x00},
+	{R367_OFDM_TIMOFF2				,0x00},
+	{R367_OFDM_EPQ					,0x02},
+	{R367_OFDM_EPQAUTO				,0x01},
+	{R367_OFDM_SYR_UPDATE			,0xf5},
+	{R367_OFDM_CHPFREE						,0x00},
+	{R367_OFDM_PPM_STATE_MAC		      ,0x23},
+	{R367_OFDM_INR_THRESHOLD		      ,0xff},
+	{R367_OFDM_EPQ_TPS_ID_CELL	      ,0xf9},
+	{R367_OFDM_EPQ_CFG				      ,0x00},
+	{R367_OFDM_EPQ_STATUS			      ,0x01},
+	{R367_OFDM_AUTORELOCK			      ,0x81},
+	{R367_OFDM_BER_THR_VMSB		      ,0x00},
+	{R367_OFDM_BER_THR_MSB		      ,0x00},
+	{R367_OFDM_BER_THR_LSB		      ,0x00},
+	{R367_OFDM_CCD					      ,0x83},
+	{R367_OFDM_SPECTR_CFG			      ,0x00},
+	{R367_OFDM_CHC_DUMMY			      ,0x18},
+	{R367_OFDM_INC_CTL				      ,0x88},
+	{R367_OFDM_INCTHRES_COR1		      ,0xb4},
+	{R367_OFDM_INCTHRES_COR2		      ,0x96},
+	{R367_OFDM_INCTHRES_DET1		      ,0x0e},
+	{R367_OFDM_INCTHRES_DET2		      ,0x11},
+	{R367_OFDM_IIR_CELLNB				   ,0x8d},
+	{R367_OFDM_IIRCX_COEFF1_MSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF1_LSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF2_MSB	      ,0x09},
+	{R367_OFDM_IIRCX_COEFF2_LSB	      ,0x18},
+	{R367_OFDM_IIRCX_COEFF3_MSB	      ,0x14},
+	{R367_OFDM_IIRCX_COEFF3_LSB	      ,0x9c},
+	{R367_OFDM_IIRCX_COEFF4_MSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF4_LSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF5_MSB	      ,0x36},
+	{R367_OFDM_IIRCX_COEFF5_LSB			,0x42},
+	{R367_OFDM_FEPATH_CFG			      ,0x00},
+	{R367_OFDM_PMC1_FUNC			      ,0x65},
+	{R367_OFDM_PMC1_FOR			      ,0x00},
+	{R367_OFDM_PMC2_FUNC			      ,0x00},
+	{R367_OFDM_STATUS_ERR_DA		      ,0xe0},
+	{R367_OFDM_DIG_AGC_R			      ,0xfe},
+	{R367_OFDM_COMAGC_TARMSB		      ,0x0b},
+	{R367_OFDM_COM_AGC_TAR_ENMODE     ,0x41},
+	{R367_OFDM_COM_AGC_CFG			   ,0x3e},
+	{R367_OFDM_COM_AGC_GAIN1				,0x39},
+	{R367_OFDM_AUT_AGC_TARGETMSB	   ,0x0b},
+	{R367_OFDM_LOCK_DET_MSB			   ,0x01},
+	{R367_OFDM_AGCTAR_LOCK_LSBS		   ,0x40},
+	{R367_OFDM_AUT_GAIN_EN		      ,0xf4},
+	{R367_OFDM_AUT_CFG				      ,0xf0},
+	{R367_OFDM_LOCKN				      ,0x23},
+	{R367_OFDM_INT_X_3				      ,0x00},
+	{R367_OFDM_INT_X_2				      ,0x03},
+	{R367_OFDM_INT_X_1				      ,0x8d},
+	{R367_OFDM_INT_X_0				      ,0xa0},
+	{R367_OFDM_MIN_ERRX_MSB		      ,0x00},
+	{R367_OFDM_COR_CTL				      ,0x00},
+	{R367_OFDM_COR_STAT			      ,0xf6},
+	{R367_OFDM_COR_INTEN			      ,0x00},
+	{R367_OFDM_COR_INTSTAT		      ,0x3f},
+	{R367_OFDM_COR_MODEGUARD		      ,0x03},
+	{R367_OFDM_AGC_CTL				      ,0x08},
+	{R367_OFDM_AGC_MANUAL1		      ,0x00},
+	{R367_OFDM_AGC_MANUAL2		      ,0x00},
+	{R367_OFDM_AGC_TARG			      ,0x16},
+	{R367_OFDM_AGC_GAIN1			      ,0x53},
+	{R367_OFDM_AGC_GAIN2			      ,0x1d},
+	{R367_OFDM_RESERVED_1			      ,0x00},
+	{R367_OFDM_RESERVED_2			      ,0x00},
+	{R367_OFDM_RESERVED_3			      ,0x00},
+	{R367_OFDM_CAS_CTL				      ,0x44},
+	{R367_OFDM_CAS_FREQ			      ,0xb3},
+	{R367_OFDM_CAS_DAGCGAIN		      ,0x12},
+	{R367_OFDM_SYR_CTL				      ,0x04},
+	{R367_OFDM_SYR_STAT			      ,0x10},
+	{R367_OFDM_SYR_NCO1			      ,0x00},
+	{R367_OFDM_SYR_NCO2			      ,0x00},
+	{R367_OFDM_SYR_OFFSET1		      ,0x00},
+	{R367_OFDM_SYR_OFFSET2		      ,0x00},
+	{R367_OFDM_FFT_CTL				      ,0x00},
+	{R367_OFDM_SCR_CTL				      ,0x70},
+	{R367_OFDM_PPM_CTL1			      ,0xf8},
+	{R367_OFDM_TRL_CTL				      ,0xac},
+	{R367_OFDM_TRL_NOMRATE1		      ,0x1e},
+	{R367_OFDM_TRL_NOMRATE2		      ,0x58},
+	{R367_OFDM_TRL_TIME1			      ,0x1d},
+	{R367_OFDM_TRL_TIME2			      ,0xfc},
+	{R367_OFDM_CRL_CTL				      ,0x24},
+	{R367_OFDM_CRL_FREQ1			      ,0xad},
+	{R367_OFDM_CRL_FREQ2			      ,0x9d},
+	{R367_OFDM_CRL_FREQ3			      ,0xff},
+	{R367_OFDM_CHC_CTL		       ,0x01},
+	{R367_OFDM_CHC_SNR				      ,0xf0},
+	{R367_OFDM_BDI_CTL				      ,0x00},
+	{R367_OFDM_DMP_CTL				      ,0x00},
+	{R367_OFDM_TPS_RCVD1			      ,0x30},
+	{R367_OFDM_TPS_RCVD2			      ,0x02},
+	{R367_OFDM_TPS_RCVD3			      ,0x01},
+	{R367_OFDM_TPS_RCVD4			      ,0x00},
+	{R367_OFDM_TPS_ID_CELL1		      ,0x00},
+	{R367_OFDM_TPS_ID_CELL2		      ,0x00},
+	{R367_OFDM_TPS_RCVD5_SET1	      ,0x02},
+	{R367_OFDM_TPS_SET2			      ,0x02},
+	{R367_OFDM_TPS_SET3			      ,0x01},
+	{R367_OFDM_TPS_CTL				      ,0x00},
+	{R367_OFDM_CTL_FFTOSNUM		      ,0x34},
+	{R367_OFDM_TESTSELECT			      ,0x09},
+	{R367_OFDM_MSC_REV 			      ,0x0a},
+	{R367_OFDM_PIR_CTL 			      ,0x00},
+	{R367_OFDM_SNR_CARRIER1 		      ,0xa1},
+	{R367_OFDM_SNR_CARRIER2		      ,0x9a},
+	{R367_OFDM_PPM_CPAMP			      ,0x2c},
+	{R367_OFDM_TSM_AP0				      ,0x00},
+	{R367_OFDM_TSM_AP1				      ,0x00},
+	{R367_OFDM_TSM_AP2 			      ,0x00},
+	{R367_OFDM_TSM_AP3				      ,0x00},
+	{R367_OFDM_TSM_AP4				      ,0x00},
+	{R367_OFDM_TSM_AP5				      ,0x00},
+	{R367_OFDM_TSM_AP6				      ,0x00},
+	{R367_OFDM_TSM_AP7				      ,0x00},
+	//{R367_OFDM_TSTRES				 ,0x00},
+	//{R367_OFDM_ANACTRL				 ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/
+	//{R367_OFDM_TSTBUS				      ,0x00},
+	//{R367_OFDM_TSTRATE				      ,0x00},
+	{R367_OFDM_CONSTMODE			      ,0x01},
+	{R367_OFDM_CONSTCARR1			      ,0x00},
+	{R367_OFDM_CONSTCARR2			      ,0x00},
+	{R367_OFDM_ICONSTEL			      ,0x0a},
+	{R367_OFDM_QCONSTEL			      ,0x15},
+	{R367_OFDM_TSTBISTRES0		      ,0x00},
+	{R367_OFDM_TSTBISTRES1		      ,0x00},
+	{R367_OFDM_TSTBISTRES2		      ,0x28},
+	{R367_OFDM_TSTBISTRES3		      ,0x00},
+	//{R367_OFDM_RF_AGC1				      ,0xff},
+	//{R367_OFDM_RF_AGC2				      ,0x83},
+	//{R367_OFDM_ANADIGCTRL			      ,0x19},
+	//{R367_OFDM_PLLMDIV				      ,0x0c},
+	//{R367_OFDM_PLLNDIV				      ,0x55},
+	//{R367_OFDM_PLLSETUP			      ,0x18},
+	//{R367_OFDM_DUAL_AD12			      ,0x00},
+	//{R367_OFDM_TSTBIST				      ,0x00},
+	//{R367_OFDM_PAD_COMP_CTRL		      ,0x00},
+	//{R367_OFDM_PAD_COMP_WR		      ,0x00},
+	//{R367_OFDM_PAD_COMP_RD		      ,0xe0},
+	{R367_OFDM_SYR_TARGET_FFTADJT_MSB	,0x00},
+	{R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00},
+	{R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00},
+	{R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00},
+	{R367_OFDM_SYR_FLAG			 ,0x00},
+	{R367_OFDM_CRL_TARGET1		 ,0x00},
+	{R367_OFDM_CRL_TARGET2		 ,0x00},
+	{R367_OFDM_CRL_TARGET3		 ,0x00},
+	{R367_OFDM_CRL_TARGET4		 ,0x00},
+	{R367_OFDM_CRL_FLAG			 ,0x00},
+	{R367_OFDM_TRL_TARGET1		 ,0x00},
+	{R367_OFDM_TRL_TARGET2		 ,0x00},
+	{R367_OFDM_TRL_CHC				 ,0x00},
+	{R367_OFDM_CHC_SNR_TARG		 ,0x00},
+	{R367_OFDM_TOP_TRACK			      ,0x00},
+	{R367_OFDM_TRACKER_FREE1		 ,0x00},
+	{R367_OFDM_ERROR_CRL1			 ,0x00},
+	{R367_OFDM_ERROR_CRL2			 ,0x00},
+	{R367_OFDM_ERROR_CRL3			 ,0x00},
+	{R367_OFDM_ERROR_CRL4			 ,0x00},
+	{R367_OFDM_DEC_NCO1			 ,0x2c},
+	{R367_OFDM_DEC_NCO2			 ,0x0f},
+	{R367_OFDM_DEC_NCO3			 ,0x20},
+	{R367_OFDM_SNR					 ,0xf1},
+	{R367_OFDM_SYR_FFTADJ1		      ,0x00},
+	{R367_OFDM_SYR_FFTADJ2		 ,0x00},
+	{R367_OFDM_SYR_CHCADJ1		 ,0x00},
+	{R367_OFDM_SYR_CHCADJ2		 ,0x00},
+	{R367_OFDM_SYR_OFF				 ,0x00},
+	{R367_OFDM_PPM_OFFSET1		      ,0x00},
+	{R367_OFDM_PPM_OFFSET2		 ,0x03},
+	{R367_OFDM_TRACKER_FREE2		 ,0x00},
+	{R367_OFDM_DEBG_LT10			 ,0x00},
+	{R367_OFDM_DEBG_LT11			 ,0x00},
+	{R367_OFDM_DEBG_LT12			      ,0x00},
+	{R367_OFDM_DEBG_LT13			 ,0x00},
+	{R367_OFDM_DEBG_LT14			 ,0x00},
+	{R367_OFDM_DEBG_LT15			 ,0x00},
+	{R367_OFDM_DEBG_LT16			 ,0x00},
+	{R367_OFDM_DEBG_LT17			 ,0x00},
+	{R367_OFDM_DEBG_LT18			 ,0x00},
+	{R367_OFDM_DEBG_LT19			 ,0x00},
+	{R367_OFDM_DEBG_LT1A			 ,0x00},
+	{R367_OFDM_DEBG_LT1B			 ,0x00},
+	{R367_OFDM_DEBG_LT1C 			 ,0x00},
+	{R367_OFDM_DEBG_LT1D 			 ,0x00},
+	{R367_OFDM_DEBG_LT1E			 ,0x00},
+	{R367_OFDM_DEBG_LT1F			 ,0x00},
+	{R367_OFDM_RCCFGH				 ,0x00},
+	{R367_OFDM_RCCFGM						,0x00},
+	{R367_OFDM_RCCFGL						,0x00},
+	{R367_OFDM_RCINSDELH					,0x00},
+	{R367_OFDM_RCINSDELM			 ,0x00},
+	{R367_OFDM_RCINSDELL			 ,0x00},
+	{R367_OFDM_RCSTATUS			 ,0x00},
+	{R367_OFDM_RCSPEED 			 ,0x6f},
+	{R367_OFDM_RCDEBUGM			 ,0xe7},
+	{R367_OFDM_RCDEBUGL			 ,0x9b},
+	{R367_OFDM_RCOBSCFG			 ,0x00},
+	{R367_OFDM_RCOBSM 				 ,0x00},
+	{R367_OFDM_RCOBSL 				 ,0x00},
+	{R367_OFDM_RCFECSPY			 ,0x00},
+	{R367_OFDM_RCFSPYCFG 			 ,0x00},
+	{R367_OFDM_RCFSPYDATA			 ,0x00},
+	{R367_OFDM_RCFSPYOUT 			 ,0x00},
+	{R367_OFDM_RCFSTATUS 			 ,0x00},
+	{R367_OFDM_RCFGOODPACK		 ,0x00},
+	{R367_OFDM_RCFPACKCNT 		 ,0x00},
+	{R367_OFDM_RCFSPYMISC 		 ,0x00},
+	{R367_OFDM_RCFBERCPT4 		 ,0x00},
+	{R367_OFDM_RCFBERCPT3 		 ,0x00},
+	{R367_OFDM_RCFBERCPT2 		 ,0x00},
+	{R367_OFDM_RCFBERCPT1 		 ,0x00},
+	{R367_OFDM_RCFBERCPT0 		 ,0x00},
+	{R367_OFDM_RCFBERERR2 		 ,0x00},
+	{R367_OFDM_RCFBERERR1 		 ,0x00},
+	{R367_OFDM_RCFBERERR0 		 ,0x00},
+	{R367_OFDM_RCFSTATESM 		 ,0x00},
+	{R367_OFDM_RCFSTATESL 		 ,0x00},
+	{R367_OFDM_RCFSPYBER  		 ,0x00},
+	{R367_OFDM_RCFSPYDISTM		 ,0x00},
+	{R367_OFDM_RCFSPYDISTL		 ,0x00},
+	{R367_OFDM_RCFSPYOBS7 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS6 		      ,0x00},
+	{R367_OFDM_RCFSPYOBS5 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS4 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS3 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS2 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS1 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS0			 ,0x00},
+	//{R367_OFDM_TSGENERAL 			 ,0x00},
+	//{R367_OFDM_RC1SPEED  			 ,0x6f},
+	//{R367_OFDM_TSGSTATUS			 ,0x18},
+	{R367_OFDM_FECM					 ,0x01},
+	{R367_OFDM_VTH12				 ,0xff},
+	{R367_OFDM_VTH23				 ,0xa1},
+	{R367_OFDM_VTH34				 ,0x64},
+	{R367_OFDM_VTH56				 ,0x40},
+	{R367_OFDM_VTH67				 ,0x00},
+	{R367_OFDM_VTH78				 ,0x2c},
+	{R367_OFDM_VITCURPUN			 ,0x12},
+	{R367_OFDM_VERROR				 ,0x01},
+	{R367_OFDM_PRVIT				 ,0x3f},
+	{R367_OFDM_VAVSRVIT			 ,0x00},
+	{R367_OFDM_VSTATUSVIT			 ,0xbd},
+	{R367_OFDM_VTHINUSE 			 ,0xa1},
+	{R367_OFDM_KDIV12				 ,0x20},
+	{R367_OFDM_KDIV23				 ,0x40},
+	{R367_OFDM_KDIV34				 ,0x20},
+	{R367_OFDM_KDIV56				 ,0x30},
+	{R367_OFDM_KDIV67				 ,0x00},
+	{R367_OFDM_KDIV78				 ,0x30},
+	{R367_OFDM_SIGPOWER 			 ,0x54},
+	{R367_OFDM_DEMAPVIT 			 ,0x40},
+	{R367_OFDM_VITSCALE 			 ,0x00},
+	{R367_OFDM_FFEC1PRG 			 ,0x00},
+	{R367_OFDM_FVITCURPUN 		 ,0x12},
+	{R367_OFDM_FVERROR 			 ,0x01},
+	{R367_OFDM_FVSTATUSVIT		 ,0xbd},
+	{R367_OFDM_DEBUG_LT1			 ,0x00},
+	{R367_OFDM_DEBUG_LT2			 ,0x00},
+	{R367_OFDM_DEBUG_LT3			 ,0x00},
+	{R367_OFDM_TSTSFMET  			 ,0x00},
+	{R367_OFDM_SELOUT				 ,0x00},
+	{R367_OFDM_TSYNC				 ,0x00},
+	{R367_OFDM_TSTERR				 ,0x00},
+	{R367_OFDM_TSFSYNC   			 ,0x00},
+	{R367_OFDM_TSTSFERR  			 ,0x00},
+	{R367_OFDM_TSTTSSF1  			 ,0x01},
+	{R367_OFDM_TSTTSSF2  			 ,0x1f},
+	{R367_OFDM_TSTTSSF3  			 ,0x00},
+	{R367_OFDM_TSTTS1   			 ,0x00},
+	{R367_OFDM_TSTTS2   			      ,0x1f},
+	{R367_OFDM_TSTTS3   			 ,0x01},
+	{R367_OFDM_TSTTS4   			 ,0x00},
+	{R367_OFDM_TSTTSRC  			 ,0x00},
+	{R367_OFDM_TSTTSRS  			 ,0x00},
+	{R367_OFDM_TSSTATEM			 ,0xb0},
+	{R367_OFDM_TSSTATEL			 ,0x40},
+	{R367_OFDM_TSCFGH  			 ,0x80},
+	{R367_OFDM_TSCFGM  			 ,0x00},
+	{R367_OFDM_TSCFGL  			 ,0x20},
+	{R367_OFDM_TSSYNC  			 ,0x00},
+	{R367_OFDM_TSINSDELH			 ,0x00},
+	{R367_OFDM_TSINSDELM 			 ,0x00},
+	{R367_OFDM_TSINSDELL			 ,0x00},
+	{R367_OFDM_TSDIVN				 ,0x03},
+	{R367_OFDM_TSDIVPM				 ,0x00},
+	{R367_OFDM_TSDIVPL				 ,0x00},
+	{R367_OFDM_TSDIVQM 			 ,0x00},
+	{R367_OFDM_TSDIVQL				 ,0x00},
+	{R367_OFDM_TSDILSTKM			 ,0x00},
+	{R367_OFDM_TSDILSTKL			 ,0x00},
+	{R367_OFDM_TSSPEED				 ,0x6f},
+	{R367_OFDM_TSSTATUS			 ,0x81},
+	{R367_OFDM_TSSTATUS2			 ,0x6a},
+	{R367_OFDM_TSBITRATEM			 ,0x0f},
+	{R367_OFDM_TSBITRATEL			 ,0xc6},
+	{R367_OFDM_TSPACKLENM			 ,0x00},
+	{R367_OFDM_TSPACKLENL			 ,0xfc},
+	{R367_OFDM_TSBLOCLENM			 ,0x0a},
+	{R367_OFDM_TSBLOCLENL			 ,0x80},
+	{R367_OFDM_TSDLYH 				 ,0x90},
+	{R367_OFDM_TSDLYM				 ,0x68},
+	{R367_OFDM_TSDLYL				 ,0x01},
+	{R367_OFDM_TSNPDAV				 ,0x00},
+	{R367_OFDM_TSBUFSTATH 		 ,0x00},
+	{R367_OFDM_TSBUFSTATM 		 ,0x00},
+	{R367_OFDM_TSBUFSTATL			 ,0x00},
+	{R367_OFDM_TSDEBUGM			 ,0xcf},
+	{R367_OFDM_TSDEBUGL			 ,0x1e},
+	{R367_OFDM_TSDLYSETH 			 ,0x00},
+	{R367_OFDM_TSDLYSETM			 ,0x68},
+	{R367_OFDM_TSDLYSETL			 ,0x00},
+	{R367_OFDM_TSOBSCFG			 ,0x00},
+	{R367_OFDM_TSOBSM 				 ,0x47},
+	{R367_OFDM_TSOBSL				 ,0x1f},
+	{R367_OFDM_ERRCTRL1			 ,0x95},
+	{R367_OFDM_ERRCNT1H 			 ,0x80},
+	{R367_OFDM_ERRCNT1M 			 ,0x00},
+	{R367_OFDM_ERRCNT1L 			 ,0x00},
+	{R367_OFDM_ERRCTRL2			 ,0x95},
+	{R367_OFDM_ERRCNT2H			 ,0x00},
+	{R367_OFDM_ERRCNT2M			 ,0x00},
+	{R367_OFDM_ERRCNT2L			 ,0x00},
+	{R367_OFDM_FECSPY 				 ,0x88},
+	{R367_OFDM_FSPYCFG				 ,0x2c},
+	{R367_OFDM_FSPYDATA			 ,0x3a},
+	{R367_OFDM_FSPYOUT				 ,0x06},
+	{R367_OFDM_FSTATUS				 ,0x61},
+	{R367_OFDM_FGOODPACK			 ,0xff},
+	{R367_OFDM_FPACKCNT			 ,0xff},
+	{R367_OFDM_FSPYMISC 			 ,0x66},
+	{R367_OFDM_FBERCPT4 			 ,0x00},
+	{R367_OFDM_FBERCPT3			 ,0x00},
+	{R367_OFDM_FBERCPT2			 ,0x36},
+	{R367_OFDM_FBERCPT1			 ,0x36},
+	{R367_OFDM_FBERCPT0 			 ,0x14},
+	{R367_OFDM_FBERERR2			 ,0x00},
+	{R367_OFDM_FBERERR1			 ,0x03},
+	{R367_OFDM_FBERERR0			 ,0x28},
+	{R367_OFDM_FSTATESM			 ,0x00},
+	{R367_OFDM_FSTATESL			 ,0x02},
+	{R367_OFDM_FSPYBER 			 ,0x00},
+	{R367_OFDM_FSPYDISTM			 ,0x01},
+	{R367_OFDM_FSPYDISTL			 ,0x9f},
+	{R367_OFDM_FSPYOBS7 			 ,0xc9},
+	{R367_OFDM_FSPYOBS6 			 ,0x99},
+	{R367_OFDM_FSPYOBS5			 ,0x08},
+	{R367_OFDM_FSPYOBS4			 ,0xec},
+	{R367_OFDM_FSPYOBS3			 ,0x01},
+	{R367_OFDM_FSPYOBS2			 ,0x0f},
+	{R367_OFDM_FSPYOBS1			 ,0xf5},
+	{R367_OFDM_FSPYOBS0			 ,0x08},
+	{R367_OFDM_SFDEMAP 			 ,0x40},
+	{R367_OFDM_SFERROR 			 ,0x00},
+	{R367_OFDM_SFAVSR  			 ,0x30},
+	{R367_OFDM_SFECSTATUS			 ,0xcc},
+	{R367_OFDM_SFKDIV12			 ,0x20},
+	{R367_OFDM_SFKDIV23			 ,0x40},
+	{R367_OFDM_SFKDIV34			 ,0x20},
+	{R367_OFDM_SFKDIV56			 ,0x20},
+	{R367_OFDM_SFKDIV67			 ,0x00},
+	{R367_OFDM_SFKDIV78			 ,0x20},
+	{R367_OFDM_SFDILSTKM			 ,0x00},
+	{R367_OFDM_SFDILSTKL 			 ,0x00},
+	{R367_OFDM_SFSTATUS			 ,0xb5},
+	{R367_OFDM_SFDLYH				 ,0x90},
+	{R367_OFDM_SFDLYM				 ,0x60},
+	{R367_OFDM_SFDLYL				 ,0x01},
+	{R367_OFDM_SFDLYSETH			 ,0xc0},
+	{R367_OFDM_SFDLYSETM			 ,0x60},
+	{R367_OFDM_SFDLYSETL			 ,0x00},
+	{R367_OFDM_SFOBSCFG 			 ,0x00},
+	{R367_OFDM_SFOBSM 				 ,0x47},
+	{R367_OFDM_SFOBSL				 ,0x05},
+	{R367_OFDM_SFECINFO 			 ,0x40},
+	{R367_OFDM_SFERRCTRL 			 ,0x74},
+	{R367_OFDM_SFERRCNTH			 ,0x80},
+	{R367_OFDM_SFERRCNTM 			 ,0x00},
+	{R367_OFDM_SFERRCNTL			 ,0x00},
+	{R367_OFDM_SYMBRATEM			 ,0x2f},
+	{R367_OFDM_SYMBRATEL			      ,0x50},
+	{R367_OFDM_SYMBSTATUS			 ,0x7f},
+	{R367_OFDM_SYMBCFG 			 ,0x00},
+	{R367_OFDM_SYMBFIFOM 			 ,0xf4},
+	{R367_OFDM_SYMBFIFOL 			 ,0x0d},
+	{R367_OFDM_SYMBOFFSM 			 ,0xf0},
+	{R367_OFDM_SYMBOFFSL 			 ,0x2d},
+	//{R367_OFDM_DEBUG_LT4			 ,0x00},
+	//{R367_OFDM_DEBUG_LT5			 ,0x00},
+	//{R367_OFDM_DEBUG_LT6			 ,0x00},
+	//{R367_OFDM_DEBUG_LT7			 ,0x00},
+	//{R367_OFDM_DEBUG_LT8			 ,0x00},
+	//{R367_OFDM_DEBUG_LT9			 ,0x00},
+	{ 0x0000, 0x00 } // EOT
+};
+
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64)a * (u64)b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+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) {
+		printk("stv0367: i2c_write error\n");
+		return -1;
+	}
+	return 0;
+}
+
+#if 0
+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) {
+		printk("stv0367: i2c_read error\n");
+		return -1;
+	}
+	return 0;
+}
+#endif
+
+static int writereg(struct stv_state *state, u16 reg, u8 dat)
+{
+	u8 mm[3] = { (reg >> 8), reg & 0xff, dat };
+
+	return i2c_write(state->i2c, state->adr, mm, 3);
+}
+
+static int readreg(struct stv_state *state, u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = state->adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1}};
+	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int readregs(struct stv_state *state, u16 reg, u8 *val, int count)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = state->adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = count}};
+	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int write_init_table(struct stv_state *state, struct init_table *tab)
+{
+	while (1) {
+		if (!tab->adr)
+			break;
+		if (writereg(state, tab->adr, tab->data) < 0)
+			return -1;
+		tab++;
+	}
+	return 0;
+}
+
+static int qam_set_modulation(struct stv_state *state)
+{
+	int stat = 0;
+
+	switch(state->modulation) {
+	case QAM_16:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x64);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0x90);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a);
+		break;
+	case QAM_32:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0xb0);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	case QAM_64:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82);   /* Set digital AGC reference */
+		if(state->symbol_rate>4500000)
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xb0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xa0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
+		}
+		else
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xa0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0x99);
+		break;
+	case QAM_128:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x76);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);	/* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0x90);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1);
+		if(state->symbol_rate>4500000) // 45000000
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
+		}
+		else
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	case QAM_256:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);     /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0xa0);
+		if(state->symbol_rate>4500000) // 45000000
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		}
+		else
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	default:
+		stat = -EINVAL;
+		break;
+	}
+	return stat;
+}
+
+
+static int QAM_SetSymbolRate(struct stv_state *state)
+{
+	int status = 0;
+	u32 sr = state->symbol_rate;
+	u32 Corr = 0;
+	u32 Temp, Temp1, AdpClk;
+
+	switch(state->modulation) {
+	default:
+	case QAM_16:   Corr = 1032; break;
+	case QAM_32:   Corr =  954; break;
+	case QAM_64:   Corr =  983; break;
+	case QAM_128:  Corr =  957; break;
+	case QAM_256:  Corr =  948; break;
+	}
+
+	// Transfer ration
+	Temp = (256*sr) / state->adc_clock;
+	writereg(state, R367_QAM_EQU_CRL_TFR,(Temp));
+
+	/* Symbol rate and SRC gain calculation */
+	AdpClk = (state->master_clock) / 2000; /* TRL works at half the system clock */
+
+	Temp = state->symbol_rate;
+	Temp1 = sr;
+
+	if(sr < 2097152)				/* 2097152 = 2^21 */
+	{
+		Temp  = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8;
+		Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000;
+	}
+	else if(sr < 4194304)			/* 4194304 = 2**22 */
+	{
+		Temp  = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16;
+		Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000;
+	}
+	else if(sr < 8388608)			/* 8388608 = 2**23 */
+	{
+		Temp  = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32;
+		Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000;
+	}
+	else
+	{
+		Temp  = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64;
+		Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000;
+	}
+
+	///* Filters' coefficients are calculated and written into registers only if the filters are enabled */
+	//if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init!
+	//{
+	//    FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate);
+	//}
+	///* AllPass filter is never used on this IC */
+	//ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init!
+
+	writereg(state, R367_QAM_SRC_NCO_LL,(Temp));
+	writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8));
+	writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16));
+	writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24));
+
+	writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1));
+	writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8));
+	return status;
+}
+
+
+static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency)
+{
+	int status = 0;
+	u32 Sampled_IF;
+
+	do {
+		//if (DerotFrequency < 1000000)
+		//    DerotFrequency = state->adc_clock/4; /* ZIF operation */
+		if (DerotFrequency > state->adc_clock)
+			DerotFrequency = DerotFrequency - state->adc_clock;	// User Alias
+
+		Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256;
+		if(Sampled_IF > 8388607)
+			Sampled_IF = 8388607;
+
+		writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF));
+		writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8));
+		writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16));
+	} while(0);
+
+	return status;
+}
+
+
+
+static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
+{
+	int status = 0;
+	u32 AGCTimeOut = 25;
+	u32 TRLTimeOut = 100000000 / state->symbol_rate;
+	u32 CRLSymbols = 0;
+	u32 EQLTimeOut = 100;
+	u32 SearchRange = state->symbol_rate / 25;
+	u32 CRLTimeOut;
+	u8 Temp;
+
+	if( state->demod_state != QAMSet ) {
+		writereg(state, R367_DEBUG_LT4,0x00);
+		writereg(state, R367_DEBUG_LT5,0x01);
+		writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1
+		writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2
+		writereg(state, R367_DEBUG_LT8,0x00);
+		writereg(state, R367_DEBUG_LT9,0x00);
+
+		// Tuner Setup
+		writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */
+		writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */
+
+		// Clock setup
+		writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */
+		writereg(state, R367_TOPCTRL,0x10); // Set QAM
+
+		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,232);
+		writereg(state, R367_PLLSETUP,0x18);  /* ADC clock is equal to system clock */
+
+		msleep(50);
+		writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */
+
+		state->master_clock = 58000000;
+		state->adc_clock = 58000000;
+
+		state->demod_state = QAMSet;
+	}
+
+	state->m_bFirstTimeLock = true;
+	state->m_DemodLockTime  = -1;
+
+	qam_set_modulation(state);
+	QAM_SetSymbolRate(state);
+
+	// Will make problems on low symbol rates ( < 2500000 )
+
+	switch(state->modulation) {
+	default:
+	case QAM_16:   CRLSymbols = 150000; break;
+	case QAM_32:   CRLSymbols = 250000; break;
+	case QAM_64:   CRLSymbols = 200000; break;
+	case QAM_128:  CRLSymbols = 250000; break;
+	case QAM_256:  CRLSymbols = 250000; break;
+	}
+
+	CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000);
+	CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate;
+	if( CRLTimeOut < 50 ) CRLTimeOut = 50;
+
+	state->m_FECTimeOut = 20;
+	state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
+	state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut;
+
+	// QAM_AGC_ACCUMRSTSEL = 0;
+	readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL);
+	writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F);
+
+	// QAM_MODULUSMAP_EN = 0
+	readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp);
+	writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40);
+
+	// QAM_SWEEP_EN = 0
+	readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp);
+	writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08);
+
+	QAM_SetDerotFrequency(state, IntermediateFrequency);
+
+	// Release TRL
+	writereg(state, R367_QAM_CTRL_1,0x00);
+
+	state->IF = IntermediateFrequency;
+	state->demod_state = QAMStarted;
+
+	return status;
+}
+
+static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
+{
+	int status = 0;
+	u8 GAIN_SRC1;
+	u32 Derot;
+	u8 SYR_CTL;
+	u8 tmp1;
+	u8 tmp2;
+
+	if ( state->demod_state != OFDMSet ) {
+		// QAM Disable
+		writereg(state, R367_DEBUG_LT4, 0x00);
+		writereg(state, R367_DEBUG_LT5, 0x00);
+		writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1
+		writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2
+		writereg(state, R367_DEBUG_LT8, 0x00);
+		writereg(state, R367_DEBUG_LT9, 0x00);
+
+		// Tuner Setup
+		writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */
+		writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
+
+		// Clock setup
+		writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
+		writereg(state, R367_TOPCTRL, 0x00); // Set OFDM
+
+		writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV, 8);
+		writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
+
+		msleep(50);
+		writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
+
+		state->master_clock = 54000000;
+		state->adc_clock    = 54000000;
+
+		state->demod_state = OFDMSet;
+	}
+
+	state->m_bFirstTimeLock = true;
+	state->m_DemodLockTime  = -1;
+
+	// Set inversion in GAIN_SRC1 (fixed from init)
+	//  is in GAIN_SRC1, see below
+
+	GAIN_SRC1 = 0xA0;
+	// Bandwidth
+
+	// Fixed values for 54 MHz
+	switch(state->bandwidth) {
+	case 0:
+	case 8000000:
+		// Normrate = 44384;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x56);
+		// Gain SRC = 2774
+		writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0xD6);
+		break;
+	case 7000000:
+		// Normrate = 38836;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B);
+		// Gain SRC = 2427
+		writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0x7B);
+		break;
+	case 6000000:
+		// Normrate = 33288;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0x04);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x41);
+		// Gain SRC = 2080
+		writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0x20);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	Derot = ((IntermediateFrequency / 1000) * 65536) / (state->master_clock / 1000);
+
+	writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8));
+	writereg(state, R367_OFDM_INC_DEROT2,(Derot));
+
+	readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL);
+	SYR_CTL  &= ~0x78;
+	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // EchoPos = 0
+
+
+	writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3
+	SYR_CTL &= 0x01;
+	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // SYR_TR_DIS = 0
+
+	msleep(5);
+
+	writereg(state, R367_OFDM_COR_CTL,0x20);    // Start core
+
+	// -- Begin M.V.
+	// Reset FEC and Read Solomon
+	readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	readreg(state, R367_TSGENERAL,&tmp2);
+	writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08);
+	writereg(state, R367_TSGENERAL,tmp2 | 0x01);
+	// -- End M.V.
+
+	state->m_SignalTimeOut = 200;
+	state->IF = IntermediateFrequency;
+	state->demod_state = OFDMStarted;
+	state->m_DemodTimeOut = 0;
+	state->m_FECTimeOut = 0;
+	state->m_TSTimeOut = 0;
+
+	return status;
+}
+
+#if 0
+static int Stop(struct stv_state *state)
+{
+	int status = 0;
+
+	switch(state->demod_state)
+	{
+	case QAMStarted:
+		status = writereg(state, R367_QAM_CTRL_1,0x06);
+		state->demod_state = QAMSet;
+		break;
+	case OFDMStarted:
+		status = writereg(state, R367_OFDM_COR_CTL,0x00);
+		state->demod_state = OFDMSet;
+		break;
+	default:
+		break;
+	}
+	return status;
+}
+#endif
+
+static s32 Log10x100(u32 x)
+{
+	static u32 LookupTable[100] = {
+		101157945, 103514217, 105925373, 108392691, 110917482,
+		113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5
+		127350308, 130316678, 133352143, 136458314, 139636836,
+		142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
+		160324539, 164058977, 167880402, 171790839, 175792361,
+		179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
+		201836636, 206538016, 211348904, 216271852, 221309471,
+		226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
+		254097271, 260015956, 266072506, 272270131, 278612117,
+		285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
+		319889511, 327340695, 334965439, 342767787, 350751874,
+		358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
+		402717034, 412097519, 421696503, 431519077, 441570447,
+		451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
+		506990708, 518800039, 530884444, 543250331, 555904257,
+		568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
+		638263486, 653130553, 668343918, 683911647, 699841996,
+		716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
+		803526122, 822242650, 841395142, 860993752, 881048873,
+		901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
+	};
+	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;
+}
+
+static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
+{
+	u32 RegValAvg = 0;
+	u8 RegVal[2];
+	int status = 0, i;
+
+	*pSignalToNoise = 0;
+	for (i = 0; i < 10; i += 1 ) {
+		readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2);
+		RegValAvg += RegVal[0] + 256 * RegVal[1];
+	}
+	if (RegValAvg != 0) {
+		s32 Power = 1;
+		switch(state->modulation) {
+		case QAM_16:
+			Power = 20480;
+			break;
+		case QAM_32:
+			Power = 23040;
+			break;
+		case QAM_64:
+			Power = 21504;
+			break;
+		case QAM_128:
+			Power = 23616; 
+			break;
+		case QAM_256:
+			Power = 21760; 
+			break;
+		default:
+			break;
+		}
+		*pSignalToNoise = Log10x100((Power * 320) / RegValAvg);
+	} else {
+		*pSignalToNoise = 380;
+	}
+	return status;
+}
+
+static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
+{
+	u8 CHC_SNR = 0;
+
+	int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR);
+	if (status >= 0) {
+		// Note: very unclear documentation on this.
+		//   Datasheet states snr = CHC_SNR/4 dB  -> way to high values!
+		//   Software  snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values
+		//   Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367
+		//   361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best
+		*pSignalToNoise = ( (s32)CHC_SNR * 10) / 8;
+	}
+	//printk("SNR %d\n", *pSignalToNoise);
+	return status;
+}
+
+#if 0
+static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	*pQuality = 100;
+	return 0;
+};
+
+static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	static s32 QE_SN[] = {
+		51, // QPSK 1/2
+		69, // QPSK 2/3
+		79, // QPSK 3/4
+		89, // QPSK 5/6
+		97, // QPSK 7/8
+		108, // 16-QAM 1/2
+		131, // 16-QAM 2/3
+		146, // 16-QAM 3/4
+		156, // 16-QAM 5/6
+		160, // 16-QAM 7/8
+		165, // 64-QAM 1/2
+		187, // 64-QAM 2/3
+		202, // 64-QAM 3/4
+		216, // 64-QAM 5/6
+		225, // 64-QAM 7/8
+	};
+	u8 TPS_Received[2];
+	int Constellation;
+	int CodeRate;
+	s32 SignalToNoiseRel, BERQuality;
+
+	*pQuality = 0;
+	readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received));
+	Constellation = TPS_Received[0] & 0x03;
+	CodeRate = TPS_Received[1] & 0x07;
+
+	if( Constellation > 2 || CodeRate > 5 )
+		return -1;
+	SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate];
+	BERQuality = 100;
+
+	if( SignalToNoiseRel < -70 )
+		*pQuality = 0;
+	else if( SignalToNoiseRel < 30 ) {
+		*pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100;
+	} else
+		*pQuality = BERQuality;
+	return 0;
+};
+
+static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise)
+{
+	s32 SignalToNoiseRel = 0;
+	s32 Quality = 0;
+	s32 BERQuality = 100;
+
+	switch(state->modulation) {
+	case QAM_16:  SignalToNoiseRel = SignalToNoise - 200 ; break;
+	case QAM_32:  SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig
+	case QAM_64:  SignalToNoiseRel = SignalToNoise - 260 ; break;
+	case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break;
+	case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break;
+	}
+
+	if( SignalToNoiseRel < -70 ) Quality = 0;
+	else if( SignalToNoiseRel < 30 )
+	{
+		Quality = ((SignalToNoiseRel + 70) * BERQuality)/100;
+	}
+	else
+	Quality = BERQuality;
+
+	return Quality;
+}
+
+static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	*pQuality = 0;
+	switch(state->demod_state)
+	{
+	case QAMStarted:
+		*pQuality = DVBCQuality(state, SignalToNoise);
+		break;
+	case OFDMStarted:
+		return DVBT_GetQuality(state, SignalToNoise, pQuality);
+	}
+	return 0;
+};
+#endif
+
+static int attach_init(struct stv_state *state)
+{
+	int stat = 0;
+
+	stat = readreg(state, R367_ID, &state->ID);
+	if ( stat < 0 || state->ID != 0x60 )
+		return -ENODEV;
+	printk("stv0367 found\n");
+
+	writereg(state, R367_TOPCTRL, 0x10);
+	write_init_table(state, base_init);
+	write_init_table(state, qam_init);
+
+	writereg(state, R367_TOPCTRL, 0x00);
+	write_init_table(state, ofdm_init);
+
+	writereg(state, R367_OFDM_GAIN_SRC1, 0x2A);
+	writereg(state, R367_OFDM_GAIN_SRC2, 0xD6);
+	writereg(state, R367_OFDM_INC_DEROT1, 0x55);
+	writereg(state, R367_OFDM_INC_DEROT2, 0x55);
+	writereg(state, R367_OFDM_TRL_CTL, 0x14);
+	writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE);
+	writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56);
+	writereg(state, R367_OFDM_FEPATH_CFG, 0x0);
+
+	// OFDM TS Setup
+
+	writereg(state, R367_OFDM_TSCFGH, 0x70);
+	writereg(state, R367_OFDM_TSCFGM, 0xC0);
+	writereg(state, R367_OFDM_TSCFGL, 0x20);
+	writereg(state, R367_OFDM_TSSPEED, 0x40);        // Fixed at 54 MHz
+	//writereg(state, R367_TSTBUS, 0x80);      // Invert CLK
+
+	writereg(state, R367_OFDM_TSCFGH, 0x71);
+	writereg(state, R367_OFDM_TSCFGH, 0x70);
+
+	writereg(state, R367_TOPCTRL, 0x10);
+
+	// Also needed for QAM
+	writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup
+
+	writereg(state, R367_OFDM_AGCCTRL1, 0x8A); //
+
+	// QAM TS setup, note exact format also depends on descrambler settings
+	writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial
+	// writereg(state, R367_QAM_OUTFORMAT_1, 0x00); //
+
+	// Clock setup
+	writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
+
+	if( state->master_clock == 58000000 ) {
+		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,232);
+	} else {
+		writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,8);
+	}
+	writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
+
+	// Tuner setup
+	writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */
+	writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
+
+	writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */
+	writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */
+	writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */
+	writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */
+
+	writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
+
+	writereg(state, R367_I2CRPT, state->I2CRPT);
+	state->demod_state    = QAMSet;
+	return stat;
+}
+
+#ifdef USE_API3
+static void c_release(struct dvb_frontend* fe)
+#else
+static void release(struct dvb_frontend* fe)
+#endif
+{
+	struct stv_state *state=fe->demodulator_priv;
+	printk("%s\n", __FUNCTION__);
+	kfree(state);
+}
+
+#ifdef USE_API3
+static int c_init (struct dvb_frontend *fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+
+	if (mutex_trylock(&state->ctlock)==0)
+		return -EBUSY;
+	state->omode = OM_DVBC;
+	return 0;
+}
+
+static int c_sleep(struct dvb_frontend* fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+
+	mutex_unlock(&state->ctlock);
+	return 0;
+}
+#endif
+
+static int gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u8 i2crpt = state->I2CRPT & ~0x80;
+
+	if (enable)
+		i2crpt |= 0x80;
+	if (writereg(state, R367_I2CRPT, i2crpt) < 0)
+		return -1;
+	state->I2CRPT = i2crpt;
+	return 0;
+}
+
+#if 0
+static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	return DVBFE_ALGO_SEARCH_AGAIN;
+}
+#endif
+
+#if 0
+int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+#endif
+
+static int ofdm_lock(struct stv_state *state)
+{
+	int status = 0;
+	u8 OFDM_Status;
+	s32 DemodTimeOut = 10;
+	s32 FECTimeOut = 0;
+	s32 TSTimeOut = 0;
+	u8 CPAMPMin = 255;
+	u8 CPAMPValue;
+	u8 SYR_STAT;
+	u8 FFTMode;
+	u8 TSStatus;
+
+	msleep(state->m_SignalTimeOut);
+	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
+
+	if (!(OFDM_Status & 0x40))
+		return -1;
+	//printk("lock 1\n");
+
+	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
+	FFTMode = (SYR_STAT & 0x0C) >> 2;
+
+	switch(FFTMode)
+	{
+	    case 0: // 2K
+		DemodTimeOut = 10;
+		FECTimeOut = 150;
+		TSTimeOut = 125;
+		CPAMPMin = 20;
+		break;
+	    case 1: // 8K
+		DemodTimeOut = 55;
+		FECTimeOut = 600;
+		TSTimeOut = 500;
+		CPAMPMin = 80;
+		break;
+	    case 2: // 4K
+		DemodTimeOut = 40;
+		FECTimeOut = 300;
+		TSTimeOut = 250;
+		CPAMPMin = 30;
+		break;
+	}
+	state->m_OFDM_FFTMode = FFTMode;
+	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
+	msleep(DemodTimeOut);
+	{
+	    // Release FEC and Read Solomon Reset
+	    u8 tmp1;
+	    u8 tmp2;
+	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	    readreg(state, R367_TSGENERAL,&tmp2);
+	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
+	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
+	}
+	msleep(FECTimeOut);
+	if( (OFDM_Status & 0x98) != 0x98 )
+		;//return -1;
+	//printk("lock 2\n");
+
+	{
+	    u8 Guard = (SYR_STAT & 0x03);
+	    if(Guard < 2)
+	    {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
+	    } else {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
+	    }
+
+	    // apply Sfec workaround if 8K 64QAM CR!=1/2
+	    if( FFTMode == 1)
+	    {
+		u8 tmp[2];
+		readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2);
+		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
+		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
+		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
+		}
+		else
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
+		}
+	    }
+	}
+	msleep(TSTimeOut);
+	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
+	if( (TSStatus & 0x80) != 0x80 )
+		return -1;
+	//printk("lock 3\n");
+	return status;
+}
+
+
+#ifdef USE_API3
+static int set_parameters(struct dvb_frontend *fe,
+			  struct dvb_frontend_parameters *p)
+{
+	int stat;
+	struct stv_state *state = fe->demodulator_priv;
+	u32 OF = 0;
+	u32 IF;
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, p);
+
+	switch (state->omode) {
+	case OM_DVBC:
+	case OM_QAM_ITU_C:
+		state->modulation = p->u.qam.modulation;
+		state->symbol_rate = p->u.qam.symbol_rate;
+		break;
+	case OM_DVBT:
+		switch (p->u.ofdm.bandwidth) {
+		case BANDWIDTH_AUTO:
+		case BANDWIDTH_8_MHZ:
+			state->bandwidth = 8000000;
+			break;
+		case BANDWIDTH_7_MHZ:
+			state->bandwidth = 7000000;
+			break;
+		case BANDWIDTH_6_MHZ:
+			state->bandwidth = 6000000;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+#else
+static int set_parameters(struct dvb_frontend *fe)
+{
+	int stat;
+	struct stv_state *state = fe->demodulator_priv;
+	u32 OF = 0;
+	u32 IF;
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+		state->omode = OM_DVBC;
+		/* symbol rate 0 might cause an oops */
+		if (fe->dtv_property_cache.symbol_rate == 0) {
+			printk(KERN_ERR "stv0367dd: Invalid symbol rate\n");
+			return -EINVAL;
+		}
+		break;
+	case SYS_DVBT:
+		state->omode = OM_DVBT;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+	state->modulation = fe->dtv_property_cache.modulation;
+	state->symbol_rate = fe->dtv_property_cache.symbol_rate;
+	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
+#endif
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	//fe->ops.tuner_ops.get_frequency(fe, &IF);
+
+	switch(state->omode) {
+	case OM_DVBT:
+		stat = OFDM_Start(state, OF, IF);
+		ofdm_lock(state);
+		break;
+	case OM_DVBC:
+	case OM_QAM_ITU_C:
+		stat = QAM_Start(state, OF, IF);
+		break;
+	default:
+		stat = -EINVAL;
+	}
+	//printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF);
+	return stat;
+}
+
+#if 0
+static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	//struct stv_state *state = fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	return 0;
+}
+
+static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time)
+{
+	int status = STATUS_SUCCESS;
+	u8 OFDM_Status;
+	s32 DemodTimeOut = 0;
+	s32 FECTimeOut = 0;
+	s32 TSTimeOut = 0;
+	u8 CPAMPMin = 255;
+	u8 CPAMPValue;
+	bool SYRLock;
+	u8 SYR_STAT;
+	u8 FFTMode;
+	u8 TSStatus;
+
+	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
+
+	SYRLock = (OFDM_Status & 0x40) != 0;
+
+	if( Time > m_SignalTimeOut && !SYRLock )
+	{
+	    *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( !SYRLock ) break;
+
+	*pLockStatus = SIGNAL_PRESENT;
+
+	// Check Mode
+
+	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
+	FFTMode = (SYR_STAT & 0x0C) >> 2;
+
+	switch(FFTMode)
+	{
+	    case 0: // 2K
+		DemodTimeOut = 10;
+		FECTimeOut = 150;
+		TSTimeOut = 125;
+		CPAMPMin = 20;
+		break;
+	    case 1: // 8K
+		DemodTimeOut = 55;
+		FECTimeOut = 600;
+		TSTimeOut = 500;
+		CPAMPMin = 80;
+		break;
+	    case 2: // 4K
+		DemodTimeOut = 40;
+		FECTimeOut = 300;
+		TSTimeOut = 250;
+		CPAMPMin = 30;
+		break;
+	}
+
+	m_OFDM_FFTMode = FFTMode;
+
+	if( m_DemodTimeOut == 0 && m_bFirstTimeLock )
+	{
+	    m_DemodTimeOut = Time + DemodTimeOut;
+	    //break;
+	}
+
+	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
+
+	if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin )
+	{
+	    break;
+	}
+
+	if( CPAMPValue < CPAMPMin && m_bFirstTimeLock )
+	{
+	    // initiate retry
+	    *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( CPAMPValue < CPAMPMin ) break;
+
+	*pLockStatus = DEMOD_LOCK;
+
+	if( m_FECTimeOut == 0 && m_bFirstTimeLock )
+	{
+	    // Release FEC and Read Solomon Reset
+	    u8 tmp1;
+	    u8 tmp2;
+	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	    readreg(state, R367_TSGENERAL,&tmp2);
+	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
+	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
+
+	    m_FECTimeOut = Time + FECTimeOut;
+	}
+
+	// Wait for TSP_LOCK, LK, PRF
+	if( (OFDM_Status & 0x98) != 0x98 )
+	{
+	    if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( m_bFirstTimeLock && m_TSTimeOut == 0)
+	{
+	    u8 Guard = (SYR_STAT & 0x03);
+	    if(Guard < 2)
+	    {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
+	    } else {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
+	    }
+
+	    // apply Sfec workaround if 8K 64QAM CR!=1/2
+	    if( FFTMode == 1)
+	    {
+		u8 tmp[2];
+		readreg(state, R367_OFDM_TPS_RCVD2,tmp,2);
+		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
+		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
+		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
+		}
+		else
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
+		}
+	    }
+
+	    m_TSTimeOut = Time + TSTimeOut;
+	}
+	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
+	if( (TSStatus & 0x80) != 0x80 )
+	{
+		if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+	*pLockStatus = MPEG_LOCK;
+	m_bFirstTimeLock = false;
+	return status;
+}
+
+#endif
+
+static int read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	*status=0;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+	{
+		u8 FEC_Lock;
+		u8 QAM_Lock;
+
+		readreg(state, R367_QAM_FSM_STS, &QAM_Lock);
+		QAM_Lock &= 0x0F;
+		if (QAM_Lock >10)
+			*status|=0x07;
+		readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock);
+		if (FEC_Lock&2)
+			*status|=0x1f;
+		if (state->m_bFirstTimeLock) {
+			state->m_bFirstTimeLock = false;
+			// QAM_AGC_ACCUMRSTSEL to Tracking;
+			writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL);
+		}
+		break;
+	}
+	case OFDMStarted:
+	{
+		u8 OFDM_Status;
+		u8 TSStatus;
+
+		readreg(state, R367_OFDM_TSSTATUS, &TSStatus);
+
+		readreg(state, R367_OFDM_STATUS, &OFDM_Status);
+		if (OFDM_Status & 0x40)
+			*status |= FE_HAS_SIGNAL;
+
+		if ((OFDM_Status & 0x98) == 0x98)
+			*status|=0x0f;
+
+		if (TSStatus & 0x80)
+			*status |= 0x1f;
+		break;
+	}
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int read_ber_ter(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u32 err;
+	u8 cnth, cntm, cntl;
+
+#if 1
+	readreg(state, R367_OFDM_SFERRCNTH, &cnth);
+
+	if (cnth & 0x80) {
+		*ber = state->ber; 
+		return 0;
+	}
+
+	readreg(state, R367_OFDM_SFERRCNTM, &cntm);
+	readreg(state, R367_OFDM_SFERRCNTL, &cntl);
+
+	err = ((cnth & 0x7f) << 16) | (cntm << 8) | cntl;
+	
+#if 0
+	{
+		u64 err64;
+		err64 = (u64) err;
+		err64 *= 1000000000ULL;
+		err64 >>= 21;
+		err = err64;
+	}
+#endif
+#else
+	readreg(state, R367_OFDM_ERRCNT1HM, &cnth);
+
+#endif
+	*ber = state->ber = err;
+	return 0;
+}
+
+static int read_ber_cab(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u32 err;
+	u8 cntm, cntl, ctrl;
+
+	readreg(state, R367_QAM_BERT_1, &ctrl);
+	if (!(ctrl & 0x20)) {
+		readreg(state, R367_QAM_BERT_2, &cntl);
+		readreg(state, R367_QAM_BERT_3, &cntm);
+		err = (cntm << 8) | cntl;
+		//printk("err %04x\n", err);
+		state->ber = err;
+		writereg(state, R367_QAM_BERT_1, 0x27);
+	}
+	*ber = (u32) state->ber;
+	return 0;
+}
+
+static int read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv_state *state = fe->demodulator_priv;
+
+	if (state->demod_state == QAMStarted)
+		return read_ber_cab(fe, ber);
+	if (state->demod_state == OFDMStarted)
+		return read_ber_ter(fe, ber);
+	*ber = 0;
+	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 int read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ 	struct stv_state *state = fe->demodulator_priv;
+	s32 snr2 = 0;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+		QAM_GetSignalToNoise(state, &snr2);
+		break;
+	case OFDMStarted:
+		OFDM_GetSignalToNoise(state, &snr2);
+		break;
+	default:
+		break;
+	}
+	*snr = snr2&0xffff;
+	return 0;
+}
+
+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u8 errl, errm, errh;
+	u8 val;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+		readreg(state, R367_QAM_RS_COUNTER_4, &errl);
+		readreg(state, R367_QAM_RS_COUNTER_5, &errm);
+		*ucblocks = (errm << 8) | errl;
+		break;
+	case OFDMStarted:
+		readreg(state, R367_OFDM_SFERRCNTH, &val);
+		if ((val & 0x80) == 0) {
+			readreg(state, R367_OFDM_ERRCNT1H, &errh);
+			readreg(state, R367_OFDM_ERRCNT1M, &errl);
+			readreg(state, R367_OFDM_ERRCNT1L, &errm);
+			state->ucblocks = (errh <<16) | (errm << 8) | errl;
+		}
+		*ucblocks = state->ucblocks;
+		break;
+	default:
+		*ucblocks = 0;
+		break;
+	}
+	return 0;
+}
+
+static int c_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *sets)
+{
+	sets->min_delay_ms=3000;
+	sets->max_drift=0;
+	sets->step_size=0;
+	return 0;
+}
+
+#ifndef USE_API3
+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;
+	}
+}
+#endif
+
+#ifdef USE_API3
+static void t_release(struct dvb_frontend* fe)
+{
+	//struct stv_state *state=fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	//kfree(state);
+}
+
+static int t_init (struct dvb_frontend *fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+	if (mutex_trylock(&state->ctlock)==0)
+		return -EBUSY;
+	state->omode = OM_DVBT;
+	return 0;
+}
+
+static int t_sleep(struct dvb_frontend* fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+	mutex_unlock(&state->ctlock);
+	return 0;
+}
+#endif
+
+#if 0
+static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	//struct stv_state *state = fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	return 0;
+}
+
+static enum dvbfe_algo algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+#endif
+
+#ifdef USE_API3
+static struct dvb_frontend_ops c_ops = {
+	.info = {
+		.name = "STV0367 DVB-C",
+		.type = FE_QAM,
+		.frequency_stepsize = 62500,
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
+	},
+	.release = c_release,
+	.init = c_init,
+	.sleep = c_sleep,
+	.i2c_gate_ctrl = gate_ctrl,
+
+	.get_tune_settings = c_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,
+
+#if 1
+	.set_frontend = set_parameters,
+#else
+	.get_frontend_algo = algo,
+	.search = search,
+#endif
+};
+
+static struct dvb_frontend_ops t_ops = {
+	.info = {
+		.name			= "STV0367 DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 47125000,
+		.frequency_max		= 865000000,
+		.frequency_stepsize	= 166667,
+		.frequency_tolerance	= 0,
+		.caps = 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_QAM_16 | FE_CAN_QAM_64 |
+		FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO |
+		FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+		FE_CAN_MUTE_TS
+	},
+	.release = t_release,
+	.init = t_init,
+	.sleep = t_sleep,
+	.i2c_gate_ctrl = gate_ctrl,
+
+	.set_frontend = set_parameters,
+
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+};
+
+#else
+
+static struct dvb_frontend_ops common_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT },
+	.info = {
+		.name = "STV0367 DVB-C DVB-T",
+		.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,
+
+	.get_tune_settings = get_tune_settings,
+
+	.set_frontend = set_parameters,
+
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+};
+#endif
+
+
+static void init_state(struct stv_state *state, struct stv0367_cfg *cfg)
+{
+	u32 ulENARPTLEVEL = 5;
+	u32 ulQAMInversion = 2;
+	state->omode = OM_NONE;
+	state->adr = cfg->adr;
+
+	mutex_init(&state->mutex);
+	mutex_init(&state->ctlock);
+
+#ifdef USE_API3
+	memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops));
+	state->c_frontend.demodulator_priv = state;
+	state->t_frontend.demodulator_priv = state;
+#else
+	memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+#endif
+
+	state->master_clock = 58000000;
+	state->adc_clock = 58000000;
+	state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4);
+	state->qam_inversion = ((ulQAMInversion & 3) << 6 );
+	state->demod_state   = Off;
+}
+
+
+struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg,
+				    struct dvb_frontend **fe_t)
+{
+	struct stv_state *state = NULL;
+
+	state = kzalloc(sizeof(struct stv_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->i2c = i2c;
+	init_state(state, cfg);
+
+	if (attach_init(state)<0)
+		goto error;
+#ifdef USE_API3
+	*fe_t = &state->t_frontend;
+	return &state->c_frontend;
+#else
+	return &state->frontend;
+#endif
+
+error:
+	printk("stv0367: not found\n");
+	kfree(state);
+	return NULL;
+}
+
+
+MODULE_DESCRIPTION("STV0367DD driver");
+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(stv0367_attach);
+
+
+
diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h
new file mode 100644
index 0000000..a13df69
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367dd.h
@@ -0,0 +1,48 @@
+/*
+ *  stv0367dd.h: STV0367 DVB-C/T demodulator driver
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#ifndef _STV0367DD_H_
+#define _STV0367DD_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct stv0367_cfg {
+	u8  adr;
+	u32 xtal;
+	u32 ts_mode;
+};
+
+#if IS_ENABLED(CONFIG_DVB_STV0367DD)
+extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
+					   struct stv0367_cfg *cfg,
+					   struct dvb_frontend **fe_t);
+#else
+static inline struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
+						  struct stv0367_cfg *cfg,
+						  struct dvb_frontend **fe_t);
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h
new file mode 100644
index 0000000..3881f55
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367dd_regs.h
@@ -0,0 +1,3442 @@
+/*
+ *  stv0367dd_regs.h: DVB-C/DVB-T STMicroelectronics STV0367
+ *                    register defintions
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#ifndef _STV0367DD_REGS_H_
+#define _STV0367DD_REGS_H_
+
+/* ID */
+#define	R367_ID		0xF000
+#define	F367_IDENTIFICATIONREG		0xF00000FF
+
+/* I2CRPT */
+#define	R367_I2CRPT		0xF001
+#define	F367_I2CT_ON		0xF0010080
+#define	F367_ENARPT_LEVEL		0xF0010070
+#define	F367_SCLT_DELAY		0xF0010008
+#define	F367_SCLT_NOD		0xF0010004
+#define	F367_STOP_ENABLE		0xF0010002
+#define	F367_SDAT_NOD		0xF0010001
+
+/* TOPCTRL */
+#define	R367_TOPCTRL		0xF002
+#define	F367_STDBY		0xF0020080
+#define	F367_STDBY_FEC		0xF0020040
+#define	F367_STDBY_CORE		0xF0020020
+#define	F367_QAM_COFDM		0xF0020010
+#define	F367_TS_DIS		0xF0020008
+#define	F367_DIR_CLK_216		0xF0020004
+#define	F367_TUNER_BB		0xF0020002
+#define	F367_DVBT_H		0xF0020001
+
+/* IOCFG0 */
+#define	R367_IOCFG0		0xF003
+#define	F367_OP0_SD		0xF0030080
+#define	F367_OP0_VAL		0xF0030040
+#define	F367_OP0_OD		0xF0030020
+#define	F367_OP0_INV		0xF0030010
+#define	F367_OP0_DACVALUE_HI		0xF003000F
+
+/* DAC0R */
+#define	R367_DAC0R		0xF004
+#define	F367_OP0_DACVALUE_LO		0xF00400FF
+
+/* IOCFG1 */
+#define	R367_IOCFG1		0xF005
+#define	F367_IP0		0xF0050040
+#define	F367_OP1_OD		0xF0050020
+#define	F367_OP1_INV		0xF0050010
+#define	F367_OP1_DACVALUE_HI		0xF005000F
+
+/* DAC1R */
+#define	R367_DAC1R		0xF006
+#define	F367_OP1_DACVALUE_LO		0xF00600FF
+
+/* IOCFG2 */
+#define	R367_IOCFG2		0xF007
+#define	F367_OP2_LOCK_CONF		0xF00700E0
+#define	F367_OP2_OD		0xF0070010
+#define	F367_OP2_VAL		0xF0070008
+#define	F367_OP1_LOCK_CONF		0xF0070007
+
+/* SDFR */
+#define	R367_SDFR		0xF008
+#define	F367_OP0_FREQ		0xF00800F0
+#define	F367_OP1_FREQ		0xF008000F
+
+/* STATUS */
+#define	R367_OFDM_STATUS		0xF009
+#define	F367_TPS_LOCK		0xF0090080
+#define	F367_SYR_LOCK		0xF0090040
+#define	F367_AGC_LOCK		0xF0090020
+#define	F367_PRF		0xF0090010
+#define	F367_LK		0xF0090008
+#define	F367_PR		0xF0090007
+
+/* AUX_CLK */
+#define	R367_AUX_CLK		0xF00A
+#define	F367_AUXFEC_CTL		0xF00A00C0
+#define	F367_DIS_CKX4		0xF00A0020
+#define	F367_CKSEL		0xF00A0018
+#define	F367_CKDIV_PROG		0xF00A0006
+#define	F367_AUXCLK_ENA		0xF00A0001
+
+/* FREESYS1 */
+#define	R367_FREESYS1		0xF00B
+#define	F367_FREE_SYS1		0xF00B00FF
+
+/* FREESYS2 */
+#define	R367_FREESYS2		0xF00C
+#define	F367_FREE_SYS2		0xF00C00FF
+
+/* FREESYS3 */
+#define	R367_FREESYS3		0xF00D
+#define	F367_FREE_SYS3		0xF00D00FF
+
+/* GPIO_CFG */
+#define	R367_GPIO_CFG		0xF00E
+#define	F367_GPIO7_NOD		0xF00E0080
+#define	F367_GPIO7_CFG		0xF00E0040
+#define	F367_GPIO6_NOD		0xF00E0020
+#define	F367_GPIO6_CFG		0xF00E0010
+#define	F367_GPIO5_NOD		0xF00E0008
+#define	F367_GPIO5_CFG		0xF00E0004
+#define	F367_GPIO4_NOD		0xF00E0002
+#define	F367_GPIO4_CFG		0xF00E0001
+
+/* GPIO_CMD */
+#define	R367_GPIO_CMD		0xF00F
+#define	F367_GPIO7_VAL		0xF00F0008
+#define	F367_GPIO6_VAL		0xF00F0004
+#define	F367_GPIO5_VAL		0xF00F0002
+#define	F367_GPIO4_VAL		0xF00F0001
+
+/* AGC2MAX */
+#define	R367_OFDM_AGC2MAX		0xF010
+#define	F367_OFDM_AGC2_MAX		0xF01000FF
+
+/* AGC2MIN */
+#define	R367_OFDM_AGC2MIN		0xF011
+#define	F367_OFDM_AGC2_MIN		0xF01100FF
+
+/* AGC1MAX */
+#define	R367_OFDM_AGC1MAX		0xF012
+#define	F367_OFDM_AGC1_MAX		0xF01200FF
+
+/* AGC1MIN */
+#define	R367_OFDM_AGC1MIN		0xF013
+#define	F367_OFDM_AGC1_MIN		0xF01300FF
+
+/* AGCR */
+#define	R367_OFDM_AGCR		0xF014
+#define	F367_OFDM_RATIO_A		0xF01400E0
+#define	F367_OFDM_RATIO_B		0xF0140018
+#define	F367_OFDM_RATIO_C		0xF0140007
+
+/* AGC2TH */
+#define	R367_OFDM_AGC2TH		0xF015
+#define	F367_OFDM_AGC2_THRES		0xF01500FF
+
+/* AGC12C */
+#define	R367_OFDM_AGC12C		0xF016
+#define	F367_OFDM_AGC1_IV		0xF0160080
+#define	F367_OFDM_AGC1_OD		0xF0160040
+#define	F367_OFDM_AGC1_LOAD		0xF0160020
+#define	F367_OFDM_AGC2_IV		0xF0160010
+#define	F367_OFDM_AGC2_OD		0xF0160008
+#define	F367_OFDM_AGC2_LOAD		0xF0160004
+#define	F367_OFDM_AGC12_MODE		0xF0160003
+
+/* AGCCTRL1 */
+#define	R367_OFDM_AGCCTRL1		0xF017
+#define	F367_OFDM_DAGC_ON		0xF0170080
+#define	F367_OFDM_INVERT_AGC12		0xF0170040
+#define	F367_OFDM_AGC1_MODE		0xF0170008
+#define	F367_OFDM_AGC2_MODE		0xF0170007
+
+/* AGCCTRL2 */
+#define	R367_OFDM_AGCCTRL2		0xF018
+#define	F367_OFDM_FRZ2_CTRL		0xF0180060
+#define	F367_OFDM_FRZ1_CTRL		0xF0180018
+#define	F367_OFDM_TIME_CST		0xF0180007
+
+/* AGC1VAL1 */
+#define	R367_OFDM_AGC1VAL1		0xF019
+#define	F367_OFDM_AGC1_VAL_LO		0xF01900FF
+
+/* AGC1VAL2 */
+#define	R367_OFDM_AGC1VAL2		0xF01A
+#define	F367_OFDM_AGC1_VAL_HI		0xF01A000F
+
+/* AGC2VAL1 */
+#define	R367_OFDM_AGC2VAL1		0xF01B
+#define	F367_OFDM_AGC2_VAL_LO		0xF01B00FF
+
+/* AGC2VAL2 */
+#define	R367_OFDM_AGC2VAL2		0xF01C
+#define	F367_OFDM_AGC2_VAL_HI		0xF01C000F
+
+/* AGC2PGA */
+#define	R367_OFDM_AGC2PGA		0xF01D
+#define	F367_OFDM_AGC2_PGA		0xF01D00FF
+
+/* OVF_RATE1 */
+#define	R367_OFDM_OVF_RATE1		0xF01E
+#define	F367_OFDM_OVF_RATE_HI		0xF01E000F
+
+/* OVF_RATE2 */
+#define	R367_OFDM_OVF_RATE2		0xF01F
+#define	F367_OFDM_OVF_RATE_LO		0xF01F00FF
+
+/* GAIN_SRC1 */
+#define	R367_OFDM_GAIN_SRC1		0xF020
+#define	F367_OFDM_INV_SPECTR		0xF0200080
+#define	F367_OFDM_IQ_INVERT		0xF0200040
+#define	F367_OFDM_INR_BYPASS		0xF0200020
+#define	F367_OFDM_STATUS_INV_SPECRUM		0xF0200010
+#define	F367_OFDM_GAIN_SRC_HI		0xF020000F
+
+/* GAIN_SRC2 */
+#define	R367_OFDM_GAIN_SRC2		0xF021
+#define	F367_OFDM_GAIN_SRC_LO		0xF02100FF
+
+/* INC_DEROT1 */
+#define	R367_OFDM_INC_DEROT1		0xF022
+#define	F367_OFDM_INC_DEROT_HI		0xF02200FF
+
+/* INC_DEROT2 */
+#define	R367_OFDM_INC_DEROT2		0xF023
+#define	F367_OFDM_INC_DEROT_LO		0xF02300FF
+
+/* PPM_CPAMP_DIR */
+#define	R367_OFDM_PPM_CPAMP_DIR		0xF024
+#define	F367_OFDM_PPM_CPAMP_DIRECT		0xF02400FF
+
+/* PPM_CPAMP_INV */
+#define	R367_OFDM_PPM_CPAMP_INV		0xF025
+#define	F367_OFDM_PPM_CPAMP_INVER		0xF02500FF
+
+/* FREESTFE_1 */
+#define	R367_OFDM_FREESTFE_1		0xF026
+#define	F367_OFDM_SYMBOL_NUMBER_INC		0xF02600C0
+#define	F367_OFDM_SEL_LSB		0xF0260004
+#define	F367_OFDM_AVERAGE_ON		0xF0260002
+#define	F367_OFDM_DC_ADJ		0xF0260001
+
+/* FREESTFE_2 */
+#define	R367_OFDM_FREESTFE_2		0xF027
+#define	F367_OFDM_SEL_SRCOUT		0xF02700C0
+#define	F367_OFDM_SEL_SYRTHR		0xF027001F
+
+/* DCOFFSET */
+#define	R367_OFDM_DCOFFSET		0xF028
+#define	F367_OFDM_SELECT_I_Q		0xF0280080
+#define	F367_OFDM_DC_OFFSET		0xF028007F
+
+/* EN_PROCESS */
+#define	R367_OFDM_EN_PROCESS		0xF029
+#define	F367_OFDM_FREE		0xF02900F0
+#define	F367_OFDM_ENAB_MANUAL		0xF0290001
+
+/* SDI_SMOOTHER */
+#define	R367_OFDM_SDI_SMOOTHER		0xF02A
+#define	F367_OFDM_DIS_SMOOTH		0xF02A0080
+#define	F367_OFDM_SDI_INC_SMOOTHER		0xF02A007F
+
+/* FE_LOOP_OPEN */
+#define	R367_OFDM_FE_LOOP_OPEN		0xF02B
+#define	F367_OFDM_TRL_LOOP_OP		0xF02B0002
+#define	F367_OFDM_CRL_LOOP_OP		0xF02B0001
+
+/* FREQOFF1 */
+#define	R367_OFDM_FREQOFF1		0xF02C
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI		0xF02C00FF
+
+/* FREQOFF2 */
+#define	R367_OFDM_FREQOFF2		0xF02D
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI		0xF02D00FF
+
+/* FREQOFF3 */
+#define	R367_OFDM_FREQOFF3		0xF02E
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO		0xF02E00FF
+
+/* TIMOFF1 */
+#define	R367_OFDM_TIMOFF1		0xF02F
+#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI		0xF02F00FF
+
+/* TIMOFF2 */
+#define	R367_OFDM_TIMOFF2		0xF030
+#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO		0xF03000FF
+
+/* EPQ */
+#define	R367_OFDM_EPQ		0xF031
+#define	F367_OFDM_EPQ1		0xF03100FF
+
+/* EPQAUTO */
+#define	R367_OFDM_EPQAUTO		0xF032
+#define	F367_OFDM_EPQ2		0xF03200FF
+
+/* SYR_UPDATE */
+#define	R367_OFDM_SYR_UPDATE		0xF033
+#define	F367_OFDM_SYR_PROTV		0xF0330080
+#define	F367_OFDM_SYR_PROTV_GAIN		0xF0330060
+#define	F367_OFDM_SYR_FILTER		0xF0330010
+#define	F367_OFDM_SYR_TRACK_THRES		0xF033000C
+
+/* CHPFREE */
+#define	R367_OFDM_CHPFREE		0xF034
+#define	F367_OFDM_CHP_FREE		0xF03400FF
+
+/* PPM_STATE_MAC */
+#define	R367_OFDM_PPM_STATE_MAC		0xF035
+#define	F367_OFDM_PPM_STATE_MACHINE_DECODER		0xF035003F
+
+/* INR_THRESHOLD */
+#define	R367_OFDM_INR_THRESHOLD		0xF036
+#define	F367_OFDM_INR_THRESH		0xF03600FF
+
+/* EPQ_TPS_ID_CELL */
+#define	R367_OFDM_EPQ_TPS_ID_CELL		0xF037
+#define	F367_OFDM_ENABLE_LGTH_TO_CF		0xF0370080
+#define	F367_OFDM_DIS_TPS_RSVD		0xF0370040
+#define	F367_OFDM_DIS_BCH		0xF0370020
+#define	F367_OFDM_DIS_ID_CEL		0xF0370010
+#define	F367_OFDM_TPS_ADJUST_SYM		0xF037000F
+
+/* EPQ_CFG */
+#define	R367_OFDM_EPQ_CFG		0xF038
+#define	F367_OFDM_EPQ_RANGE		0xF0380002
+#define	F367_OFDM_EPQ_SOFT		0xF0380001
+
+/* EPQ_STATUS */
+#define	R367_OFDM_EPQ_STATUS		0xF039
+#define	F367_OFDM_SLOPE_INC		0xF03900FC
+#define	F367_OFDM_TPS_FIELD		0xF0390003
+
+/* AUTORELOCK */
+#define	R367_OFDM_AUTORELOCK		0xF03A
+#define	F367_OFDM_BYPASS_BER_TEMPO		0xF03A0080
+#define	F367_OFDM_BER_TEMPO		0xF03A0070
+#define	F367_OFDM_BYPASS_COFDM_TEMPO		0xF03A0008
+#define	F367_OFDM_COFDM_TEMPO		0xF03A0007
+
+/* BER_THR_VMSB */
+#define	R367_OFDM_BER_THR_VMSB		0xF03B
+#define	F367_OFDM_BER_THRESHOLD_HI		0xF03B00FF
+
+/* BER_THR_MSB */
+#define	R367_OFDM_BER_THR_MSB		0xF03C
+#define	F367_OFDM_BER_THRESHOLD_MID		0xF03C00FF
+
+/* BER_THR_LSB */
+#define	R367_OFDM_BER_THR_LSB		0xF03D
+#define	F367_OFDM_BER_THRESHOLD_LO		0xF03D00FF
+
+/* CCD */
+#define	R367_OFDM_CCD		0xF03E
+#define	F367_OFDM_CCD_DETECTED		0xF03E0080
+#define	F367_OFDM_CCD_RESET		0xF03E0040
+#define	F367_OFDM_CCD_THRESHOLD		0xF03E000F
+
+/* SPECTR_CFG */
+#define	R367_OFDM_SPECTR_CFG		0xF03F
+#define	F367_OFDM_SPECT_CFG		0xF03F0003
+
+/* CONSTMU_MSB */
+#define	R367_OFDM_CONSTMU_MSB		0xF040
+#define	F367_OFDM_CONSTMU_FREEZE		0xF0400080
+#define	F367_OFDM_CONSTNU_FORCE_EN		0xF0400040
+#define	F367_OFDM_CONST_MU_MSB		0xF040003F
+
+/* CONSTMU_LSB */
+#define	R367_OFDM_CONSTMU_LSB		0xF041
+#define	F367_OFDM_CONST_MU_LSB		0xF04100FF
+
+/* CONSTMU_MAX_MSB */
+#define	R367_OFDM_CONSTMU_MAX_MSB		0xF042
+#define	F367_OFDM_CONST_MU_MAX_MSB		0xF042003F
+
+/* CONSTMU_MAX_LSB */
+#define	R367_OFDM_CONSTMU_MAX_LSB		0xF043
+#define	F367_OFDM_CONST_MU_MAX_LSB		0xF04300FF
+
+/* ALPHANOISE */
+#define	R367_OFDM_ALPHANOISE		0xF044
+#define	F367_OFDM_USE_ALLFILTER		0xF0440080
+#define	F367_OFDM_INTER_ON		0xF0440040
+#define	F367_OFDM_ALPHA_NOISE		0xF044001F
+
+/* MAXGP_MSB */
+#define	R367_OFDM_MAXGP_MSB		0xF045
+#define	F367_OFDM_MUFILTER_LENGTH		0xF04500F0
+#define	F367_OFDM_MAX_GP_MSB		0xF045000F
+
+/* MAXGP_LSB */
+#define	R367_OFDM_MAXGP_LSB		0xF046
+#define	F367_OFDM_MAX_GP_LSB		0xF04600FF
+
+/* ALPHAMSB */
+#define	R367_OFDM_ALPHAMSB		0xF047
+#define	F367_OFDM_CHC_DATARATE		0xF04700C0
+#define	F367_OFDM_ALPHA_MSB		0xF047003F
+
+/* ALPHALSB */
+#define	R367_OFDM_ALPHALSB		0xF048
+#define	F367_OFDM_ALPHA_LSB		0xF04800FF
+
+/* PILOT_ACCU */
+#define	R367_OFDM_PILOT_ACCU		0xF049
+#define	F367_OFDM_USE_SCAT4ADDAPT		0xF0490080
+#define	F367_OFDM_PILOT_ACC		0xF049001F
+
+/* PILOTMU_ACCU */
+#define	R367_OFDM_PILOTMU_ACCU		0xF04A
+#define	F367_OFDM_DISCARD_BAD_SP		0xF04A0080
+#define	F367_OFDM_DISCARD_BAD_CP		0xF04A0040
+#define	F367_OFDM_PILOT_MU_ACCU		0xF04A001F
+
+/* FILT_CHANNEL_EST */
+#define	R367_OFDM_FILT_CHANNEL_EST		0xF04B
+#define	F367_OFDM_USE_FILT_PILOT		0xF04B0080
+#define	F367_OFDM_FILT_CHANNEL		0xF04B007F
+
+/* ALPHA_NOPISE_FREQ */
+#define	R367_OFDM_ALPHA_NOPISE_FREQ		0xF04C
+#define	F367_OFDM_NOISE_FREQ_FILT		0xF04C0040
+#define	F367_OFDM_ALPHA_NOISE_FREQ		0xF04C003F
+
+/* RATIO_PILOT */
+#define	R367_OFDM_RATIO_PILOT		0xF04D
+#define	F367_OFDM_RATIO_MEAN_SP		0xF04D00F0
+#define	F367_OFDM_RATIO_MEAN_CP		0xF04D000F
+
+/* CHC_CTL */
+#define	R367_OFDM_CHC_CTL		0xF04E
+#define	F367_OFDM_TRACK_EN		0xF04E0080
+#define	F367_OFDM_NOISE_NORM_EN		0xF04E0040
+#define	F367_OFDM_FORCE_CHC_RESET		0xF04E0020
+#define	F367_OFDM_SHORT_TIME		0xF04E0010
+#define	F367_OFDM_FORCE_STATE_EN		0xF04E0008
+#define	F367_OFDM_FORCE_STATE		0xF04E0007
+
+/* EPQ_ADJUST */
+#define	R367_OFDM_EPQ_ADJUST		0xF04F
+#define	F367_OFDM_ADJUST_SCAT_IND		0xF04F00C0
+#define	F367_OFDM_ONE_SYMBOL		0xF04F0010
+#define	F367_OFDM_EPQ_DECAY		0xF04F000E
+#define	F367_OFDM_HOLD_SLOPE		0xF04F0001
+
+/* EPQ_THRES */
+#define	R367_OFDM_EPQ_THRES		0xF050
+#define	F367_OFDM_EPQ_THR		0xF05000FF
+
+/* OMEGA_CTL */
+#define	R367_OFDM_OMEGA_CTL		0xF051
+#define	F367_OFDM_OMEGA_RST		0xF0510080
+#define	F367_OFDM_FREEZE_OMEGA		0xF0510040
+#define	F367_OFDM_OMEGA_SEL		0xF051003F
+
+/* GP_CTL */
+#define	R367_OFDM_GP_CTL		0xF052
+#define	F367_OFDM_CHC_STATE		0xF05200E0
+#define	F367_OFDM_FREEZE_GP		0xF0520010
+#define	F367_OFDM_GP_SEL		0xF052000F
+
+/* MUMSB */
+#define	R367_OFDM_MUMSB		0xF053
+#define	F367_OFDM_MU_MSB		0xF053007F
+
+/* MULSB */
+#define	R367_OFDM_MULSB		0xF054
+#define	F367_OFDM_MU_LSB		0xF05400FF
+
+/* GPMSB */
+#define	R367_OFDM_GPMSB		0xF055
+#define	F367_OFDM_CSI_THRESHOLD		0xF05500E0
+#define	F367_OFDM_GP_MSB		0xF055000F
+
+/* GPLSB */
+#define	R367_OFDM_GPLSB		0xF056
+#define	F367_OFDM_GP_LSB		0xF05600FF
+
+/* OMEGAMSB */
+#define	R367_OFDM_OMEGAMSB		0xF057
+#define	F367_OFDM_OMEGA_MSB		0xF057007F
+
+/* OMEGALSB */
+#define	R367_OFDM_OMEGALSB		0xF058
+#define	F367_OFDM_OMEGA_LSB		0xF05800FF
+
+/* SCAT_NB */
+#define	R367_OFDM_SCAT_NB		0xF059
+#define	F367_OFDM_CHC_TEST		0xF05900F8
+#define	F367_OFDM_SCAT_NUMB		0xF0590003
+
+/* CHC_DUMMY */
+#define	R367_OFDM_CHC_DUMMY		0xF05A
+#define	F367_OFDM_CHC_DUM		0xF05A00FF
+
+/* INC_CTL */
+#define	R367_OFDM_INC_CTL		0xF05B
+#define	F367_OFDM_INC_BYPASS		0xF05B0080
+#define	F367_OFDM_INC_NDEPTH		0xF05B000C
+#define	F367_OFDM_INC_MADEPTH		0xF05B0003
+
+/* INCTHRES_COR1 */
+#define	R367_OFDM_INCTHRES_COR1		0xF05C
+#define	F367_OFDM_INC_THRES_COR1		0xF05C00FF
+
+/* INCTHRES_COR2 */
+#define	R367_OFDM_INCTHRES_COR2		0xF05D
+#define	F367_OFDM_INC_THRES_COR2		0xF05D00FF
+
+/* INCTHRES_DET1 */
+#define	R367_OFDM_INCTHRES_DET1		0xF05E
+#define	F367_OFDM_INC_THRES_DET1		0xF05E003F
+
+/* INCTHRES_DET2 */
+#define	R367_OFDM_INCTHRES_DET2		0xF05F
+#define	F367_OFDM_INC_THRES_DET2		0xF05F003F
+
+/* IIR_CELLNB */
+#define	R367_OFDM_IIR_CELLNB		0xF060
+#define	F367_OFDM_NRST_IIR		0xF0600080
+#define	F367_OFDM_IIR_CELL_NB		0xF0600007
+
+/* IIRCX_COEFF1_MSB */
+#define	R367_OFDM_IIRCX_COEFF1_MSB		0xF061
+#define	F367_OFDM_IIR_CX_COEFF1_MSB		0xF06100FF
+
+/* IIRCX_COEFF1_LSB */
+#define	R367_OFDM_IIRCX_COEFF1_LSB		0xF062
+#define	F367_OFDM_IIR_CX_COEFF1_LSB		0xF06200FF
+
+/* IIRCX_COEFF2_MSB */
+#define	R367_OFDM_IIRCX_COEFF2_MSB		0xF063
+#define	F367_OFDM_IIR_CX_COEFF2_MSB		0xF06300FF
+
+/* IIRCX_COEFF2_LSB */
+#define	R367_OFDM_IIRCX_COEFF2_LSB		0xF064
+#define	F367_OFDM_IIR_CX_COEFF2_LSB		0xF06400FF
+
+/* IIRCX_COEFF3_MSB */
+#define	R367_OFDM_IIRCX_COEFF3_MSB		0xF065
+#define	F367_OFDM_IIR_CX_COEFF3_MSB		0xF06500FF
+
+/* IIRCX_COEFF3_LSB */
+#define	R367_OFDM_IIRCX_COEFF3_LSB		0xF066
+#define	F367_OFDM_IIR_CX_COEFF3_LSB		0xF06600FF
+
+/* IIRCX_COEFF4_MSB */
+#define	R367_OFDM_IIRCX_COEFF4_MSB		0xF067
+#define	F367_OFDM_IIR_CX_COEFF4_MSB		0xF06700FF
+
+/* IIRCX_COEFF4_LSB */
+#define	R367_OFDM_IIRCX_COEFF4_LSB		0xF068
+#define	F367_OFDM_IIR_CX_COEFF4_LSB		0xF06800FF
+
+/* IIRCX_COEFF5_MSB */
+#define	R367_OFDM_IIRCX_COEFF5_MSB		0xF069
+#define	F367_OFDM_IIR_CX_COEFF5_MSB		0xF06900FF
+
+/* IIRCX_COEFF5_LSB */
+#define	R367_OFDM_IIRCX_COEFF5_LSB		0xF06A
+#define	F367_OFDM_IIR_CX_COEFF5_LSB		0xF06A00FF
+
+/* FEPATH_CFG */
+#define	R367_OFDM_FEPATH_CFG		0xF06B
+#define	F367_OFDM_DEMUX_SWAP		0xF06B0004
+#define	F367_OFDM_DIGAGC_SWAP		0xF06B0002
+#define	F367_OFDM_LONGPATH_IF		0xF06B0001
+
+/* PMC1_FUNC */
+#define	R367_OFDM_PMC1_FUNC		0xF06C
+#define	F367_OFDM_SOFT_RSTN		0xF06C0080
+#define	F367_OFDM_PMC1_AVERAGE_TIME		0xF06C0078
+#define	F367_OFDM_PMC1_WAIT_TIME		0xF06C0006
+#define	F367_OFDM_PMC1_2N_SEL		0xF06C0001
+
+/* PMC1_FOR */
+#define	R367_OFDM_PMC1_FOR		0xF06D
+#define	F367_OFDM_PMC1_FORCE		0xF06D0080
+#define	F367_OFDM_PMC1_FORCE_VALUE		0xF06D007C
+
+/* PMC2_FUNC */
+#define	R367_OFDM_PMC2_FUNC		0xF06E
+#define	F367_OFDM_PMC2_SOFT_STN		0xF06E0080
+#define	F367_OFDM_PMC2_ACCU_TIME		0xF06E0070
+#define	F367_OFDM_PMC2_CMDP_MN		0xF06E0008
+#define	F367_OFDM_PMC2_SWAP		0xF06E0004
+
+/* STATUS_ERR_DA */
+#define	R367_OFDM_STATUS_ERR_DA		0xF06F
+#define	F367_OFDM_COM_USEGAINTRK		0xF06F0080
+#define	F367_OFDM_COM_AGCLOCK		0xF06F0040
+#define	F367_OFDM_AUT_AGCLOCK		0xF06F0020
+#define	F367_OFDM_MIN_ERR_X_LSB		0xF06F000F
+
+/* DIG_AGC_R */
+#define	R367_OFDM_DIG_AGC_R		0xF070
+#define	F367_OFDM_COM_SOFT_RSTN		0xF0700080
+#define	F367_OFDM_COM_AGC_ON		0xF0700040
+#define	F367_OFDM_COM_EARLY		0xF0700020
+#define	F367_OFDM_AUT_SOFT_RESETN		0xF0700010
+#define	F367_OFDM_AUT_AGC_ON		0xF0700008
+#define	F367_OFDM_AUT_EARLY		0xF0700004
+#define	F367_OFDM_AUT_ROT_EN		0xF0700002
+#define	F367_OFDM_LOCK_SOFT_RESETN		0xF0700001
+
+/* COMAGC_TARMSB */
+#define	R367_OFDM_COMAGC_TARMSB		0xF071
+#define	F367_OFDM_COM_AGC_TARGET_MSB		0xF07100FF
+
+/* COM_AGC_TAR_ENMODE */
+#define	R367_OFDM_COM_AGC_TAR_ENMODE		0xF072
+#define	F367_OFDM_COM_AGC_TARGET_LSB		0xF07200F0
+#define	F367_OFDM_COM_ENMODE		0xF072000F
+
+/* COM_AGC_CFG */
+#define	R367_OFDM_COM_AGC_CFG		0xF073
+#define	F367_OFDM_COM_N		0xF07300F8
+#define	F367_OFDM_COM_STABMODE		0xF0730006
+#define	F367_OFDM_ERR_SEL		0xF0730001
+
+/* COM_AGC_GAIN1 */
+#define	R367_OFDM_COM_AGC_GAIN1		0xF074
+#define	F367_OFDM_COM_GAIN1ACK		0xF07400F0
+#define	F367_OFDM_COM_GAIN1TRK		0xF074000F
+
+/* AUT_AGC_TARGETMSB */
+#define	R367_OFDM_AUT_AGC_TARGETMSB		0xF075
+#define	F367_OFDM_AUT_AGC_TARGET_MSB		0xF07500FF
+
+/* LOCK_DET_MSB */
+#define	R367_OFDM_LOCK_DET_MSB		0xF076
+#define	F367_OFDM_LOCK_DETECT_MSB		0xF07600FF
+
+/* AGCTAR_LOCK_LSBS */
+#define	R367_OFDM_AGCTAR_LOCK_LSBS		0xF077
+#define	F367_OFDM_AUT_AGC_TARGET_LSB		0xF07700F0
+#define	F367_OFDM_LOCK_DETECT_LSB		0xF077000F
+
+/* AUT_GAIN_EN */
+#define	R367_OFDM_AUT_GAIN_EN		0xF078
+#define	F367_OFDM_AUT_ENMODE		0xF07800F0
+#define	F367_OFDM_AUT_GAIN2		0xF078000F
+
+/* AUT_CFG */
+#define	R367_OFDM_AUT_CFG		0xF079
+#define	F367_OFDM_AUT_N		0xF07900F8
+#define	F367_OFDM_INT_CHOICE		0xF0790006
+#define	F367_OFDM_INT_LOAD		0xF0790001
+
+/* LOCKN */
+#define	R367_OFDM_LOCKN		0xF07A
+#define	F367_OFDM_LOCK_N		0xF07A00F8
+#define	F367_OFDM_SEL_IQNTAR		0xF07A0004
+#define	F367_OFDM_LOCK_DETECT_CHOICE		0xF07A0003
+
+/* INT_X_3 */
+#define	R367_OFDM_INT_X_3		0xF07B
+#define	F367_OFDM_INT_X3		0xF07B00FF
+
+/* INT_X_2 */
+#define	R367_OFDM_INT_X_2		0xF07C
+#define	F367_OFDM_INT_X2		0xF07C00FF
+
+/* INT_X_1 */
+#define	R367_OFDM_INT_X_1		0xF07D
+#define	F367_OFDM_INT_X1		0xF07D00FF
+
+/* INT_X_0 */
+#define	R367_OFDM_INT_X_0		0xF07E
+#define	F367_OFDM_INT_X0		0xF07E00FF
+
+/* MIN_ERRX_MSB */
+#define	R367_OFDM_MIN_ERRX_MSB		0xF07F
+#define	F367_OFDM_MIN_ERR_X_MSB		0xF07F00FF
+
+/* COR_CTL */
+#define	R367_OFDM_COR_CTL		0xF080
+#define	F367_OFDM_CORE_ACTIVE		0xF0800020
+#define	F367_OFDM_HOLD		0xF0800010
+#define	F367_OFDM_CORE_STATE_CTL		0xF080000F
+
+/* COR_STAT */
+#define	R367_OFDM_COR_STAT		0xF081
+#define	F367_OFDM_SCATT_LOCKED		0xF0810080
+#define	F367_OFDM_TPS_LOCKED		0xF0810040
+#define	F367_OFDM_SYR_LOCKED_COR		0xF0810020
+#define	F367_OFDM_AGC_LOCKED_STAT		0xF0810010
+#define	F367_OFDM_CORE_STATE_STAT		0xF081000F
+
+/* COR_INTEN */
+#define	R367_OFDM_COR_INTEN		0xF082
+#define	F367_OFDM_INTEN		0xF0820080
+#define	F367_OFDM_INTEN_SYR		0xF0820020
+#define	F367_OFDM_INTEN_FFT		0xF0820010
+#define	F367_OFDM_INTEN_AGC		0xF0820008
+#define	F367_OFDM_INTEN_TPS1		0xF0820004
+#define	F367_OFDM_INTEN_TPS2		0xF0820002
+#define	F367_OFDM_INTEN_TPS3		0xF0820001
+
+/* COR_INTSTAT */
+#define	R367_OFDM_COR_INTSTAT		0xF083
+#define	F367_OFDM_INTSTAT_SYR		0xF0830020
+#define	F367_OFDM_INTSTAT_FFT		0xF0830010
+#define	F367_OFDM_INTSAT_AGC		0xF0830008
+#define	F367_OFDM_INTSTAT_TPS1		0xF0830004
+#define	F367_OFDM_INTSTAT_TPS2		0xF0830002
+#define	F367_OFDM_INTSTAT_TPS3		0xF0830001
+
+/* COR_MODEGUARD */
+#define	R367_OFDM_COR_MODEGUARD		0xF084
+#define	F367_OFDM_FORCE		0xF0840010
+#define	F367_OFDM_MODE		0xF084000C
+#define	F367_OFDM_GUARD		0xF0840003
+
+/* AGC_CTL */
+#define	R367_OFDM_AGC_CTL		0xF085
+#define	F367_OFDM_AGC_TIMING_FACTOR		0xF08500E0
+#define	F367_OFDM_AGC_LAST		0xF0850010
+#define	F367_OFDM_AGC_GAIN		0xF085000C
+#define	F367_OFDM_AGC_NEG		0xF0850002
+#define	F367_OFDM_AGC_SET		0xF0850001
+
+/* AGC_MANUAL1 */
+#define	R367_OFDM_AGC_MANUAL1		0xF086
+#define	F367_OFDM_AGC_VAL_LO		0xF08600FF
+
+/* AGC_MANUAL2 */
+#define	R367_OFDM_AGC_MANUAL2		0xF087
+#define	F367_OFDM_AGC_VAL_HI		0xF087000F
+
+/* AGC_TARG */
+#define	R367_OFDM_AGC_TARG		0xF088
+#define	F367_OFDM_AGC_TARGET		0xF08800FF
+
+/* AGC_GAIN1 */
+#define	R367_OFDM_AGC_GAIN1		0xF089
+#define	F367_OFDM_AGC_GAIN_LO		0xF08900FF
+
+/* AGC_GAIN2 */
+#define	R367_OFDM_AGC_GAIN2		0xF08A
+#define	F367_OFDM_AGC_LOCKED_GAIN2		0xF08A0010
+#define	F367_OFDM_AGC_GAIN_HI		0xF08A000F
+
+/* RESERVED_1 */
+#define	R367_OFDM_RESERVED_1		0xF08B
+#define	F367_OFDM_RESERVED1		0xF08B00FF
+
+/* RESERVED_2 */
+#define	R367_OFDM_RESERVED_2		0xF08C
+#define	F367_OFDM_RESERVED2		0xF08C00FF
+
+/* RESERVED_3 */
+#define	R367_OFDM_RESERVED_3		0xF08D
+#define	F367_OFDM_RESERVED3		0xF08D00FF
+
+/* CAS_CTL */
+#define	R367_OFDM_CAS_CTL		0xF08E
+#define	F367_OFDM_CCS_ENABLE		0xF08E0080
+#define	F367_OFDM_ACS_DISABLE		0xF08E0040
+#define	F367_OFDM_DAGC_DIS		0xF08E0020
+#define	F367_OFDM_DAGC_GAIN		0xF08E0018
+#define	F367_OFDM_CCSMU		0xF08E0007
+
+/* CAS_FREQ */
+#define	R367_OFDM_CAS_FREQ		0xF08F
+#define	F367_OFDM_CCS_FREQ		0xF08F00FF
+
+/* CAS_DAGCGAIN */
+#define	R367_OFDM_CAS_DAGCGAIN		0xF090
+#define	F367_OFDM_CAS_DAGC_GAIN		0xF09000FF
+
+/* SYR_CTL */
+#define	R367_OFDM_SYR_CTL		0xF091
+#define	F367_OFDM_SICTH_ENABLE		0xF0910080
+#define	F367_OFDM_LONG_ECHO		0xF0910078
+#define	F367_OFDM_AUTO_LE_EN		0xF0910004
+#define	F367_OFDM_SYR_BYPASS		0xF0910002
+#define	F367_OFDM_SYR_TR_DIS		0xF0910001
+
+/* SYR_STAT */
+#define	R367_OFDM_SYR_STAT		0xF092
+#define	F367_OFDM_SYR_LOCKED_STAT		0xF0920010
+#define	F367_OFDM_SYR_MODE		0xF092000C
+#define	F367_OFDM_SYR_GUARD		0xF0920003
+
+/* SYR_NCO1 */
+#define	R367_OFDM_SYR_NCO1		0xF093
+#define	F367_OFDM_SYR_NCO_LO		0xF09300FF
+
+/* SYR_NCO2 */
+#define	R367_OFDM_SYR_NCO2		0xF094
+#define	F367_OFDM_SYR_NCO_HI		0xF094003F
+
+/* SYR_OFFSET1 */
+#define	R367_OFDM_SYR_OFFSET1		0xF095
+#define	F367_OFDM_SYR_OFFSET_LO		0xF09500FF
+
+/* SYR_OFFSET2 */
+#define	R367_OFDM_SYR_OFFSET2		0xF096
+#define	F367_OFDM_SYR_OFFSET_HI		0xF096003F
+
+/* FFT_CTL */
+#define	R367_OFDM_FFT_CTL		0xF097
+#define	F367_OFDM_SHIFT_FFT_TRIG		0xF0970018
+#define	F367_OFDM_FFT_TRIGGER		0xF0970004
+#define	F367_OFDM_FFT_MANUAL		0xF0970002
+#define	F367_OFDM_IFFT_MODE		0xF0970001
+
+/* SCR_CTL */
+#define	R367_OFDM_SCR_CTL		0xF098
+#define	F367_OFDM_SYRADJDECAY		0xF0980070
+#define	F367_OFDM_SCR_CPEDIS		0xF0980002
+#define	F367_OFDM_SCR_DIS		0xF0980001
+
+/* PPM_CTL1 */
+#define	R367_OFDM_PPM_CTL1		0xF099
+#define	F367_OFDM_PPM_MAXFREQ		0xF0990030
+#define	F367_OFDM_PPM_MAXTIM		0xF0990008
+#define	F367_OFDM_PPM_INVSEL		0xF0990004
+#define	F367_OFDM_PPM_SCATDIS		0xF0990002
+#define	F367_OFDM_PPM_BYP		0xF0990001
+
+/* TRL_CTL */
+#define	R367_OFDM_TRL_CTL		0xF09A
+#define	F367_OFDM_TRL_NOMRATE_LSB		0xF09A0080
+#define	F367_OFDM_TRL_GAIN_FACTOR		0xF09A0078
+#define	F367_OFDM_TRL_LOOPGAIN		0xF09A0007
+
+/* TRL_NOMRATE1 */
+#define	R367_OFDM_TRL_NOMRATE1		0xF09B
+#define	F367_OFDM_TRL_NOMRATE_LO		0xF09B00FF
+
+/* TRL_NOMRATE2 */
+#define	R367_OFDM_TRL_NOMRATE2		0xF09C
+#define	F367_OFDM_TRL_NOMRATE_HI		0xF09C00FF
+
+/* TRL_TIME1 */
+#define	R367_OFDM_TRL_TIME1		0xF09D
+#define	F367_OFDM_TRL_TOFFSET_LO		0xF09D00FF
+
+/* TRL_TIME2 */
+#define	R367_OFDM_TRL_TIME2		0xF09E
+#define	F367_OFDM_TRL_TOFFSET_HI		0xF09E00FF
+
+/* CRL_CTL */
+#define	R367_OFDM_CRL_CTL		0xF09F
+#define	F367_OFDM_CRL_DIS		0xF09F0080
+#define	F367_OFDM_CRL_GAIN_FACTOR		0xF09F0078
+#define	F367_OFDM_CRL_LOOPGAIN		0xF09F0007
+
+/* CRL_FREQ1 */
+#define	R367_OFDM_CRL_FREQ1		0xF0A0
+#define	F367_OFDM_CRL_FOFFSET_LO		0xF0A000FF
+
+/* CRL_FREQ2 */
+#define	R367_OFDM_CRL_FREQ2		0xF0A1
+#define	F367_OFDM_CRL_FOFFSET_HI		0xF0A100FF
+
+/* CRL_FREQ3 */
+#define	R367_OFDM_CRL_FREQ3		0xF0A2
+#define	F367_OFDM_CRL_FOFFSET_VHI		0xF0A200FF
+
+/* TPS_SFRAME_CTL */
+#define	R367_OFDM_TPS_SFRAME_CTL		0xF0A3
+#define	F367_OFDM_TPS_SFRAME_SYNC		0xF0A30001
+
+/* CHC_SNR */
+#define	R367_OFDM_CHC_SNR		0xF0A4
+#define	F367_OFDM_CHCSNR		0xF0A400FF
+
+/* BDI_CTL */
+#define	R367_OFDM_BDI_CTL		0xF0A5
+#define	F367_OFDM_BDI_LPSEL		0xF0A50002
+#define	F367_OFDM_BDI_SERIAL		0xF0A50001
+
+/* DMP_CTL */
+#define	R367_OFDM_DMP_CTL		0xF0A6
+#define	F367_OFDM_DMP_SCALING_FACTOR		0xF0A6001E
+#define	F367_OFDM_DMP_SDDIS		0xF0A60001
+
+/* TPS_RCVD1 */
+#define	R367_OFDM_TPS_RCVD1		0xF0A7
+#define	F367_OFDM_TPS_CHANGE		0xF0A70040
+#define	F367_OFDM_BCH_OK		0xF0A70020
+#define	F367_OFDM_TPS_SYNC		0xF0A70010
+#define	F367_OFDM_TPS_FRAME		0xF0A70003
+
+/* TPS_RCVD2 */
+#define	R367_OFDM_TPS_RCVD2		0xF0A8
+#define	F367_OFDM_TPS_HIERMODE		0xF0A80070
+#define	F367_OFDM_TPS_CONST		0xF0A80003
+
+/* TPS_RCVD3 */
+#define	R367_OFDM_TPS_RCVD3		0xF0A9
+#define	F367_OFDM_TPS_LPCODE		0xF0A90070
+#define	F367_OFDM_TPS_HPCODE		0xF0A90007
+
+/* TPS_RCVD4 */
+#define	R367_OFDM_TPS_RCVD4		0xF0AA
+#define	F367_OFDM_TPS_GUARD		0xF0AA0030
+#define	F367_OFDM_TPS_MODE		0xF0AA0003
+
+/* TPS_ID_CELL1 */
+#define	R367_OFDM_TPS_ID_CELL1		0xF0AB
+#define	F367_OFDM_TPS_ID_CELL_LO		0xF0AB00FF
+
+/* TPS_ID_CELL2 */
+#define	R367_OFDM_TPS_ID_CELL2		0xF0AC
+#define	F367_OFDM_TPS_ID_CELL_HI		0xF0AC00FF
+
+/* TPS_RCVD5_SET1 */
+#define	R367_OFDM_TPS_RCVD5_SET1		0xF0AD
+#define	F367_OFDM_TPS_NA		0xF0AD00FC
+#define	F367_OFDM_TPS_SETFRAME		0xF0AD0003
+
+/* TPS_SET2 */
+#define	R367_OFDM_TPS_SET2		0xF0AE
+#define	F367_OFDM_TPS_SETHIERMODE		0xF0AE0070
+#define	F367_OFDM_TPS_SETCONST		0xF0AE0003
+
+/* TPS_SET3 */
+#define	R367_OFDM_TPS_SET3		0xF0AF
+#define	F367_OFDM_TPS_SETLPCODE		0xF0AF0070
+#define	F367_OFDM_TPS_SETHPCODE		0xF0AF0007
+
+/* TPS_CTL */
+#define	R367_OFDM_TPS_CTL		0xF0B0
+#define	F367_OFDM_TPS_IMM		0xF0B00004
+#define	F367_OFDM_TPS_BCHDIS		0xF0B00002
+#define	F367_OFDM_TPS_UPDDIS		0xF0B00001
+
+/* CTL_FFTOSNUM */
+#define	R367_OFDM_CTL_FFTOSNUM		0xF0B1
+#define	F367_OFDM_SYMBOL_NUMBER		0xF0B1007F
+
+/* TESTSELECT */
+#define	R367_OFDM_TESTSELECT		0xF0B2
+#define	F367_OFDM_TEST_SELECT		0xF0B2001F
+
+/* MSC_REV */
+#define	R367_OFDM_MSC_REV		0xF0B3
+#define	F367_OFDM_REV_NUMBER		0xF0B300FF
+
+/* PIR_CTL */
+#define	R367_OFDM_PIR_CTL		0xF0B4
+#define	F367_OFDM_FREEZE		0xF0B40001
+
+/* SNR_CARRIER1 */
+#define	R367_OFDM_SNR_CARRIER1		0xF0B5
+#define	F367_OFDM_SNR_CARRIER_LO		0xF0B500FF
+
+/* SNR_CARRIER2 */
+#define	R367_OFDM_SNR_CARRIER2		0xF0B6
+#define	F367_OFDM_MEAN		0xF0B600C0
+#define	F367_OFDM_SNR_CARRIER_HI		0xF0B6001F
+
+/* PPM_CPAMP */
+#define	R367_OFDM_PPM_CPAMP		0xF0B7
+#define	F367_OFDM_PPM_CPC		0xF0B700FF
+
+/* TSM_AP0 */
+#define	R367_OFDM_TSM_AP0		0xF0B8
+#define	F367_OFDM_ADDRESS_BYTE_0		0xF0B800FF
+
+/* TSM_AP1 */
+#define	R367_OFDM_TSM_AP1		0xF0B9
+#define	F367_OFDM_ADDRESS_BYTE_1		0xF0B900FF
+
+/* TSM_AP2 */
+#define	R367_OFDM_TSM_AP2		0xF0BA
+#define	F367_OFDM_DATA_BYTE_0		0xF0BA00FF
+
+/* TSM_AP3 */
+#define	R367_OFDM_TSM_AP3		0xF0BB
+#define	F367_OFDM_DATA_BYTE_1		0xF0BB00FF
+
+/* TSM_AP4 */
+#define	R367_OFDM_TSM_AP4		0xF0BC
+#define	F367_OFDM_DATA_BYTE_2		0xF0BC00FF
+
+/* TSM_AP5 */
+#define	R367_OFDM_TSM_AP5		0xF0BD
+#define	F367_OFDM_DATA_BYTE_3		0xF0BD00FF
+
+/* TSM_AP6 */
+#define	R367_OFDM_TSM_AP6		0xF0BE
+#define	F367_OFDM_TSM_AP_6		0xF0BE00FF
+
+/* TSM_AP7 */
+#define	R367_OFDM_TSM_AP7		0xF0BF
+#define	F367_OFDM_MEM_SELECT_BYTE		0xF0BF00FF
+
+/* TSTRES */
+#define	R367_TSTRES		0xF0C0
+#define	F367_FRES_DISPLAY		0xF0C00080
+#define	F367_FRES_FIFO_AD		0xF0C00020
+#define	F367_FRESRS		0xF0C00010
+#define	F367_FRESACS		0xF0C00008
+#define	F367_FRESFEC		0xF0C00004
+#define	F367_FRES_PRIF		0xF0C00002
+#define	F367_FRESCORE		0xF0C00001
+
+/* ANACTRL */
+#define	R367_ANACTRL		0xF0C1
+#define	F367_BYPASS_XTAL		0xF0C10040
+#define	F367_BYPASS_PLLXN		0xF0C1000C
+#define	F367_DIS_PAD_OSC		0xF0C10002
+#define	F367_STDBY_PLLXN		0xF0C10001
+
+/* TSTBUS */
+#define	R367_TSTBUS		0xF0C2
+#define	F367_TS_BYTE_CLK_INV		0xF0C20080
+#define	F367_CFG_IP		0xF0C20070
+#define	F367_CFG_TST		0xF0C2000F
+
+/* TSTRATE */
+#define	R367_TSTRATE		0xF0C6
+#define	F367_FORCEPHA		0xF0C60080
+#define	F367_FNEWPHA		0xF0C60010
+#define	F367_FROT90		0xF0C60008
+#define	F367_FR		0xF0C60007
+
+/* CONSTMODE */
+#define	R367_OFDM_CONSTMODE		0xF0CB
+#define	F367_OFDM_TST_PRIF		0xF0CB00E0
+#define	F367_OFDM_CAR_TYPE		0xF0CB0018
+#define	F367_OFDM_CONST_MODE		0xF0CB0003
+
+/* CONSTCARR1 */
+#define	R367_OFDM_CONSTCARR1		0xF0CC
+#define	F367_OFDM_CONST_CARR_LO		0xF0CC00FF
+
+/* CONSTCARR2 */
+#define	R367_OFDM_CONSTCARR2		0xF0CD
+#define	F367_OFDM_CONST_CARR_HI		0xF0CD001F
+
+/* ICONSTEL */
+#define	R367_OFDM_ICONSTEL		0xF0CE
+#define	F367_OFDM_PICONSTEL		0xF0CE00FF
+
+/* QCONSTEL */
+#define	R367_OFDM_QCONSTEL		0xF0CF
+#define	F367_OFDM_PQCONSTEL		0xF0CF00FF
+
+/* TSTBISTRES0 */
+#define	R367_OFDM_TSTBISTRES0		0xF0D0
+#define	F367_OFDM_BEND_PPM		0xF0D00080
+#define	F367_OFDM_BBAD_PPM		0xF0D00040
+#define	F367_OFDM_BEND_FFTW		0xF0D00020
+#define	F367_OFDM_BBAD_FFTW		0xF0D00010
+#define	F367_OFDM_BEND_FFT_BUF		0xF0D00008
+#define	F367_OFDM_BBAD_FFT_BUF		0xF0D00004
+#define	F367_OFDM_BEND_SYR		0xF0D00002
+#define	F367_OFDM_BBAD_SYR		0xF0D00001
+
+/* TSTBISTRES1 */
+#define	R367_OFDM_TSTBISTRES1		0xF0D1
+#define	F367_OFDM_BEND_CHC_CP		0xF0D10080
+#define	F367_OFDM_BBAD_CHC_CP		0xF0D10040
+#define	F367_OFDM_BEND_CHCI		0xF0D10020
+#define	F367_OFDM_BBAD_CHCI		0xF0D10010
+#define	F367_OFDM_BEND_BDI		0xF0D10008
+#define	F367_OFDM_BBAD_BDI		0xF0D10004
+#define	F367_OFDM_BEND_SDI		0xF0D10002
+#define	F367_OFDM_BBAD_SDI		0xF0D10001
+
+/* TSTBISTRES2 */
+#define	R367_OFDM_TSTBISTRES2		0xF0D2
+#define	F367_OFDM_BEND_CHC_INC		0xF0D20080
+#define	F367_OFDM_BBAD_CHC_INC		0xF0D20040
+#define	F367_OFDM_BEND_CHC_SPP		0xF0D20020
+#define	F367_OFDM_BBAD_CHC_SPP		0xF0D20010
+#define	F367_OFDM_BEND_CHC_CPP		0xF0D20008
+#define	F367_OFDM_BBAD_CHC_CPP		0xF0D20004
+#define	F367_OFDM_BEND_CHC_SP		0xF0D20002
+#define	F367_OFDM_BBAD_CHC_SP		0xF0D20001
+
+/* TSTBISTRES3 */
+#define	R367_OFDM_TSTBISTRES3		0xF0D3
+#define	F367_OFDM_BEND_QAM		0xF0D30080
+#define	F367_OFDM_BBAD_QAM		0xF0D30040
+#define	F367_OFDM_BEND_SFEC_VIT		0xF0D30020
+#define	F367_OFDM_BBAD_SFEC_VIT		0xF0D30010
+#define	F367_OFDM_BEND_SFEC_DLINE		0xF0D30008
+#define	F367_OFDM_BBAD_SFEC_DLINE		0xF0D30004
+#define	F367_OFDM_BEND_SFEC_HW		0xF0D30002
+#define	F367_OFDM_BBAD_SFEC_HW		0xF0D30001
+
+/* RF_AGC1 */
+#define	R367_RF_AGC1		0xF0D4
+#define	F367_RF_AGC1_LEVEL_HI		0xF0D400FF
+
+/* RF_AGC2 */
+#define	R367_RF_AGC2		0xF0D5
+#define	F367_REF_ADGP		0xF0D50080
+#define	F367_STDBY_ADCGP		0xF0D50020
+#define	F367_CHANNEL_SEL		0xF0D5001C
+#define	F367_RF_AGC1_LEVEL_LO		0xF0D50003
+
+/* ANADIGCTRL */
+#define	R367_ANADIGCTRL		0xF0D7
+#define	F367_SEL_CLKDEM		0xF0D70020
+#define	F367_EN_BUFFER_Q		0xF0D70010
+#define	F367_EN_BUFFER_I		0xF0D70008
+#define	F367_ADC_RIS_EGDE		0xF0D70004
+#define	F367_SGN_ADC		0xF0D70002
+#define	F367_SEL_AD12_SYNC		0xF0D70001
+
+/* PLLMDIV */
+#define	R367_PLLMDIV		0xF0D8
+#define	F367_PLL_MDIV		0xF0D800FF
+
+/* PLLNDIV */
+#define	R367_PLLNDIV		0xF0D9
+#define	F367_PLL_NDIV		0xF0D900FF
+
+/* PLLSETUP */
+#define	R367_PLLSETUP		0xF0DA
+#define	F367_PLL_PDIV		0xF0DA0070
+#define	F367_PLL_KDIV		0xF0DA000F
+
+/* DUAL_AD12 */
+#define	R367_DUAL_AD12		0xF0DB
+#define	F367_FS20M		0xF0DB0020
+#define	F367_FS50M		0xF0DB0010
+#define	F367_INMODE0		0xF0DB0008
+#define	F367_POFFQ		0xF0DB0004
+#define	F367_POFFI		0xF0DB0002
+#define	F367_INMODE1		0xF0DB0001
+
+/* TSTBIST */
+#define	R367_TSTBIST		0xF0DC
+#define	F367_TST_BYP_CLK		0xF0DC0080
+#define	F367_TST_GCLKENA_STD		0xF0DC0040
+#define	F367_TST_GCLKENA		0xF0DC0020
+#define	F367_TST_MEMBIST		0xF0DC001F
+
+/* PAD_COMP_CTRL */
+#define	R367_PAD_COMP_CTRL		0xF0DD
+#define	F367_COMPTQ		0xF0DD0010
+#define	F367_COMPEN		0xF0DD0008
+#define	F367_FREEZE2		0xF0DD0004
+#define	F367_SLEEP_INHBT		0xF0DD0002
+#define	F367_CHIP_SLEEP		0xF0DD0001
+
+/* PAD_COMP_WR */
+#define	R367_PAD_COMP_WR		0xF0DE
+#define	F367_WR_ASRC		0xF0DE007F
+
+/* PAD_COMP_RD */
+#define	R367_PAD_COMP_RD		0xF0DF
+#define	F367_COMPOK		0xF0DF0080
+#define	F367_RD_ASRC		0xF0DF007F
+
+/* SYR_TARGET_FFTADJT_MSB */
+#define	R367_OFDM_SYR_TARGET_FFTADJT_MSB		0xF100
+#define	F367_OFDM_SYR_START		0xF1000080
+#define	F367_OFDM_SYR_TARGET_FFTADJ_HI		0xF100000F
+
+/* SYR_TARGET_FFTADJT_LSB */
+#define	R367_OFDM_SYR_TARGET_FFTADJT_LSB		0xF101
+#define	F367_OFDM_SYR_TARGET_FFTADJ_LO		0xF10100FF
+
+/* SYR_TARGET_CHCADJT_MSB */
+#define	R367_OFDM_SYR_TARGET_CHCADJT_MSB		0xF102
+#define	F367_OFDM_SYR_TARGET_CHCADJ_HI		0xF102000F
+
+/* SYR_TARGET_CHCADJT_LSB */
+#define	R367_OFDM_SYR_TARGET_CHCADJT_LSB		0xF103
+#define	F367_OFDM_SYR_TARGET_CHCADJ_LO		0xF10300FF
+
+/* SYR_FLAG */
+#define	R367_OFDM_SYR_FLAG		0xF104
+#define	F367_OFDM_TRIG_FLG1		0xF1040080
+#define	F367_OFDM_TRIG_FLG0		0xF1040040
+#define	F367_OFDM_FFT_FLG1		0xF1040008
+#define	F367_OFDM_FFT_FLG0		0xF1040004
+#define	F367_OFDM_CHC_FLG1		0xF1040002
+#define	F367_OFDM_CHC_FLG0		0xF1040001
+
+/* CRL_TARGET1 */
+#define	R367_OFDM_CRL_TARGET1		0xF105
+#define	F367_OFDM_CRL_START		0xF1050080
+#define	F367_OFDM_CRL_TARGET_VHI		0xF105000F
+
+/* CRL_TARGET2 */
+#define	R367_OFDM_CRL_TARGET2		0xF106
+#define	F367_OFDM_CRL_TARGET_HI		0xF10600FF
+
+/* CRL_TARGET3 */
+#define	R367_OFDM_CRL_TARGET3		0xF107
+#define	F367_OFDM_CRL_TARGET_LO		0xF10700FF
+
+/* CRL_TARGET4 */
+#define	R367_OFDM_CRL_TARGET4		0xF108
+#define	F367_OFDM_CRL_TARGET_VLO		0xF10800FF
+
+/* CRL_FLAG */
+#define	R367_OFDM_CRL_FLAG		0xF109
+#define	F367_OFDM_CRL_FLAG1		0xF1090002
+#define	F367_OFDM_CRL_FLAG0		0xF1090001
+
+/* TRL_TARGET1 */
+#define	R367_OFDM_TRL_TARGET1		0xF10A
+#define	F367_OFDM_TRL_TARGET_HI		0xF10A00FF
+
+/* TRL_TARGET2 */
+#define	R367_OFDM_TRL_TARGET2		0xF10B
+#define	F367_OFDM_TRL_TARGET_LO		0xF10B00FF
+
+/* TRL_CHC */
+#define	R367_OFDM_TRL_CHC		0xF10C
+#define	F367_OFDM_TRL_START		0xF10C0080
+#define	F367_OFDM_CHC_START		0xF10C0040
+#define	F367_OFDM_TRL_FLAG1		0xF10C0002
+#define	F367_OFDM_TRL_FLAG0		0xF10C0001
+
+/* CHC_SNR_TARG */
+#define	R367_OFDM_CHC_SNR_TARG		0xF10D
+#define	F367_OFDM_CHC_SNR_TARGET		0xF10D00FF
+
+/* TOP_TRACK */
+#define	R367_OFDM_TOP_TRACK		0xF10E
+#define	F367_OFDM_TOP_START		0xF10E0080
+#define	F367_OFDM_FIRST_FLAG		0xF10E0070
+#define	F367_OFDM_TOP_FLAG1		0xF10E0008
+#define	F367_OFDM_TOP_FLAG0		0xF10E0004
+#define	F367_OFDM_CHC_FLAG1		0xF10E0002
+#define	F367_OFDM_CHC_FLAG0		0xF10E0001
+
+/* TRACKER_FREE1 */
+#define	R367_OFDM_TRACKER_FREE1		0xF10F
+#define	F367_OFDM_TRACKER_FREE_1		0xF10F00FF
+
+/* ERROR_CRL1 */
+#define	R367_OFDM_ERROR_CRL1		0xF110
+#define	F367_OFDM_ERROR_CRL_VHI		0xF11000FF
+
+/* ERROR_CRL2 */
+#define	R367_OFDM_ERROR_CRL2		0xF111
+#define	F367_OFDM_ERROR_CRL_HI		0xF11100FF
+
+/* ERROR_CRL3 */
+#define	R367_OFDM_ERROR_CRL3		0xF112
+#define	F367_OFDM_ERROR_CRL_LOI		0xF11200FF
+
+/* ERROR_CRL4 */
+#define	R367_OFDM_ERROR_CRL4		0xF113
+#define	F367_OFDM_ERROR_CRL_VLO		0xF11300FF
+
+/* DEC_NCO1 */
+#define	R367_OFDM_DEC_NCO1		0xF114
+#define	F367_OFDM_DEC_NCO_VHI		0xF11400FF
+
+/* DEC_NCO2 */
+#define	R367_OFDM_DEC_NCO2		0xF115
+#define	F367_OFDM_DEC_NCO_HI		0xF11500FF
+
+/* DEC_NCO3 */
+#define	R367_OFDM_DEC_NCO3		0xF116
+#define	F367_OFDM_DEC_NCO_LO		0xF11600FF
+
+/* SNR */
+#define	R367_OFDM_SNR		0xF117
+#define	F367_OFDM_SNRATIO		0xF11700FF
+
+/* SYR_FFTADJ1 */
+#define	R367_OFDM_SYR_FFTADJ1		0xF118
+#define	F367_OFDM_SYR_FFTADJ_HI		0xF11800FF
+
+/* SYR_FFTADJ2 */
+#define	R367_OFDM_SYR_FFTADJ2		0xF119
+#define	F367_OFDM_SYR_FFTADJ_LO		0xF11900FF
+
+/* SYR_CHCADJ1 */
+#define	R367_OFDM_SYR_CHCADJ1		0xF11A
+#define	F367_OFDM_SYR_CHCADJ_HI		0xF11A00FF
+
+/* SYR_CHCADJ2 */
+#define	R367_OFDM_SYR_CHCADJ2		0xF11B
+#define	F367_OFDM_SYR_CHCADJ_LO		0xF11B00FF
+
+/* SYR_OFF */
+#define	R367_OFDM_SYR_OFF		0xF11C
+#define	F367_OFDM_SYR_OFFSET		0xF11C00FF
+
+/* PPM_OFFSET1 */
+#define	R367_OFDM_PPM_OFFSET1		0xF11D
+#define	F367_OFDM_PPM_OFFSET_HI		0xF11D00FF
+
+/* PPM_OFFSET2 */
+#define	R367_OFDM_PPM_OFFSET2		0xF11E
+#define	F367_OFDM_PPM_OFFSET_LO		0xF11E00FF
+
+/* TRACKER_FREE2 */
+#define	R367_OFDM_TRACKER_FREE2		0xF11F
+#define	F367_OFDM_TRACKER_FREE_2		0xF11F00FF
+
+/* DEBG_LT10 */
+#define	R367_OFDM_DEBG_LT10		0xF120
+#define	F367_OFDM_DEBUG_LT10		0xF12000FF
+
+/* DEBG_LT11 */
+#define	R367_OFDM_DEBG_LT11		0xF121
+#define	F367_OFDM_DEBUG_LT11		0xF12100FF
+
+/* DEBG_LT12 */
+#define	R367_OFDM_DEBG_LT12		0xF122
+#define	F367_OFDM_DEBUG_LT12		0xF12200FF
+
+/* DEBG_LT13 */
+#define	R367_OFDM_DEBG_LT13		0xF123
+#define	F367_OFDM_DEBUG_LT13		0xF12300FF
+
+/* DEBG_LT14 */
+#define	R367_OFDM_DEBG_LT14		0xF124
+#define	F367_OFDM_DEBUG_LT14		0xF12400FF
+
+/* DEBG_LT15 */
+#define	R367_OFDM_DEBG_LT15		0xF125
+#define	F367_OFDM_DEBUG_LT15		0xF12500FF
+
+/* DEBG_LT16 */
+#define	R367_OFDM_DEBG_LT16		0xF126
+#define	F367_OFDM_DEBUG_LT16		0xF12600FF
+
+/* DEBG_LT17 */
+#define	R367_OFDM_DEBG_LT17		0xF127
+#define	F367_OFDM_DEBUG_LT17		0xF12700FF
+
+/* DEBG_LT18 */
+#define	R367_OFDM_DEBG_LT18		0xF128
+#define	F367_OFDM_DEBUG_LT18		0xF12800FF
+
+/* DEBG_LT19 */
+#define	R367_OFDM_DEBG_LT19		0xF129
+#define	F367_OFDM_DEBUG_LT19		0xF12900FF
+
+/* DEBG_LT1A */
+#define	R367_OFDM_DEBG_LT1A		0xF12A
+#define	F367_OFDM_DEBUG_LT1A		0xF12A00FF
+
+/* DEBG_LT1B */
+#define	R367_OFDM_DEBG_LT1B		0xF12B
+#define	F367_OFDM_DEBUG_LT1B		0xF12B00FF
+
+/* DEBG_LT1C */
+#define	R367_OFDM_DEBG_LT1C		0xF12C
+#define	F367_OFDM_DEBUG_LT1C		0xF12C00FF
+
+/* DEBG_LT1D */
+#define	R367_OFDM_DEBG_LT1D		0xF12D
+#define	F367_OFDM_DEBUG_LT1D		0xF12D00FF
+
+/* DEBG_LT1E */
+#define	R367_OFDM_DEBG_LT1E		0xF12E
+#define	F367_OFDM_DEBUG_LT1E		0xF12E00FF
+
+/* DEBG_LT1F */
+#define	R367_OFDM_DEBG_LT1F		0xF12F
+#define	F367_OFDM_DEBUG_LT1F		0xF12F00FF
+
+/* RCCFGH */
+#define	R367_OFDM_RCCFGH		0xF200
+#define	F367_OFDM_TSRCFIFO_DVBCI		0xF2000080
+#define	F367_OFDM_TSRCFIFO_SERIAL		0xF2000040
+#define	F367_OFDM_TSRCFIFO_DISABLE		0xF2000020
+#define	F367_OFDM_TSFIFO_2TORC		0xF2000010
+#define	F367_OFDM_TSRCFIFO_HSGNLOUT		0xF2000008
+#define	F367_OFDM_TSRCFIFO_ERRMODE		0xF2000006
+#define	F367_OFDM_RCCFGH_0		0xF2000001
+
+/* RCCFGM */
+#define	R367_OFDM_RCCFGM		0xF201
+#define	F367_OFDM_TSRCFIFO_MANSPEED		0xF20100C0
+#define	F367_OFDM_TSRCFIFO_PERMDATA		0xF2010020
+#define	F367_OFDM_TSRCFIFO_NONEWSGNL		0xF2010010
+#define	F367_OFDM_RCBYTE_OVERSAMPLING		0xF201000E
+#define	F367_OFDM_TSRCFIFO_INVDATA		0xF2010001
+
+/* RCCFGL */
+#define	R367_OFDM_RCCFGL		0xF202
+#define	F367_OFDM_TSRCFIFO_BCLKDEL1CK		0xF20200C0
+#define	F367_OFDM_RCCFGL_5		0xF2020020
+#define	F367_OFDM_TSRCFIFO_DUTY50		0xF2020010
+#define	F367_OFDM_TSRCFIFO_NSGNL2DATA		0xF2020008
+#define	F367_OFDM_TSRCFIFO_DISSERMUX		0xF2020004
+#define	F367_OFDM_RCCFGL_1		0xF2020002
+#define	F367_OFDM_TSRCFIFO_STOPCKDIS		0xF2020001
+
+/* RCINSDELH */
+#define	R367_OFDM_RCINSDELH		0xF203
+#define	F367_OFDM_TSRCDEL_SYNCBYTE		0xF2030080
+#define	F367_OFDM_TSRCDEL_XXHEADER		0xF2030040
+#define	F367_OFDM_TSRCDEL_BBHEADER		0xF2030020
+#define	F367_OFDM_TSRCDEL_DATAFIELD		0xF2030010
+#define	F367_OFDM_TSRCINSDEL_ISCR		0xF2030008
+#define	F367_OFDM_TSRCINSDEL_NPD		0xF2030004
+#define	F367_OFDM_TSRCINSDEL_RSPARITY		0xF2030002
+#define	F367_OFDM_TSRCINSDEL_CRC8		0xF2030001
+
+/* RCINSDELM */
+#define	R367_OFDM_RCINSDELM		0xF204
+#define	F367_OFDM_TSRCINS_BBPADDING		0xF2040080
+#define	F367_OFDM_TSRCINS_BCHFEC		0xF2040040
+#define	F367_OFDM_TSRCINS_LDPCFEC		0xF2040020
+#define	F367_OFDM_TSRCINS_EMODCOD		0xF2040010
+#define	F367_OFDM_TSRCINS_TOKEN		0xF2040008
+#define	F367_OFDM_TSRCINS_XXXERR		0xF2040004
+#define	F367_OFDM_TSRCINS_MATYPE		0xF2040002
+#define	F367_OFDM_TSRCINS_UPL		0xF2040001
+
+/* RCINSDELL */
+#define	R367_OFDM_RCINSDELL		0xF205
+#define	F367_OFDM_TSRCINS_DFL		0xF2050080
+#define	F367_OFDM_TSRCINS_SYNCD		0xF2050040
+#define	F367_OFDM_TSRCINS_BLOCLEN		0xF2050020
+#define	F367_OFDM_TSRCINS_SIGPCOUNT		0xF2050010
+#define	F367_OFDM_TSRCINS_FIFO		0xF2050008
+#define	F367_OFDM_TSRCINS_REALPACK		0xF2050004
+#define	F367_OFDM_TSRCINS_TSCONFIG		0xF2050002
+#define	F367_OFDM_TSRCINS_LATENCY		0xF2050001
+
+/* RCSTATUS */
+#define	R367_OFDM_RCSTATUS		0xF206
+#define	F367_OFDM_TSRCFIFO_LINEOK		0xF2060080
+#define	F367_OFDM_TSRCFIFO_ERROR		0xF2060040
+#define	F367_OFDM_TSRCFIFO_DATA7		0xF2060020
+#define	F367_OFDM_RCSTATUS_4		0xF2060010
+#define	F367_OFDM_TSRCFIFO_DEMODSEL		0xF2060008
+#define	F367_OFDM_TSRC1FIFOSPEED_STORE		0xF2060004
+#define	F367_OFDM_RCSTATUS_1		0xF2060002
+#define	F367_OFDM_TSRCSERIAL_IMPOSSIBLE		0xF2060001
+
+/* RCSPEED */
+#define	R367_OFDM_RCSPEED		0xF207
+#define	F367_OFDM_TSRCFIFO_OUTSPEED		0xF20700FF
+
+/* RCDEBUGM */
+#define	R367_OFDM_RCDEBUGM		0xF208
+#define	F367_OFDM_SD_UNSYNC		0xF2080080
+#define	F367_OFDM_ULFLOCK_DETECTM		0xF2080040
+#define	F367_OFDM_SUL_SELECTOS		0xF2080020
+#define	F367_OFDM_DILUL_NOSCRBLE		0xF2080010
+#define	F367_OFDM_NUL_SCRB		0xF2080008
+#define	F367_OFDM_UL_SCRB		0xF2080004
+#define	F367_OFDM_SCRAULBAD		0xF2080002
+#define	F367_OFDM_SCRAUL_UNSYNC		0xF2080001
+
+/* RCDEBUGL */
+#define	R367_OFDM_RCDEBUGL		0xF209
+#define	F367_OFDM_RS_ERR		0xF2090080
+#define	F367_OFDM_LLFLOCK_DETECTM		0xF2090040
+#define	F367_OFDM_NOT_SUL_SELECTOS		0xF2090020
+#define	F367_OFDM_DILLL_NOSCRBLE		0xF2090010
+#define	F367_OFDM_NLL_SCRB		0xF2090008
+#define	F367_OFDM_LL_SCRB		0xF2090004
+#define	F367_OFDM_SCRALLBAD		0xF2090002
+#define	F367_OFDM_SCRALL_UNSYNC		0xF2090001
+
+/* RCOBSCFG */
+#define	R367_OFDM_RCOBSCFG		0xF20A
+#define	F367_OFDM_TSRCFIFO_OBSCFG		0xF20A00FF
+
+/* RCOBSM */
+#define	R367_OFDM_RCOBSM		0xF20B
+#define	F367_OFDM_TSRCFIFO_OBSDATA_HI		0xF20B00FF
+
+/* RCOBSL */
+#define	R367_OFDM_RCOBSL		0xF20C
+#define	F367_OFDM_TSRCFIFO_OBSDATA_LO		0xF20C00FF
+
+/* RCFECSPY */
+#define	R367_OFDM_RCFECSPY		0xF210
+#define	F367_OFDM_SPYRC_ENABLE		0xF2100080
+#define	F367_OFDM_RCNO_SYNCBYTE		0xF2100040
+#define	F367_OFDM_RCSERIAL_MODE		0xF2100020
+#define	F367_OFDM_RCUNUSUAL_PACKET		0xF2100010
+#define	F367_OFDM_BERRCMETER_DATAMODE		0xF210000C
+#define	F367_OFDM_BERRCMETER_LMODE		0xF2100002
+#define	F367_OFDM_BERRCMETER_RESET		0xF2100001
+
+/* RCFSPYCFG */
+#define	R367_OFDM_RCFSPYCFG		0xF211
+#define	F367_OFDM_FECSPYRC_INPUT		0xF21100C0
+#define	F367_OFDM_RCRST_ON_ERROR		0xF2110020
+#define	F367_OFDM_RCONE_SHOT		0xF2110010
+#define	F367_OFDM_RCI2C_MODE		0xF211000C
+#define	F367_OFDM_SPYRC_HSTERESIS		0xF2110003
+
+/* RCFSPYDATA */
+#define	R367_OFDM_RCFSPYDATA		0xF212
+#define	F367_OFDM_SPYRC_STUFFING		0xF2120080
+#define	F367_OFDM_RCNOERR_PKTJITTER		0xF2120040
+#define	F367_OFDM_SPYRC_CNULLPKT		0xF2120020
+#define	F367_OFDM_SPYRC_OUTDATA_MODE		0xF212001F
+
+/* RCFSPYOUT */
+#define	R367_OFDM_RCFSPYOUT		0xF213
+#define	F367_OFDM_FSPYRC_DIRECT		0xF2130080
+#define	F367_OFDM_RCFSPYOUT_6		0xF2130040
+#define	F367_OFDM_SPYRC_OUTDATA_BUS		0xF2130038
+#define	F367_OFDM_RCSTUFF_MODE		0xF2130007
+
+/* RCFSTATUS */
+#define	R367_OFDM_RCFSTATUS		0xF214
+#define	F367_OFDM_SPYRC_ENDSIM		0xF2140080
+#define	F367_OFDM_RCVALID_SIM		0xF2140040
+#define	F367_OFDM_RCFOUND_SIGNAL		0xF2140020
+#define	F367_OFDM_RCDSS_SYNCBYTE		0xF2140010
+#define	F367_OFDM_RCRESULT_STATE		0xF214000F
+
+/* RCFGOODPACK */
+#define	R367_OFDM_RCFGOODPACK		0xF215
+#define	F367_OFDM_RCGOOD_PACKET		0xF21500FF
+
+/* RCFPACKCNT */
+#define	R367_OFDM_RCFPACKCNT		0xF216
+#define	F367_OFDM_RCPACKET_COUNTER		0xF21600FF
+
+/* RCFSPYMISC */
+#define	R367_OFDM_RCFSPYMISC		0xF217
+#define	F367_OFDM_RCLABEL_COUNTER		0xF21700FF
+
+/* RCFBERCPT4 */
+#define	R367_OFDM_RCFBERCPT4		0xF218
+#define	F367_OFDM_FBERRCMETER_CPT_MMMMSB		0xF21800FF
+
+/* RCFBERCPT3 */
+#define	R367_OFDM_RCFBERCPT3		0xF219
+#define	F367_OFDM_FBERRCMETER_CPT_MMMSB		0xF21900FF
+
+/* RCFBERCPT2 */
+#define	R367_OFDM_RCFBERCPT2		0xF21A
+#define	F367_OFDM_FBERRCMETER_CPT_MMSB		0xF21A00FF
+
+/* RCFBERCPT1 */
+#define	R367_OFDM_RCFBERCPT1		0xF21B
+#define	F367_OFDM_FBERRCMETER_CPT_MSB		0xF21B00FF
+
+/* RCFBERCPT0 */
+#define	R367_OFDM_RCFBERCPT0		0xF21C
+#define	F367_OFDM_FBERRCMETER_CPT_LSB		0xF21C00FF
+
+/* RCFBERERR2 */
+#define	R367_OFDM_RCFBERERR2		0xF21D
+#define	F367_OFDM_FBERRCMETER_ERR_HI		0xF21D00FF
+
+/* RCFBERERR1 */
+#define	R367_OFDM_RCFBERERR1		0xF21E
+#define	F367_OFDM_FBERRCMETER_ERR		0xF21E00FF
+
+/* RCFBERERR0 */
+#define	R367_OFDM_RCFBERERR0		0xF21F
+#define	F367_OFDM_FBERRCMETER_ERR_LO		0xF21F00FF
+
+/* RCFSTATESM */
+#define	R367_OFDM_RCFSTATESM		0xF220
+#define	F367_OFDM_RCRSTATE_F		0xF2200080
+#define	F367_OFDM_RCRSTATE_E		0xF2200040
+#define	F367_OFDM_RCRSTATE_D		0xF2200020
+#define	F367_OFDM_RCRSTATE_C		0xF2200010
+#define	F367_OFDM_RCRSTATE_B		0xF2200008
+#define	F367_OFDM_RCRSTATE_A		0xF2200004
+#define	F367_OFDM_RCRSTATE_9		0xF2200002
+#define	F367_OFDM_RCRSTATE_8		0xF2200001
+
+/* RCFSTATESL */
+#define	R367_OFDM_RCFSTATESL		0xF221
+#define	F367_OFDM_RCRSTATE_7		0xF2210080
+#define	F367_OFDM_RCRSTATE_6		0xF2210040
+#define	F367_OFDM_RCRSTATE_5		0xF2210020
+#define	F367_OFDM_RCRSTATE_4		0xF2210010
+#define	F367_OFDM_RCRSTATE_3		0xF2210008
+#define	F367_OFDM_RCRSTATE_2		0xF2210004
+#define	F367_OFDM_RCRSTATE_1		0xF2210002
+#define	F367_OFDM_RCRSTATE_0		0xF2210001
+
+/* RCFSPYBER */
+#define	R367_OFDM_RCFSPYBER		0xF222
+#define	F367_OFDM_RCFSPYBER_7		0xF2220080
+#define	F367_OFDM_SPYRCOBS_XORREAD		0xF2220040
+#define	F367_OFDM_FSPYRCBER_OBSMODE		0xF2220020
+#define	F367_OFDM_FSPYRCBER_SYNCBYT		0xF2220010
+#define	F367_OFDM_FSPYRCBER_UNSYNC		0xF2220008
+#define	F367_OFDM_FSPYRCBER_CTIME		0xF2220007
+
+/* RCFSPYDISTM */
+#define	R367_OFDM_RCFSPYDISTM		0xF223
+#define	F367_OFDM_RCPKTTIME_DISTANCE_HI		0xF22300FF
+
+/* RCFSPYDISTL */
+#define	R367_OFDM_RCFSPYDISTL		0xF224
+#define	F367_OFDM_RCPKTTIME_DISTANCE_LO		0xF22400FF
+
+/* RCFSPYOBS7 */
+#define	R367_OFDM_RCFSPYOBS7		0xF228
+#define	F367_OFDM_RCSPYOBS_SPYFAIL		0xF2280080
+#define	F367_OFDM_RCSPYOBS_SPYFAIL1		0xF2280040
+#define	F367_OFDM_RCSPYOBS_ERROR		0xF2280020
+#define	F367_OFDM_RCSPYOBS_STROUT		0xF2280010
+#define	F367_OFDM_RCSPYOBS_RESULTSTATE1		0xF228000F
+
+/* RCFSPYOBS6 */
+#define	R367_OFDM_RCFSPYOBS6		0xF229
+#define	F367_OFDM_RCSPYOBS_RESULTSTATE0		0xF22900F0
+#define	F367_OFDM_RCSPYOBS_RESULTSTATEM1		0xF229000F
+
+/* RCFSPYOBS5 */
+#define	R367_OFDM_RCFSPYOBS5		0xF22A
+#define	F367_OFDM_RCSPYOBS_BYTEOFPACKET1		0xF22A00FF
+
+/* RCFSPYOBS4 */
+#define	R367_OFDM_RCFSPYOBS4		0xF22B
+#define	F367_OFDM_RCSPYOBS_BYTEVALUE1		0xF22B00FF
+
+/* RCFSPYOBS3 */
+#define	R367_OFDM_RCFSPYOBS3		0xF22C
+#define	F367_OFDM_RCSPYOBS_DATA1		0xF22C00FF
+
+/* RCFSPYOBS2 */
+#define	R367_OFDM_RCFSPYOBS2		0xF22D
+#define	F367_OFDM_RCSPYOBS_DATA0		0xF22D00FF
+
+/* RCFSPYOBS1 */
+#define	R367_OFDM_RCFSPYOBS1		0xF22E
+#define	F367_OFDM_RCSPYOBS_DATAM1		0xF22E00FF
+
+/* RCFSPYOBS0 */
+#define	R367_OFDM_RCFSPYOBS0		0xF22F
+#define	F367_OFDM_RCSPYOBS_DATAM2		0xF22F00FF
+
+/* TSGENERAL */
+#define	R367_TSGENERAL		0xF230
+#define	F367_TSGENERAL_7		0xF2300080
+#define	F367_TSGENERAL_6		0xF2300040
+#define	F367_TSFIFO_BCLK1ALL		0xF2300020
+#define	F367_TSGENERAL_4		0xF2300010
+#define	F367_MUXSTREAM_OUTMODE		0xF2300008
+#define	F367_TSFIFO_PERMPARAL		0xF2300006
+#define	F367_RST_REEDSOLO		0xF2300001
+
+/* RC1SPEED */
+#define	R367_RC1SPEED		0xF231
+#define	F367_TSRCFIFO1_OUTSPEED		0xF23100FF
+
+/* TSGSTATUS */
+#define	R367_TSGSTATUS		0xF232
+#define	F367_TSGSTATUS_7		0xF2320080
+#define	F367_TSGSTATUS_6		0xF2320040
+#define	F367_RSMEM_FULL		0xF2320020
+#define	F367_RS_MULTCALC		0xF2320010
+#define	F367_RSIN_OVERTIME		0xF2320008
+#define	F367_TSFIFO3_DEMODSEL		0xF2320004
+#define	F367_TSFIFO2_DEMODSEL		0xF2320002
+#define	F367_TSFIFO1_DEMODSEL		0xF2320001
+
+
+/* FECM */
+#define	R367_OFDM_FECM		0xF233
+#define	F367_OFDM_DSS_DVB		0xF2330080
+#define	F367_OFDM_DEMOD_BYPASS		0xF2330040
+#define	F367_OFDM_CMP_SLOWMODE		0xF2330020
+#define	F367_OFDM_DSS_SRCH		0xF2330010
+#define	F367_OFDM_FECM_3		0xF2330008
+#define	F367_OFDM_DIFF_MODEVIT		0xF2330004
+#define	F367_OFDM_SYNCVIT		0xF2330002
+#define	F367_OFDM_I2CSYM		0xF2330001
+
+/* VTH12 */
+#define	R367_OFDM_VTH12		0xF234
+#define	F367_OFDM_VTH_12		0xF23400FF
+
+/* VTH23 */
+#define	R367_OFDM_VTH23		0xF235
+#define	F367_OFDM_VTH_23		0xF23500FF
+
+/* VTH34 */
+#define	R367_OFDM_VTH34		0xF236
+#define	F367_OFDM_VTH_34		0xF23600FF
+
+/* VTH56 */
+#define	R367_OFDM_VTH56		0xF237
+#define	F367_OFDM_VTH_56		0xF23700FF
+
+/* VTH67 */
+#define	R367_OFDM_VTH67		0xF238
+#define	F367_OFDM_VTH_67		0xF23800FF
+
+/* VTH78 */
+#define	R367_OFDM_VTH78		0xF239
+#define	F367_OFDM_VTH_78		0xF23900FF
+
+/* VITCURPUN */
+#define	R367_OFDM_VITCURPUN		0xF23A
+#define	F367_OFDM_VIT_MAPPING		0xF23A00E0
+#define	F367_OFDM_VIT_CURPUN		0xF23A001F
+
+/* VERROR */
+#define	R367_OFDM_VERROR		0xF23B
+#define	F367_OFDM_REGERR_VIT		0xF23B00FF
+
+/* PRVIT */
+#define	R367_OFDM_PRVIT		0xF23C
+#define	F367_OFDM_PRVIT_7		0xF23C0080
+#define	F367_OFDM_DIS_VTHLOCK		0xF23C0040
+#define	F367_OFDM_E7_8VIT		0xF23C0020
+#define	F367_OFDM_E6_7VIT		0xF23C0010
+#define	F367_OFDM_E5_6VIT		0xF23C0008
+#define	F367_OFDM_E3_4VIT		0xF23C0004
+#define	F367_OFDM_E2_3VIT		0xF23C0002
+#define	F367_OFDM_E1_2VIT		0xF23C0001
+
+/* VAVSRVIT */
+#define	R367_OFDM_VAVSRVIT		0xF23D
+#define	F367_OFDM_AMVIT		0xF23D0080
+#define	F367_OFDM_FROZENVIT		0xF23D0040
+#define	F367_OFDM_SNVIT		0xF23D0030
+#define	F367_OFDM_TOVVIT		0xF23D000C
+#define	F367_OFDM_HYPVIT		0xF23D0003
+
+/* VSTATUSVIT */
+#define	R367_OFDM_VSTATUSVIT		0xF23E
+#define	F367_OFDM_VITERBI_ON		0xF23E0080
+#define	F367_OFDM_END_LOOPVIT		0xF23E0040
+#define	F367_OFDM_VITERBI_DEPRF		0xF23E0020
+#define	F367_OFDM_PRFVIT		0xF23E0010
+#define	F367_OFDM_LOCKEDVIT		0xF23E0008
+#define	F367_OFDM_VITERBI_DELOCK		0xF23E0004
+#define	F367_OFDM_VIT_DEMODSEL		0xF23E0002
+#define	F367_OFDM_VITERBI_COMPOUT		0xF23E0001
+
+/* VTHINUSE */
+#define	R367_OFDM_VTHINUSE		0xF23F
+#define	F367_OFDM_VIT_INUSE		0xF23F00FF
+
+/* KDIV12 */
+#define	R367_OFDM_KDIV12		0xF240
+#define	F367_OFDM_KDIV12_MANUAL		0xF2400080
+#define	F367_OFDM_K_DIVIDER_12		0xF240007F
+
+/* KDIV23 */
+#define	R367_OFDM_KDIV23		0xF241
+#define	F367_OFDM_KDIV23_MANUAL		0xF2410080
+#define	F367_OFDM_K_DIVIDER_23		0xF241007F
+
+/* KDIV34 */
+#define	R367_OFDM_KDIV34		0xF242
+#define	F367_OFDM_KDIV34_MANUAL		0xF2420080
+#define	F367_OFDM_K_DIVIDER_34		0xF242007F
+
+/* KDIV56 */
+#define	R367_OFDM_KDIV56		0xF243
+#define	F367_OFDM_KDIV56_MANUAL		0xF2430080
+#define	F367_OFDM_K_DIVIDER_56		0xF243007F
+
+/* KDIV67 */
+#define	R367_OFDM_KDIV67		0xF244
+#define	F367_OFDM_KDIV67_MANUAL		0xF2440080
+#define	F367_OFDM_K_DIVIDER_67		0xF244007F
+
+/* KDIV78 */
+#define	R367_OFDM_KDIV78		0xF245
+#define	F367_OFDM_KDIV78_MANUAL		0xF2450080
+#define	F367_OFDM_K_DIVIDER_78		0xF245007F
+
+/* SIGPOWER */
+#define	R367_OFDM_SIGPOWER		0xF246
+#define	F367_OFDM_SIGPOWER_MANUAL		0xF2460080
+#define	F367_OFDM_SIG_POWER		0xF246007F
+
+/* DEMAPVIT */
+#define	R367_OFDM_DEMAPVIT		0xF247
+#define	F367_OFDM_DEMAPVIT_7		0xF2470080
+#define	F367_OFDM_K_DIVIDER_VIT		0xF247007F
+
+/* VITSCALE */
+#define	R367_OFDM_VITSCALE		0xF248
+#define	F367_OFDM_NVTH_NOSRANGE		0xF2480080
+#define	F367_OFDM_VERROR_MAXMODE		0xF2480040
+#define	F367_OFDM_KDIV_MODE		0xF2480030
+#define	F367_OFDM_NSLOWSN_LOCKED		0xF2480008
+#define	F367_OFDM_DELOCK_PRFLOSS		0xF2480004
+#define	F367_OFDM_DIS_RSFLOCK		0xF2480002
+#define	F367_OFDM_VITSCALE_0		0xF2480001
+
+/* FFEC1PRG */
+#define	R367_OFDM_FFEC1PRG		0xF249
+#define	F367_OFDM_FDSS_DVB		0xF2490080
+#define	F367_OFDM_FDSS_SRCH		0xF2490040
+#define	F367_OFDM_FFECPROG_5		0xF2490020
+#define	F367_OFDM_FFECPROG_4		0xF2490010
+#define	F367_OFDM_FFECPROG_3		0xF2490008
+#define	F367_OFDM_FFECPROG_2		0xF2490004
+#define	F367_OFDM_FTS1_DISABLE		0xF2490002
+#define	F367_OFDM_FTS2_DISABLE		0xF2490001
+
+/* FVITCURPUN */
+#define	R367_OFDM_FVITCURPUN		0xF24A
+#define	F367_OFDM_FVIT_MAPPING		0xF24A00E0
+#define	F367_OFDM_FVIT_CURPUN		0xF24A001F
+
+/* FVERROR */
+#define	R367_OFDM_FVERROR		0xF24B
+#define	F367_OFDM_FREGERR_VIT		0xF24B00FF
+
+/* FVSTATUSVIT */
+#define	R367_OFDM_FVSTATUSVIT		0xF24C
+#define	F367_OFDM_FVITERBI_ON		0xF24C0080
+#define	F367_OFDM_F1END_LOOPVIT		0xF24C0040
+#define	F367_OFDM_FVITERBI_DEPRF		0xF24C0020
+#define	F367_OFDM_FPRFVIT		0xF24C0010
+#define	F367_OFDM_FLOCKEDVIT		0xF24C0008
+#define	F367_OFDM_FVITERBI_DELOCK		0xF24C0004
+#define	F367_OFDM_FVIT_DEMODSEL		0xF24C0002
+#define	F367_OFDM_FVITERBI_COMPOUT		0xF24C0001
+
+/* DEBUG_LT1 */
+#define	R367_OFDM_DEBUG_LT1		0xF24D
+#define	F367_OFDM_DBG_LT1		0xF24D00FF
+
+/* DEBUG_LT2 */
+#define	R367_OFDM_DEBUG_LT2		0xF24E
+#define	F367_OFDM_DBG_LT2		0xF24E00FF
+
+/* DEBUG_LT3 */
+#define	R367_OFDM_DEBUG_LT3		0xF24F
+#define	F367_OFDM_DBG_LT3		0xF24F00FF
+
+	/*	TSTSFMET */
+#define	R367_OFDM_TSTSFMET			0xF250
+#define F367_OFDM_TSTSFEC_METRIQUES	0xF25000FF
+
+	/*	SELOUT */
+#define	R367_OFDM_SELOUT				0xF252
+#define	F367_OFDM_EN_SYNC			0xF2520080
+#define	F367_OFDM_EN_TBUSDEMAP       0xF2520040 
+#define	F367_OFDM_SELOUT_5			0xF2520020
+#define	F367_OFDM_SELOUT_4			0xF2520010
+#define	F367_OFDM_TSTSYNCHRO_MODE    0xF2520002
+
+	/*	TSYNC */
+#define R367_OFDM_TSYNC				0xF253
+#define F367_OFDM_CURPUN_INCMODE		0xF2530080
+#define F367_OFDM_CERR_TSTMODE		0xF2530040
+#define F367_OFDM_SHIFTSOF_MODE		0xF2530030
+#define F367_OFDM_SLOWPHA_MODE		0xF2530008
+#define F367_OFDM_PXX_BYPALL			0xF2530004
+#define F367_OFDM_FROTA45_FIRST		0xF2530002
+#define F367_OFDM_TST_BCHERROR		0xF2530001
+
+	/*	TSTERR */
+#define R367_OFDM_TSTERR				0xF254
+#define F367_OFDM_TST_LONGPKT		0xF2540080
+#define F367_OFDM_TST_ISSYION		0xF2540040
+#define F367_OFDM_TST_NPDON			0xF2540020
+#define F367_OFDM_TSTERR_4			0xF2540010
+#define F367_OFDM_TRACEBACK_MODE		0xF2540008
+#define F367_OFDM_TST_RSPARITY		0xF2540004
+#define F367_OFDM_METRIQUE_MODE		0xF2540003
+
+	/*	TSFSYNC */
+#define R367_OFDM_TSFSYNC			0xF255
+#define F367_OFDM_EN_SFECSYNC		0xF2550080
+#define F367_OFDM_EN_SFECDEMAP		0xF2550040
+#define F367_OFDM_SFCERR_TSTMODE		0xF2550020
+#define F367_OFDM_SFECPXX_BYPALL		0xF2550010
+#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F
+
+	/*	TSTSFERR */
+#define R367_OFDM_TSTSFERR			0xF256
+#define F367_OFDM_TSTSTERR_7			0xF2560080
+#define F367_OFDM_TSTSTERR_6			0xF2560040
+#define F367_OFDM_TSTSTERR_5 		0xF2560020
+#define F367_OFDM_TSTSTERR_4			0xF2560010
+#define F367_OFDM_SFECTRACEBACK_MODE	0xF2560008
+#define F367_OFDM_SFEC_NCONVPROG		0xF2560004
+#define F367_OFDM_SFECMETRIQUE_MODE	0xF2560003
+
+	/*	TSTTSSF1 */
+#define R367_OFDM_TSTTSSF1			0xF258
+#define F367_OFDM_TSTERSSF			0xF2580080
+#define F367_OFDM_TSTTSSFEN			0xF2580040
+#define F367_OFDM_SFEC_OUTMODE		0xF2580030
+#define F367_OFDM_XLSF_NOFTHRESHOLD  0xF2580008
+#define F367_OFDM_TSTTSSF_STACKSEL	0xF2580007
+
+	/*	TSTTSSF2 */
+#define R367_OFDM_TSTTSSF2			0xF259
+#define F367_OFDM_DILSF_DBBHEADER	0xF2590080
+#define F367_OFDM_TSTTSSF_DISBUG		0xF2590040
+#define F367_OFDM_TSTTSSF_NOBADSTART	0xF2590020
+#define F367_OFDM_TSTTSSF_SELECT 	0xF259001F
+
+	/*	TSTTSSF3 */
+#define R367_OFDM_TSTTSSF3			0xF25A
+#define F367_OFDM_TSTTSSF3_7			0xF25A0080
+#define F367_OFDM_TSTTSSF3_6			0xF25A0040
+#define F367_OFDM_TSTTSSF3_5			0xF25A0020
+#define F367_OFDM_TSTTSSF3_4			0xF25A0010
+#define F367_OFDM_TSTTSSF3_3			0xF25A0008
+#define F367_OFDM_TSTTSSF3_2			0xF25A0004
+#define F367_OFDM_TSTTSSF3_1			0xF25A0002
+#define F367_OFDM_DISSF_CLKENABLE    0xF25A0001
+
+	/*	TSTTS1 */
+#define R367_OFDM_TSTTS1				0xF25C
+#define F367_OFDM_TSTERS				0xF25C0080
+#define F367_OFDM_TSFIFO_DSSSYNCB	0xF25C0040
+#define F367_OFDM_TSTTS_FSPYBEFRS	0xF25C0020
+#define F367_OFDM_NFORCE_SYNCBYTE	0xF25C0010
+#define F367_OFDM_XL_NOFTHRESHOLD	0xF25C0008
+#define F367_OFDM_TSTTS_FRFORCEPKT	0xF25C0004
+#define F367_OFDM_DESCR_NOTAUTO		0xF25C0002
+#define F367_OFDM_TSTTSEN			0xF25C0001
+		    
+	/*	TSTTS2 */
+#define R367_OFDM_TSTTS2				0xF25D
+#define F367_OFDM_DIL_DBBHEADER		0xF25D0080
+#define F367_OFDM_TSTTS_NOBADXXX		0xF25D0040
+#define F367_OFDM_TSFIFO_DELSPEEDUP	0xF25D0020
+#define F367_OFDM_TSTTS_SELECT		0xF25D001F
+		    
+	/*	TSTTS3 */
+#define R367_OFDM_TSTTS3				0xF25E
+#define F367_OFDM_TSTTS_NOPKTGAIN	0xF25E0080
+#define F367_OFDM_TSTTS_NOPKTENE		0xF25E0040
+#define F367_OFDM_TSTTS_ISOLATION	0xF25E0020
+#define F367_OFDM_TSTTS_DISBUG		0xF25E0010
+#define F367_OFDM_TSTTS_NOBADSTART	0xF25E0008
+#define F367_OFDM_TSTTS_STACKSEL		0xF25E0007
+
+	/*	TSTTS4 */
+#define R367_OFDM_TSTTS4				0xF25F
+#define F367_OFDM_TSTTS4_7			0xF25F0080
+#define F367_OFDM_TSTTS4_6			0xF25F0040
+#define F367_OFDM_TSTTS4_5			0xF25F0020
+#define F367_OFDM_TSTTS_DISDSTATE	0xF25F0010
+#define F367_OFDM_TSTTS_FASTNOSYNC	0xF25F0008
+#define F367_OFDM_EXT_FECSPYIN		0xF25F0004
+#define F367_OFDM_TSTTS_NODPZERO		0xF25F0002
+#define F367_OFDM_TSTTS_NODIV3		0xF25F0001
+
+	/*	TSTTSRC */
+#define R367_OFDM_TSTTSRC				0xF26C
+#define F367_OFDM_TSTTSRC_7				0xF26C0080
+#define F367_OFDM_TSRCFIFO_DSSSYNCB		0xF26C0040
+#define F367_OFDM_TSRCFIFO_DPUNACTIVE	0xF26C0020
+#define F367_OFDM_TSRCFIFO_DELSPEEDUP	0xF26C0010
+#define F367_OFDM_TSTTSRC_NODIV3			0xF26C0008
+#define F367_OFDM_TSTTSRC_FRFORCEPKT		0xF26C0004
+#define F367_OFDM_SAT25_SDDORIGINE		0xF26C0002
+#define F367_OFDM_TSTTSRC_INACTIVE		0xF26C0001
+
+	/*	TSTTSRS */
+#define R367_OFDM_TSTTSRS				0xF26D
+#define F367_OFDM_TSTTSRS_7				0xF26D0080
+#define F367_OFDM_TSTTSRS_6				0xF26D0040
+#define F367_OFDM_TSTTSRS_5				0xF26D0020
+#define F367_OFDM_TSTTSRS_4				0xF26D0010
+#define F367_OFDM_TSTTSRS_3				0xF26D0008
+#define F367_OFDM_TSTTSRS_2				0xF26D0004
+#define F367_OFDM_TSTRS_DISRS2			0xF26D0002
+#define F367_OFDM_TSTRS_DISRS1			0xF26D0001
+
+/* TSSTATEM */
+#define	R367_OFDM_TSSTATEM		0xF270
+#define	F367_OFDM_TSDIL_ON		0xF2700080
+#define	F367_OFDM_TSSKIPRS_ON		0xF2700040
+#define	F367_OFDM_TSRS_ON		0xF2700020
+#define	F367_OFDM_TSDESCRAMB_ON		0xF2700010
+#define	F367_OFDM_TSFRAME_MODE		0xF2700008
+#define	F367_OFDM_TS_DISABLE		0xF2700004
+#define	F367_OFDM_TSACM_MODE		0xF2700002
+#define	F367_OFDM_TSOUT_NOSYNC		0xF2700001
+
+/* TSSTATEL */
+#define	R367_OFDM_TSSTATEL		0xF271
+#define	F367_OFDM_TSNOSYNCBYTE		0xF2710080
+#define	F367_OFDM_TSPARITY_ON		0xF2710040
+#define	F367_OFDM_TSSYNCOUTRS_ON		0xF2710020
+#define	F367_OFDM_TSDVBS2_MODE		0xF2710010
+#define	F367_OFDM_TSISSYI_ON		0xF2710008
+#define	F367_OFDM_TSNPD_ON		0xF2710004
+#define	F367_OFDM_TSCRC8_ON		0xF2710002
+#define	F367_OFDM_TSDSS_PACKET		0xF2710001
+
+/* TSCFGH */
+#define	R367_OFDM_TSCFGH		0xF272
+#define	F367_OFDM_TSFIFO_DVBCI		0xF2720080
+#define	F367_OFDM_TSFIFO_SERIAL		0xF2720040
+#define	F367_OFDM_TSFIFO_TEIUPDATE		0xF2720020
+#define	F367_OFDM_TSFIFO_DUTY50		0xF2720010
+#define	F367_OFDM_TSFIFO_HSGNLOUT		0xF2720008
+#define	F367_OFDM_TSFIFO_ERRMODE		0xF2720006
+#define	F367_OFDM_RST_HWARE		0xF2720001
+
+/* TSCFGM */
+#define	R367_OFDM_TSCFGM		0xF273
+#define	F367_OFDM_TSFIFO_MANSPEED		0xF27300C0
+#define	F367_OFDM_TSFIFO_PERMDATA		0xF2730020
+#define	F367_OFDM_TSFIFO_NONEWSGNL		0xF2730010
+#define	F367_OFDM_TSFIFO_BITSPEED		0xF2730008
+#define	F367_OFDM_NPD_SPECDVBS2		0xF2730004
+#define	F367_OFDM_TSFIFO_STOPCKDIS		0xF2730002
+#define	F367_OFDM_TSFIFO_INVDATA		0xF2730001
+
+/* TSCFGL */
+#define	R367_OFDM_TSCFGL		0xF274
+#define	F367_OFDM_TSFIFO_BCLKDEL1CK		0xF27400C0
+#define	F367_OFDM_BCHERROR_MODE		0xF2740030
+#define	F367_OFDM_TSFIFO_NSGNL2DATA		0xF2740008
+#define	F367_OFDM_TSFIFO_EMBINDVB		0xF2740004
+#define	F367_OFDM_TSFIFO_DPUNACT		0xF2740002
+#define	F367_OFDM_TSFIFO_NPDOFF		0xF2740001
+
+/* TSSYNC */
+#define	R367_OFDM_TSSYNC		0xF275
+#define	F367_OFDM_TSFIFO_PERMUTE		0xF2750080
+#define	F367_OFDM_TSFIFO_FISCR3B		0xF2750060
+#define	F367_OFDM_TSFIFO_SYNCMODE		0xF2750018
+#define	F367_OFDM_TSFIFO_SYNCSEL		0xF2750007
+
+/* TSINSDELH */
+#define	R367_OFDM_TSINSDELH		0xF276
+#define	F367_OFDM_TSDEL_SYNCBYTE		0xF2760080
+#define	F367_OFDM_TSDEL_XXHEADER		0xF2760040
+#define	F367_OFDM_TSDEL_BBHEADER		0xF2760020
+#define	F367_OFDM_TSDEL_DATAFIELD		0xF2760010
+#define	F367_OFDM_TSINSDEL_ISCR		0xF2760008
+#define	F367_OFDM_TSINSDEL_NPD		0xF2760004
+#define	F367_OFDM_TSINSDEL_RSPARITY		0xF2760002
+#define	F367_OFDM_TSINSDEL_CRC8		0xF2760001
+
+/* TSINSDELM */
+#define	R367_OFDM_TSINSDELM		0xF277
+#define	F367_OFDM_TSINS_BBPADDING		0xF2770080
+#define	F367_OFDM_TSINS_BCHFEC		0xF2770040
+#define	F367_OFDM_TSINS_LDPCFEC		0xF2770020
+#define	F367_OFDM_TSINS_EMODCOD		0xF2770010
+#define	F367_OFDM_TSINS_TOKEN		0xF2770008
+#define	F367_OFDM_TSINS_XXXERR		0xF2770004
+#define	F367_OFDM_TSINS_MATYPE		0xF2770002
+#define	F367_OFDM_TSINS_UPL		0xF2770001
+
+/* TSINSDELL */
+#define	R367_OFDM_TSINSDELL		0xF278
+#define	F367_OFDM_TSINS_DFL		0xF2780080
+#define	F367_OFDM_TSINS_SYNCD		0xF2780040
+#define	F367_OFDM_TSINS_BLOCLEN		0xF2780020
+#define	F367_OFDM_TSINS_SIGPCOUNT		0xF2780010
+#define	F367_OFDM_TSINS_FIFO		0xF2780008
+#define	F367_OFDM_TSINS_REALPACK		0xF2780004
+#define	F367_OFDM_TSINS_TSCONFIG		0xF2780002
+#define	F367_OFDM_TSINS_LATENCY		0xF2780001
+
+/* TSDIVN */
+#define	R367_OFDM_TSDIVN		0xF279
+#define	F367_OFDM_TSFIFO_LOWSPEED		0xF2790080
+#define	F367_OFDM_BYTE_OVERSAMPLING		0xF2790070
+#define	F367_OFDM_TSMANUAL_PACKETNBR		0xF279000F
+
+/* TSDIVPM */
+#define	R367_OFDM_TSDIVPM		0xF27A
+#define	F367_OFDM_TSMANUAL_P_HI		0xF27A00FF
+
+/* TSDIVPL */
+#define	R367_OFDM_TSDIVPL		0xF27B
+#define	F367_OFDM_TSMANUAL_P_LO		0xF27B00FF
+
+/* TSDIVQM */
+#define	R367_OFDM_TSDIVQM		0xF27C
+#define	F367_OFDM_TSMANUAL_Q_HI		0xF27C00FF
+
+/* TSDIVQL */
+#define	R367_OFDM_TSDIVQL		0xF27D
+#define	F367_OFDM_TSMANUAL_Q_LO		0xF27D00FF
+
+/* TSDILSTKM */
+#define	R367_OFDM_TSDILSTKM		0xF27E
+#define	F367_OFDM_TSFIFO_DILSTK_HI		0xF27E00FF
+
+/* TSDILSTKL */
+#define	R367_OFDM_TSDILSTKL		0xF27F
+#define	F367_OFDM_TSFIFO_DILSTK_LO		0xF27F00FF
+
+/* TSSPEED */
+#define	R367_OFDM_TSSPEED		0xF280
+#define	F367_OFDM_TSFIFO_OUTSPEED		0xF28000FF
+
+/* TSSTATUS */
+#define	R367_OFDM_TSSTATUS		0xF281
+#define	F367_OFDM_TSFIFO_LINEOK		0xF2810080
+#define	F367_OFDM_TSFIFO_ERROR		0xF2810040
+#define	F367_OFDM_TSFIFO_DATA7		0xF2810020
+#define	F367_OFDM_TSFIFO_NOSYNC		0xF2810010
+#define	F367_OFDM_ISCR_INITIALIZED		0xF2810008
+#define	F367_OFDM_ISCR_UPDATED		0xF2810004
+#define	F367_OFDM_SOFFIFO_UNREGUL		0xF2810002
+#define	F367_OFDM_DIL_READY		0xF2810001
+
+/* TSSTATUS2 */
+#define	R367_OFDM_TSSTATUS2		0xF282
+#define	F367_OFDM_TSFIFO_DEMODSEL		0xF2820080
+#define	F367_OFDM_TSFIFOSPEED_STORE		0xF2820040
+#define	F367_OFDM_DILXX_RESET		0xF2820020
+#define	F367_OFDM_TSSERIAL_IMPOSSIBLE		0xF2820010
+#define	F367_OFDM_TSFIFO_UNDERSPEED		0xF2820008
+#define	F367_OFDM_BITSPEED_EVENT		0xF2820004
+#define	F367_OFDM_UL_SCRAMBDETECT		0xF2820002
+#define	F367_OFDM_ULDTV67_FALSELOCK		0xF2820001
+
+/* TSBITRATEM */
+#define	R367_OFDM_TSBITRATEM		0xF283
+#define	F367_OFDM_TSFIFO_BITRATE_HI		0xF28300FF
+
+/* TSBITRATEL */
+#define	R367_OFDM_TSBITRATEL		0xF284
+#define	F367_OFDM_TSFIFO_BITRATE_LO		0xF28400FF
+
+/* TSPACKLENM */
+#define	R367_OFDM_TSPACKLENM		0xF285
+#define	F367_OFDM_TSFIFO_PACKCPT		0xF28500E0
+#define	F367_OFDM_DIL_RPLEN_HI		0xF285001F
+
+/* TSPACKLENL */
+#define	R367_OFDM_TSPACKLENL		0xF286
+#define	F367_OFDM_DIL_RPLEN_LO		0xF28600FF
+
+/* TSBLOCLENM */
+#define	R367_OFDM_TSBLOCLENM		0xF287
+#define	F367_OFDM_TSFIFO_PFLEN_HI		0xF28700FF
+
+/* TSBLOCLENL */
+#define	R367_OFDM_TSBLOCLENL		0xF288
+#define	F367_OFDM_TSFIFO_PFLEN_LO		0xF28800FF
+
+/* TSDLYH */
+#define	R367_OFDM_TSDLYH		0xF289
+#define	F367_OFDM_SOFFIFO_TSTIMEVALID		0xF2890080
+#define	F367_OFDM_SOFFIFO_SPEEDUP		0xF2890040
+#define	F367_OFDM_SOFFIFO_STOP		0xF2890020
+#define	F367_OFDM_SOFFIFO_REGULATED		0xF2890010
+#define	F367_OFDM_SOFFIFO_REALSBOFF_HI		0xF289000F
+
+/* TSDLYM */
+#define	R367_OFDM_TSDLYM		0xF28A
+#define	F367_OFDM_SOFFIFO_REALSBOFF_MED		0xF28A00FF
+
+/* TSDLYL */
+#define	R367_OFDM_TSDLYL		0xF28B
+#define	F367_OFDM_SOFFIFO_REALSBOFF_LO		0xF28B00FF
+
+/* TSNPDAV */
+#define	R367_OFDM_TSNPDAV		0xF28C
+#define	F367_OFDM_TSNPD_AVERAGE		0xF28C00FF
+
+/* TSBUFSTATH */
+#define	R367_OFDM_TSBUFSTATH		0xF28D
+#define	F367_OFDM_TSISCR_3BYTES		0xF28D0080
+#define	F367_OFDM_TSISCR_NEWDATA		0xF28D0040
+#define	F367_OFDM_TSISCR_BUFSTAT_HI		0xF28D003F
+
+/* TSBUFSTATM */
+#define	R367_OFDM_TSBUFSTATM		0xF28E
+#define	F367_OFDM_TSISCR_BUFSTAT_MED		0xF28E00FF
+
+/* TSBUFSTATL */
+#define	R367_OFDM_TSBUFSTATL		0xF28F
+#define	F367_OFDM_TSISCR_BUFSTAT_LO		0xF28F00FF
+
+/* TSDEBUGM */
+#define	R367_OFDM_TSDEBUGM		0xF290
+#define	F367_OFDM_TSFIFO_ILLPACKET		0xF2900080
+#define	F367_OFDM_DIL_NOSYNC		0xF2900040
+#define	F367_OFDM_DIL_ISCR		0xF2900020
+#define	F367_OFDM_DILOUT_BSYNCB		0xF2900010
+#define	F367_OFDM_TSFIFO_EMPTYPKT		0xF2900008
+#define	F367_OFDM_TSFIFO_EMPTYRD		0xF2900004
+#define	F367_OFDM_SOFFIFO_STOPM		0xF2900002
+#define	F367_OFDM_SOFFIFO_SPEEDUPM		0xF2900001
+
+/* TSDEBUGL */
+#define	R367_OFDM_TSDEBUGL		0xF291
+#define	F367_OFDM_TSFIFO_PACKLENFAIL		0xF2910080
+#define	F367_OFDM_TSFIFO_SYNCBFAIL		0xF2910040
+#define	F367_OFDM_TSFIFO_VITLIBRE		0xF2910020
+#define	F367_OFDM_TSFIFO_BOOSTSPEEDM		0xF2910010
+#define	F367_OFDM_TSFIFO_UNDERSPEEDM		0xF2910008
+#define	F367_OFDM_TSFIFO_ERROR_EVNT		0xF2910004
+#define	F367_OFDM_TSFIFO_FULL		0xF2910002
+#define	F367_OFDM_TSFIFO_OVERFLOWM		0xF2910001
+
+/* TSDLYSETH */
+#define	R367_OFDM_TSDLYSETH		0xF292
+#define	F367_OFDM_SOFFIFO_OFFSET		0xF29200E0
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_HI		0xF292001F
+
+/* TSDLYSETM */
+#define	R367_OFDM_TSDLYSETM		0xF293
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_MED		0xF29300FF
+
+/* TSDLYSETL */
+#define	R367_OFDM_TSDLYSETL		0xF294
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_LO		0xF29400FF
+
+/* TSOBSCFG */
+#define	R367_OFDM_TSOBSCFG		0xF295
+#define	F367_OFDM_TSFIFO_OBSCFG		0xF29500FF
+
+/* TSOBSM */
+#define	R367_OFDM_TSOBSM		0xF296
+#define	F367_OFDM_TSFIFO_OBSDATA_HI		0xF29600FF
+
+/* TSOBSL */
+#define	R367_OFDM_TSOBSL		0xF297
+#define	F367_OFDM_TSFIFO_OBSDATA_LO		0xF29700FF
+
+/* ERRCTRL1 */
+#define	R367_OFDM_ERRCTRL1		0xF298
+#define	F367_OFDM_ERR_SRC1		0xF29800F0
+#define	F367_OFDM_ERRCTRL1_3		0xF2980008
+#define	F367_OFDM_NUM_EVT1		0xF2980007
+
+/* ERRCNT1H */
+#define	R367_OFDM_ERRCNT1H		0xF299
+#define	F367_OFDM_ERRCNT1_OLDVALUE		0xF2990080
+#define	F367_OFDM_ERR_CNT1		0xF299007F
+
+/* ERRCNT1M */
+#define	R367_OFDM_ERRCNT1M		0xF29A
+#define	F367_OFDM_ERR_CNT1_HI		0xF29A00FF
+
+/* ERRCNT1L */
+#define	R367_OFDM_ERRCNT1L		0xF29B
+#define	F367_OFDM_ERR_CNT1_LO		0xF29B00FF
+
+/* ERRCTRL2 */
+#define	R367_OFDM_ERRCTRL2		0xF29C
+#define	F367_OFDM_ERR_SRC2		0xF29C00F0
+#define	F367_OFDM_ERRCTRL2_3		0xF29C0008
+#define	F367_OFDM_NUM_EVT2		0xF29C0007
+
+/* ERRCNT2H */
+#define	R367_OFDM_ERRCNT2H		0xF29D
+#define	F367_OFDM_ERRCNT2_OLDVALUE		0xF29D0080
+#define	F367_OFDM_ERR_CNT2_HI		0xF29D007F
+
+/* ERRCNT2M */
+#define	R367_OFDM_ERRCNT2M		0xF29E
+#define	F367_OFDM_ERR_CNT2_MED		0xF29E00FF
+
+/* ERRCNT2L */
+#define	R367_OFDM_ERRCNT2L		0xF29F
+#define	F367_OFDM_ERR_CNT2_LO		0xF29F00FF
+
+/* FECSPY */
+#define	R367_OFDM_FECSPY		0xF2A0
+#define	F367_OFDM_SPY_ENABLE		0xF2A00080
+#define	F367_OFDM_NO_SYNCBYTE		0xF2A00040
+#define	F367_OFDM_SERIAL_MODE		0xF2A00020
+#define	F367_OFDM_UNUSUAL_PACKET		0xF2A00010
+#define	F367_OFDM_BERMETER_DATAMODE		0xF2A0000C
+#define	F367_OFDM_BERMETER_LMODE		0xF2A00002
+#define	F367_OFDM_BERMETER_RESET		0xF2A00001
+
+/* FSPYCFG */
+#define	R367_OFDM_FSPYCFG		0xF2A1
+#define	F367_OFDM_FECSPY_INPUT		0xF2A100C0
+#define	F367_OFDM_RST_ON_ERROR		0xF2A10020
+#define	F367_OFDM_ONE_SHOT		0xF2A10010
+#define	F367_OFDM_I2C_MOD		0xF2A1000C
+#define	F367_OFDM_SPY_HYSTERESIS		0xF2A10003
+
+/* FSPYDATA */
+#define	R367_OFDM_FSPYDATA		0xF2A2
+#define	F367_OFDM_SPY_STUFFING		0xF2A20080
+#define	F367_OFDM_NOERROR_PKTJITTER		0xF2A20040
+#define	F367_OFDM_SPY_CNULLPKT		0xF2A20020
+#define	F367_OFDM_SPY_OUTDATA_MODE		0xF2A2001F
+
+/* FSPYOUT */
+#define	R367_OFDM_FSPYOUT		0xF2A3
+#define	F367_OFDM_FSPY_DIRECT		0xF2A30080
+#define	F367_OFDM_FSPYOUT_6		0xF2A30040
+#define	F367_OFDM_SPY_OUTDATA_BUS		0xF2A30038
+#define	F367_OFDM_STUFF_MODE		0xF2A30007
+
+/* FSTATUS */
+#define	R367_OFDM_FSTATUS		0xF2A4
+#define	F367_OFDM_SPY_ENDSIM		0xF2A40080
+#define	F367_OFDM_VALID_SIM		0xF2A40040
+#define	F367_OFDM_FOUND_SIGNAL		0xF2A40020
+#define	F367_OFDM_DSS_SYNCBYTE		0xF2A40010
+#define	F367_OFDM_RESULT_STATE		0xF2A4000F
+
+/* FGOODPACK */
+#define	R367_OFDM_FGOODPACK		0xF2A5
+#define	F367_OFDM_FGOOD_PACKET		0xF2A500FF
+
+/* FPACKCNT */
+#define	R367_OFDM_FPACKCNT		0xF2A6
+#define	F367_OFDM_FPACKET_COUNTER		0xF2A600FF
+
+/* FSPYMISC */
+#define	R367_OFDM_FSPYMISC		0xF2A7
+#define	F367_OFDM_FLABEL_COUNTER		0xF2A700FF
+
+/* FBERCPT4 */
+#define	R367_OFDM_FBERCPT4		0xF2A8
+#define	F367_OFDM_FBERMETER_CPT5		0xF2A800FF
+
+/* FBERCPT3 */
+#define	R367_OFDM_FBERCPT3		0xF2A9
+#define	F367_OFDM_FBERMETER_CPT4		0xF2A900FF
+
+/* FBERCPT2 */
+#define	R367_OFDM_FBERCPT2		0xF2AA
+#define	F367_OFDM_FBERMETER_CPT3		0xF2AA00FF
+
+/* FBERCPT1 */
+#define	R367_OFDM_FBERCPT1		0xF2AB
+#define	F367_OFDM_FBERMETER_CPT2		0xF2AB00FF
+
+/* FBERCPT0 */
+#define	R367_OFDM_FBERCPT0		0xF2AC
+#define	F367_OFDM_FBERMETER_CPT1		0xF2AC00FF
+
+/* FBERERR2 */
+#define	R367_OFDM_FBERERR2		0xF2AD
+#define	F367_OFDM_FBERMETER_ERR_HI		0xF2AD00FF
+
+/* FBERERR1 */
+#define	R367_OFDM_FBERERR1		0xF2AE
+#define	F367_OFDM_FBERMETER_ERR_MED		0xF2AE00FF
+
+/* FBERERR0 */
+#define	R367_OFDM_FBERERR0		0xF2AF
+#define	F367_OFDM_FBERMETER_ERR_LO		0xF2AF00FF
+
+/* FSTATESM */
+#define	R367_OFDM_FSTATESM		0xF2B0
+#define	F367_OFDM_RSTATE_F		0xF2B00080
+#define	F367_OFDM_RSTATE_E		0xF2B00040
+#define	F367_OFDM_RSTATE_D		0xF2B00020
+#define	F367_OFDM_RSTATE_C		0xF2B00010
+#define	F367_OFDM_RSTATE_B		0xF2B00008
+#define	F367_OFDM_RSTATE_A		0xF2B00004
+#define	F367_OFDM_RSTATE_9		0xF2B00002
+#define	F367_OFDM_RSTATE_8		0xF2B00001
+
+/* FSTATESL */
+#define	R367_OFDM_FSTATESL		0xF2B1
+#define	F367_OFDM_RSTATE_7		0xF2B10080
+#define	F367_OFDM_RSTATE_6		0xF2B10040
+#define	F367_OFDM_RSTATE_5		0xF2B10020
+#define	F367_OFDM_RSTATE_4		0xF2B10010
+#define	F367_OFDM_RSTATE_3		0xF2B10008
+#define	F367_OFDM_RSTATE_2		0xF2B10004
+#define	F367_OFDM_RSTATE_1		0xF2B10002
+#define	F367_OFDM_RSTATE_0		0xF2B10001
+
+/* FSPYBER */
+#define	R367_OFDM_FSPYBER		0xF2B2
+#define	F367_OFDM_FSPYBER_7		0xF2B20080
+#define	F367_OFDM_FSPYOBS_XORREAD		0xF2B20040
+#define	F367_OFDM_FSPYBER_OBSMODE		0xF2B20020
+#define	F367_OFDM_FSPYBER_SYNCBYTE		0xF2B20010
+#define	F367_OFDM_FSPYBER_UNSYNC		0xF2B20008
+#define	F367_OFDM_FSPYBER_CTIME		0xF2B20007
+
+/* FSPYDISTM */
+#define	R367_OFDM_FSPYDISTM		0xF2B3
+#define	F367_OFDM_PKTTIME_DISTANCE_HI		0xF2B300FF
+
+/* FSPYDISTL */
+#define	R367_OFDM_FSPYDISTL		0xF2B4
+#define	F367_OFDM_PKTTIME_DISTANCE_LO		0xF2B400FF
+
+/* FSPYOBS7 */
+#define	R367_OFDM_FSPYOBS7		0xF2B8
+#define	F367_OFDM_FSPYOBS_SPYFAIL		0xF2B80080
+#define	F367_OFDM_FSPYOBS_SPYFAIL1		0xF2B80040
+#define	F367_OFDM_FSPYOBS_ERROR		0xF2B80020
+#define	F367_OFDM_FSPYOBS_STROUT		0xF2B80010
+#define	F367_OFDM_FSPYOBS_RESULTSTATE1		0xF2B8000F
+
+/* FSPYOBS6 */
+#define	R367_OFDM_FSPYOBS6		0xF2B9
+#define	F367_OFDM_FSPYOBS_RESULTSTATE0		0xF2B900F0
+#define	F367_OFDM_FSPYOBS_RESULTSTATEM1		0xF2B9000F
+
+/* FSPYOBS5 */
+#define	R367_OFDM_FSPYOBS5		0xF2BA
+#define	F367_OFDM_FSPYOBS_BYTEOFPACKET1		0xF2BA00FF
+
+/* FSPYOBS4 */
+#define	R367_OFDM_FSPYOBS4		0xF2BB
+#define	F367_OFDM_FSPYOBS_BYTEVALUE1		0xF2BB00FF
+
+/* FSPYOBS3 */
+#define	R367_OFDM_FSPYOBS3		0xF2BC
+#define	F367_OFDM_FSPYOBS_DATA1		0xF2BC00FF
+
+/* FSPYOBS2 */
+#define	R367_OFDM_FSPYOBS2		0xF2BD
+#define	F367_OFDM_FSPYOBS_DATA0		0xF2BD00FF
+
+/* FSPYOBS1 */
+#define	R367_OFDM_FSPYOBS1		0xF2BE
+#define	F367_OFDM_FSPYOBS_DATAM1		0xF2BE00FF
+
+/* FSPYOBS0 */
+#define	R367_OFDM_FSPYOBS0		0xF2BF
+#define	F367_OFDM_FSPYOBS_DATAM2		0xF2BF00FF
+
+/* SFDEMAP */
+#define	R367_OFDM_SFDEMAP		0xF2C0
+#define	F367_OFDM_SFDEMAP_7		0xF2C00080
+#define	F367_OFDM_SFEC_K_DIVIDER_VIT		0xF2C0007F
+
+/* SFERROR */
+#define	R367_OFDM_SFERROR		0xF2C1
+#define	F367_OFDM_SFEC_REGERR_VIT		0xF2C100FF
+
+/* SFAVSR */
+#define	R367_OFDM_SFAVSR		0xF2C2
+#define	F367_OFDM_SFEC_SUMERRORS		0xF2C20080
+#define	F367_OFDM_SERROR_MAXMODE		0xF2C20040
+#define	F367_OFDM_SN_SFEC		0xF2C20030
+#define	F367_OFDM_KDIV_MODE_SFEC		0xF2C2000C
+#define	F367_OFDM_SFAVSR_1		0xF2C20002
+#define	F367_OFDM_SFAVSR_0		0xF2C20001
+
+/* SFECSTATUS */
+#define	R367_OFDM_SFECSTATUS		0xF2C3
+#define	F367_OFDM_SFEC_ON		0xF2C30080
+#define	F367_OFDM_SFSTATUS_6		0xF2C30040
+#define	F367_OFDM_SFSTATUS_5		0xF2C30020
+#define	F367_OFDM_SFSTATUS_4		0xF2C30010
+#define	F367_OFDM_LOCKEDSFEC		0xF2C30008
+#define	F367_OFDM_SFEC_DELOCK		0xF2C30004
+#define	F367_OFDM_SFEC_DEMODSEL1		0xF2C30002
+#define	F367_OFDM_SFEC_OVFON		0xF2C30001
+
+/* SFKDIV12 */
+#define	R367_OFDM_SFKDIV12		0xF2C4
+#define	F367_OFDM_SFECKDIV12_MAN		0xF2C40080
+#define	F367_OFDM_SFEC_K_DIVIDER_12		0xF2C4007F
+
+/* SFKDIV23 */
+#define	R367_OFDM_SFKDIV23		0xF2C5
+#define	F367_OFDM_SFECKDIV23_MAN		0xF2C50080
+#define	F367_OFDM_SFEC_K_DIVIDER_23		0xF2C5007F
+
+/* SFKDIV34 */
+#define	R367_OFDM_SFKDIV34		0xF2C6
+#define	F367_OFDM_SFECKDIV34_MAN		0xF2C60080
+#define	F367_OFDM_SFEC_K_DIVIDER_34		0xF2C6007F
+
+/* SFKDIV56 */
+#define	R367_OFDM_SFKDIV56		0xF2C7
+#define	F367_OFDM_SFECKDIV56_MAN		0xF2C70080
+#define	F367_OFDM_SFEC_K_DIVIDER_56		0xF2C7007F
+
+/* SFKDIV67 */
+#define	R367_OFDM_SFKDIV67		0xF2C8
+#define	F367_OFDM_SFECKDIV67_MAN		0xF2C80080
+#define	F367_OFDM_SFEC_K_DIVIDER_67		0xF2C8007F
+
+/* SFKDIV78 */
+#define	R367_OFDM_SFKDIV78		0xF2C9
+#define	F367_OFDM_SFECKDIV78_MAN		0xF2C90080
+#define	F367_OFDM_SFEC_K_DIVIDER_78		0xF2C9007F
+
+/* SFDILSTKM */
+#define	R367_OFDM_SFDILSTKM		0xF2CA
+#define	F367_OFDM_SFEC_PACKCPT		0xF2CA00E0
+#define	F367_OFDM_SFEC_DILSTK_HI		0xF2CA001F
+
+/* SFDILSTKL */
+#define	R367_OFDM_SFDILSTKL		0xF2CB
+#define	F367_OFDM_SFEC_DILSTK_LO		0xF2CB00FF
+
+/* SFSTATUS */
+#define	R367_OFDM_SFSTATUS		0xF2CC
+#define	F367_OFDM_SFEC_LINEOK		0xF2CC0080
+#define	F367_OFDM_SFEC_ERROR		0xF2CC0040
+#define	F367_OFDM_SFEC_DATA7		0xF2CC0020
+#define	F367_OFDM_SFEC_OVERFLOW		0xF2CC0010
+#define	F367_OFDM_SFEC_DEMODSEL2		0xF2CC0008
+#define	F367_OFDM_SFEC_NOSYNC		0xF2CC0004
+#define	F367_OFDM_SFEC_UNREGULA		0xF2CC0002
+#define	F367_OFDM_SFEC_READY		0xF2CC0001
+
+/* SFDLYH */
+#define	R367_OFDM_SFDLYH		0xF2CD
+#define	F367_OFDM_SFEC_TSTIMEVALID		0xF2CD0080
+#define	F367_OFDM_SFEC_SPEEDUP		0xF2CD0040
+#define	F367_OFDM_SFEC_STOP		0xF2CD0020
+#define	F367_OFDM_SFEC_REGULATED		0xF2CD0010
+#define	F367_OFDM_SFEC_REALSYMBOFFSET		0xF2CD000F
+
+/* SFDLYM */
+#define	R367_OFDM_SFDLYM		0xF2CE
+#define	F367_OFDM_SFEC_REALSYMBOFFSET_HI		0xF2CE00FF
+
+/* SFDLYL */
+#define	R367_OFDM_SFDLYL		0xF2CF
+#define	F367_OFDM_SFEC_REALSYMBOFFSET_LO		0xF2CF00FF
+
+/* SFDLYSETH */
+#define	R367_OFDM_SFDLYSETH		0xF2D0
+#define	F367_OFDM_SFEC_OFFSET		0xF2D000E0
+#define	F367_OFDM_SFECDLYSETH_4		0xF2D00010
+#define	F367_OFDM_RST_SFEC		0xF2D00008
+#define	F367_OFDM_SFECDLYSETH_2		0xF2D00004
+#define	F367_OFDM_SFEC_DISABLE		0xF2D00002
+#define	F367_OFDM_SFEC_UNREGUL		0xF2D00001
+
+/* SFDLYSETM */
+#define	R367_OFDM_SFDLYSETM		0xF2D1
+#define	F367_OFDM_SFECDLYSETM_7		0xF2D10080
+#define	F367_OFDM_SFEC_SYMBOFFSET_HI		0xF2D1007F
+
+/* SFDLYSETL */
+#define	R367_OFDM_SFDLYSETL		0xF2D2
+#define	F367_OFDM_SFEC_SYMBOFFSET_LO		0xF2D200FF
+
+/* SFOBSCFG */
+#define	R367_OFDM_SFOBSCFG		0xF2D3
+#define	F367_OFDM_SFEC_OBSCFG		0xF2D300FF
+
+/* SFOBSM */
+#define	R367_OFDM_SFOBSM		0xF2D4
+#define	F367_OFDM_SFEC_OBSDATA_HI		0xF2D400FF
+
+/* SFOBSL */
+#define	R367_OFDM_SFOBSL		0xF2D5
+#define	F367_OFDM_SFEC_OBSDATA_LO		0xF2D500FF
+
+/* SFECINFO */
+#define	R367_OFDM_SFECINFO		0xF2D6
+#define	F367_OFDM_SFECINFO_7		0xF2D60080
+#define	F367_OFDM_SFEC_SYNCDLSB		0xF2D60070
+#define	F367_OFDM_SFCE_S1CPHASE		0xF2D6000F
+
+/* SFERRCTRL */
+#define	R367_OFDM_SFERRCTRL		0xF2D8
+#define	F367_OFDM_SFEC_ERR_SOURCE		0xF2D800F0
+#define	F367_OFDM_SFERRCTRL_3		0xF2D80008
+#define	F367_OFDM_SFEC_NUM_EVENT		0xF2D80007
+
+/* SFERRCNTH */
+#define	R367_OFDM_SFERRCNTH		0xF2D9
+#define	F367_OFDM_SFERRC_OLDVALUE		0xF2D90080
+#define	F367_OFDM_SFEC_ERR_CNT		0xF2D9007F
+
+/* SFERRCNTM */
+#define	R367_OFDM_SFERRCNTM		0xF2DA
+#define	F367_OFDM_SFEC_ERR_CNT_HI		0xF2DA00FF
+
+/* SFERRCNTL */
+#define	R367_OFDM_SFERRCNTL		0xF2DB
+#define	F367_OFDM_SFEC_ERR_CNT_LO		0xF2DB00FF
+
+/* SYMBRATEM */
+#define	R367_OFDM_SYMBRATEM		0xF2E0
+#define	F367_OFDM_DEFGEN_SYMBRATE_HI		0xF2E000FF
+
+/* SYMBRATEL */
+#define	R367_OFDM_SYMBRATEL		0xF2E1
+#define	F367_OFDM_DEFGEN_SYMBRATE_LO		0xF2E100FF
+
+/* SYMBSTATUS */
+#define	R367_OFDM_SYMBSTATUS		0xF2E2
+#define	F367_OFDM_SYMBDLINE2_OFF		0xF2E20080
+#define	F367_OFDM_SDDL_REINIT1		0xF2E20040
+#define	F367_OFDM_SDD_REINIT1		0xF2E20020
+#define	F367_OFDM_TOKENID_ERROR		0xF2E20010
+#define	F367_OFDM_SYMBRATE_OVERFLOW		0xF2E20008
+#define	F367_OFDM_SYMBRATE_UNDERFLOW		0xF2E20004
+#define	F367_OFDM_TOKENID_RSTEVENT		0xF2E20002
+#define	F367_OFDM_TOKENID_RESET1		0xF2E20001
+
+/* SYMBCFG */
+#define	R367_OFDM_SYMBCFG		0xF2E3
+#define	F367_OFDM_SYMBCFG_7		0xF2E30080
+#define	F367_OFDM_SYMBCFG_6		0xF2E30040
+#define	F367_OFDM_SYMBCFG_5		0xF2E30020
+#define	F367_OFDM_SYMBCFG_4		0xF2E30010
+#define	F367_OFDM_SYMRATE_FSPEED		0xF2E3000C
+#define	F367_OFDM_SYMRATE_SSPEED		0xF2E30003
+
+/* SYMBFIFOM */
+#define	R367_OFDM_SYMBFIFOM		0xF2E4
+#define	F367_OFDM_SYMBFIFOM_7		0xF2E40080
+#define	F367_OFDM_SYMBFIFOM_6		0xF2E40040
+#define	F367_OFDM_DEFGEN_SYMFIFO_HI		0xF2E4003F
+
+/* SYMBFIFOL */
+#define	R367_OFDM_SYMBFIFOL		0xF2E5
+#define	F367_OFDM_DEFGEN_SYMFIFO_LO		0xF2E500FF
+
+/* SYMBOFFSM */
+#define	R367_OFDM_SYMBOFFSM		0xF2E6
+#define	F367_OFDM_TOKENID_RESET2		0xF2E60080
+#define	F367_OFDM_SDDL_REINIT2		0xF2E60040
+#define	F367_OFDM_SDD_REINIT2		0xF2E60020
+#define	F367_OFDM_SYMBOFFSM_4		0xF2E60010
+#define	F367_OFDM_SYMBOFFSM_3		0xF2E60008
+#define	F367_OFDM_DEFGEN_SYMBOFFSET_HI		0xF2E60007
+
+/* SYMBOFFSL */
+#define	R367_OFDM_SYMBOFFSL		0xF2E7
+#define	F367_OFDM_DEFGEN_SYMBOFFSET_LO		0xF2E700FF
+
+/* DEBUG_LT4 */
+#define	R367_DEBUG_LT4		0xF400
+#define	F367_F_DEBUG_LT4		0xF40000FF
+
+/* DEBUG_LT5 */
+#define	R367_DEBUG_LT5		0xF401
+#define	F367_F_DEBUG_LT5		0xF40100FF
+
+/* DEBUG_LT6 */
+#define	R367_DEBUG_LT6		0xF402
+#define	F367_F_DEBUG_LT6		0xF40200FF
+
+/* DEBUG_LT7 */
+#define	R367_DEBUG_LT7		0xF403
+#define	F367_F_DEBUG_LT7		0xF40300FF
+
+/* DEBUG_LT8 */
+#define	R367_DEBUG_LT8		0xF404
+#define	F367_F_DEBUG_LT8		0xF40400FF
+
+/* DEBUG_LT9 */
+#define	R367_DEBUG_LT9		0xF405
+#define	F367_F_DEBUG_LT9		0xF40500FF
+
+/* CTRL_1 */
+#define	R367_QAM_CTRL_1		0xF402
+#define	F367_QAM_SOFT_RST		0xF4020080
+#define	F367_QAM_EQU_RST		0xF4020008
+#define	F367_QAM_CRL_RST		0xF4020004
+#define	F367_QAM_TRL_RST		0xF4020002
+#define	F367_QAM_AGC_RST		0xF4020001
+
+/* CTRL_2 */
+#define	R367_QAM_CTRL_2		0xF403
+#define	F367_QAM_DEINT_RST		0xF4030008
+#define	F367_QAM_RS_RST		0xF4030004
+
+/* IT_STATUS1 */
+#define	R367_QAM_IT_STATUS1		0xF408
+#define	F367_QAM_SWEEP_OUT		0xF4080080
+#define	F367_QAM_FSM_CRL		0xF4080040
+#define	F367_QAM_CRL_LOCK		0xF4080020
+#define	F367_QAM_MFSM		0xF4080010
+#define	F367_QAM_TRL_LOCK		0xF4080008
+#define	F367_QAM_TRL_AGC_LIMIT		0xF4080004
+#define	F367_QAM_ADJ_AGC_LOCK		0xF4080002
+#define	F367_QAM_AGC_QAM_LOCK		0xF4080001
+
+/* IT_STATUS2 */
+#define	R367_QAM_IT_STATUS2		0xF409
+#define	F367_QAM_TSMF_CNT		0xF4090080
+#define	F367_QAM_TSMF_EOF		0xF4090040
+#define	F367_QAM_TSMF_RDY		0xF4090020
+#define	F367_QAM_FEC_NOCORR		0xF4090010
+#define	F367_QAM_SYNCSTATE		0xF4090008
+#define	F367_QAM_DEINT_LOCK		0xF4090004
+#define	F367_QAM_FADDING_FRZ		0xF4090002
+#define	F367_QAM_TAPMON_ALARM		0xF4090001
+
+/* IT_EN1 */
+#define	R367_QAM_IT_EN1		0xF40A
+#define	F367_QAM_SWEEP_OUTE		0xF40A0080
+#define	F367_QAM_FSM_CRLE		0xF40A0040
+#define	F367_QAM_CRL_LOCKE		0xF40A0020
+#define	F367_QAM_MFSME		0xF40A0010
+#define	F367_QAM_TRL_LOCKE		0xF40A0008
+#define	F367_QAM_TRL_AGC_LIMITE		0xF40A0004
+#define	F367_QAM_ADJ_AGC_LOCKE		0xF40A0002
+#define	F367_QAM_AGC_LOCKE		0xF40A0001
+
+/* IT_EN2 */
+#define	R367_QAM_IT_EN2		0xF40B
+#define	F367_QAM_TSMF_CNTE		0xF40B0080
+#define	F367_QAM_TSMF_EOFE		0xF40B0040
+#define	F367_QAM_TSMF_RDYE		0xF40B0020
+#define	F367_QAM_FEC_NOCORRE		0xF40B0010
+#define	F367_QAM_SYNCSTATEE		0xF40B0008
+#define	F367_QAM_DEINT_LOCKE		0xF40B0004
+#define	F367_QAM_FADDING_FRZE		0xF40B0002
+#define	F367_QAM_TAPMON_ALARME		0xF40B0001
+
+/* CTRL_STATUS */
+#define	R367_QAM_CTRL_STATUS		0xF40C
+#define	F367_QAM_QAMFEC_LOCK		0xF40C0004
+#define	F367_QAM_TSMF_LOCK		0xF40C0002
+#define	F367_QAM_TSMF_ERROR		0xF40C0001
+
+/* TEST_CTL */
+#define	R367_QAM_TEST_CTL		0xF40F
+#define	F367_QAM_TST_BLK_SEL		0xF40F0060
+#define	F367_QAM_TST_BUS_SEL		0xF40F001F
+
+/* AGC_CTL */
+#define	R367_QAM_AGC_CTL		0xF410
+#define	F367_QAM_AGC_LCK_TH		0xF41000F0
+#define	F367_QAM_AGC_ACCUMRSTSEL		0xF4100007
+
+/* AGC_IF_CFG */
+#define	R367_QAM_AGC_IF_CFG		0xF411
+#define	F367_QAM_AGC_IF_BWSEL		0xF41100F0
+#define	F367_QAM_AGC_IF_FREEZE		0xF4110002
+
+/* AGC_RF_CFG */
+#define	R367_QAM_AGC_RF_CFG		0xF412
+#define	F367_QAM_AGC_RF_BWSEL		0xF4120070
+#define	F367_QAM_AGC_RF_FREEZE		0xF4120002
+
+/* AGC_PWM_CFG */
+#define	R367_QAM_AGC_PWM_CFG		0xF413
+#define	F367_QAM_AGC_RF_PWM_TST		0xF4130080
+#define	F367_QAM_AGC_RF_PWM_INV		0xF4130040
+#define	F367_QAM_AGC_IF_PWM_TST		0xF4130008
+#define	F367_QAM_AGC_IF_PWM_INV		0xF4130004
+#define	F367_QAM_AGC_PWM_CLKDIV		0xF4130003
+
+/* AGC_PWR_REF_L */
+#define	R367_QAM_AGC_PWR_REF_L		0xF414
+#define	F367_QAM_AGC_PWRREF_LO		0xF41400FF
+
+/* AGC_PWR_REF_H */
+#define	R367_QAM_AGC_PWR_REF_H		0xF415
+#define	F367_QAM_AGC_PWRREF_HI		0xF4150003
+
+/* AGC_RF_TH_L */
+#define	R367_QAM_AGC_RF_TH_L		0xF416
+#define	F367_QAM_AGC_RF_TH_LO		0xF41600FF
+
+/* AGC_RF_TH_H */
+#define	R367_QAM_AGC_RF_TH_H		0xF417
+#define	F367_QAM_AGC_RF_TH_HI		0xF417000F
+
+/* AGC_IF_LTH_L */
+#define	R367_QAM_AGC_IF_LTH_L		0xF418
+#define	F367_QAM_AGC_IF_THLO_LO		0xF41800FF
+
+/* AGC_IF_LTH_H */
+#define	R367_QAM_AGC_IF_LTH_H		0xF419
+#define	F367_QAM_AGC_IF_THLO_HI		0xF419000F
+
+/* AGC_IF_HTH_L */
+#define	R367_QAM_AGC_IF_HTH_L		0xF41A
+#define	F367_QAM_AGC_IF_THHI_LO		0xF41A00FF
+
+/* AGC_IF_HTH_H */
+#define	R367_QAM_AGC_IF_HTH_H		0xF41B
+#define	F367_QAM_AGC_IF_THHI_HI		0xF41B000F
+
+/* AGC_PWR_RD_L */
+#define	R367_QAM_AGC_PWR_RD_L		0xF41C
+#define	F367_QAM_AGC_PWR_WORD_LO		0xF41C00FF
+
+/* AGC_PWR_RD_M */
+#define	R367_QAM_AGC_PWR_RD_M		0xF41D
+#define	F367_QAM_AGC_PWR_WORD_ME		0xF41D00FF
+
+/* AGC_PWR_RD_H */
+#define	R367_QAM_AGC_PWR_RD_H		0xF41E
+#define	F367_QAM_AGC_PWR_WORD_HI		0xF41E0003
+
+/* AGC_PWM_IFCMD_L */
+#define	R367_QAM_AGC_PWM_IFCMD_L		0xF420
+#define	F367_QAM_AGC_IF_PWMCMD_LO		0xF42000FF
+
+/* AGC_PWM_IFCMD_H */
+#define	R367_QAM_AGC_PWM_IFCMD_H		0xF421
+#define	F367_QAM_AGC_IF_PWMCMD_HI		0xF421000F
+
+/* AGC_PWM_RFCMD_L */
+#define	R367_QAM_AGC_PWM_RFCMD_L		0xF422
+#define	F367_QAM_AGC_RF_PWMCMD_LO		0xF42200FF
+
+/* AGC_PWM_RFCMD_H */
+#define	R367_QAM_AGC_PWM_RFCMD_H		0xF423
+#define	F367_QAM_AGC_RF_PWMCMD_HI		0xF423000F
+
+/* IQDEM_CFG */
+#define	R367_QAM_IQDEM_CFG		0xF424
+#define	F367_QAM_IQDEM_CLK_SEL		0xF4240004
+#define	F367_QAM_IQDEM_INVIQ		0xF4240002
+#define	F367_QAM_IQDEM_A2DTYPE		0xF4240001
+
+/* MIX_NCO_LL */
+#define	R367_QAM_MIX_NCO_LL		0xF425
+#define	F367_QAM_MIX_NCO_INC_LL		0xF42500FF
+
+/* MIX_NCO_HL */
+#define	R367_QAM_MIX_NCO_HL		0xF426
+#define	F367_QAM_MIX_NCO_INC_HL		0xF42600FF
+
+/* MIX_NCO_HH */
+#define	R367_QAM_MIX_NCO_HH		0xF427
+#define	F367_QAM_MIX_NCO_INVCNST		0xF4270080
+#define	F367_QAM_MIX_NCO_INC_HH		0xF427007F
+
+/* SRC_NCO_LL */
+#define	R367_QAM_SRC_NCO_LL		0xF428
+#define	F367_QAM_SRC_NCO_INC_LL		0xF42800FF
+
+/* SRC_NCO_LH */
+#define	R367_QAM_SRC_NCO_LH		0xF429
+#define	F367_QAM_SRC_NCO_INC_LH		0xF42900FF
+
+/* SRC_NCO_HL */
+#define	R367_QAM_SRC_NCO_HL		0xF42A
+#define	F367_QAM_SRC_NCO_INC_HL		0xF42A00FF
+
+/* SRC_NCO_HH */
+#define	R367_QAM_SRC_NCO_HH		0xF42B
+#define	F367_QAM_SRC_NCO_INC_HH		0xF42B007F
+
+/* IQDEM_GAIN_SRC_L */
+#define	R367_QAM_IQDEM_GAIN_SRC_L		0xF42C
+#define	F367_QAM_GAIN_SRC_LO		0xF42C00FF
+
+/* IQDEM_GAIN_SRC_H */
+#define	R367_QAM_IQDEM_GAIN_SRC_H		0xF42D
+#define	F367_QAM_GAIN_SRC_HI		0xF42D0003
+
+/* IQDEM_DCRM_CFG_LL */
+#define	R367_QAM_IQDEM_DCRM_CFG_LL		0xF430
+#define	F367_QAM_DCRM0_DCIN_L		0xF43000FF
+
+/* IQDEM_DCRM_CFG_LH */
+#define	R367_QAM_IQDEM_DCRM_CFG_LH		0xF431
+#define	F367_QAM_DCRM1_I_DCIN_L		0xF43100FC
+#define	F367_QAM_DCRM0_DCIN_H		0xF4310003
+
+/* IQDEM_DCRM_CFG_HL */
+#define	R367_QAM_IQDEM_DCRM_CFG_HL		0xF432
+#define	F367_QAM_DCRM1_Q_DCIN_L		0xF43200F0
+#define	F367_QAM_DCRM1_I_DCIN_H		0xF432000F
+
+/* IQDEM_DCRM_CFG_HH */
+#define	R367_QAM_IQDEM_DCRM_CFG_HH		0xF433
+#define	F367_QAM_DCRM1_FRZ		0xF4330080
+#define	F367_QAM_DCRM0_FRZ		0xF4330040
+#define	F367_QAM_DCRM1_Q_DCIN_H		0xF433003F
+
+/* IQDEM_ADJ_COEFF0 */
+#define	R367_QAM_IQDEM_ADJ_COEFF0		0xF434
+#define	F367_QAM_ADJIIR_COEFF10_L		0xF43400FF
+
+/* IQDEM_ADJ_COEFF1 */
+#define	R367_QAM_IQDEM_ADJ_COEFF1		0xF435
+#define	F367_QAM_ADJIIR_COEFF11_L		0xF43500FC
+#define	F367_QAM_ADJIIR_COEFF10_H		0xF4350003
+
+/* IQDEM_ADJ_COEFF2 */
+#define	R367_QAM_IQDEM_ADJ_COEFF2		0xF436
+#define	F367_QAM_ADJIIR_COEFF12_L		0xF43600F0
+#define	F367_QAM_ADJIIR_COEFF11_H		0xF436000F
+
+/* IQDEM_ADJ_COEFF3 */
+#define	R367_QAM_IQDEM_ADJ_COEFF3		0xF437
+#define	F367_QAM_ADJIIR_COEFF20_L		0xF43700C0
+#define	F367_QAM_ADJIIR_COEFF12_H		0xF437003F
+
+/* IQDEM_ADJ_COEFF4 */
+#define	R367_QAM_IQDEM_ADJ_COEFF4		0xF438
+#define	F367_QAM_ADJIIR_COEFF20_H		0xF43800FF
+
+/* IQDEM_ADJ_COEFF5 */
+#define	R367_QAM_IQDEM_ADJ_COEFF5		0xF439
+#define	F367_QAM_ADJIIR_COEFF21_L		0xF43900FF
+
+/* IQDEM_ADJ_COEFF6 */
+#define	R367_QAM_IQDEM_ADJ_COEFF6		0xF43A
+#define	F367_QAM_ADJIIR_COEFF22_L		0xF43A00FC
+#define	F367_QAM_ADJIIR_COEFF21_H		0xF43A0003
+
+/* IQDEM_ADJ_COEFF7 */
+#define	R367_QAM_IQDEM_ADJ_COEFF7		0xF43B
+#define	F367_QAM_ADJIIR_COEFF22_H		0xF43B000F
+
+/* IQDEM_ADJ_EN */
+#define	R367_QAM_IQDEM_ADJ_EN		0xF43C
+#define	F367_QAM_ALLPASSFILT_EN		0xF43C0008
+#define	F367_QAM_ADJ_AGC_EN		0xF43C0004
+#define	F367_QAM_ADJ_COEFF_FRZ		0xF43C0002
+#define	F367_QAM_ADJ_EN		0xF43C0001
+
+/* IQDEM_ADJ_AGC_REF */
+#define	R367_QAM_IQDEM_ADJ_AGC_REF		0xF43D
+#define	F367_QAM_ADJ_AGC_REF		0xF43D00FF
+
+/* ALLPASSFILT1 */
+#define	R367_QAM_ALLPASSFILT1		0xF440
+#define	F367_QAM_ALLPASSFILT_COEFF1_LO		0xF44000FF
+
+/* ALLPASSFILT2 */
+#define	R367_QAM_ALLPASSFILT2		0xF441
+#define	F367_QAM_ALLPASSFILT_COEFF1_ME		0xF44100FF
+
+/* ALLPASSFILT3 */
+#define	R367_QAM_ALLPASSFILT3		0xF442
+#define	F367_QAM_ALLPASSFILT_COEFF2_LO		0xF44200C0
+#define	F367_QAM_ALLPASSFILT_COEFF1_HI		0xF442003F
+
+/* ALLPASSFILT4 */
+#define	R367_QAM_ALLPASSFILT4		0xF443
+#define	F367_QAM_ALLPASSFILT_COEFF2_MEL		0xF44300FF
+
+/* ALLPASSFILT5 */
+#define	R367_QAM_ALLPASSFILT5		0xF444
+#define	F367_QAM_ALLPASSFILT_COEFF2_MEH		0xF44400FF
+
+/* ALLPASSFILT6 */
+#define	R367_QAM_ALLPASSFILT6		0xF445
+#define	F367_QAM_ALLPASSFILT_COEFF3_LO		0xF44500F0
+#define	F367_QAM_ALLPASSFILT_COEFF2_HI		0xF445000F
+
+/* ALLPASSFILT7 */
+#define	R367_QAM_ALLPASSFILT7		0xF446
+#define	F367_QAM_ALLPASSFILT_COEFF3_MEL		0xF44600FF
+
+/* ALLPASSFILT8 */
+#define	R367_QAM_ALLPASSFILT8		0xF447
+#define	F367_QAM_ALLPASSFILT_COEFF3_MEH		0xF44700FF
+
+/* ALLPASSFILT9 */
+#define	R367_QAM_ALLPASSFILT9		0xF448
+#define	F367_QAM_ALLPASSFILT_COEFF4_LO		0xF44800FC
+#define	F367_QAM_ALLPASSFILT_COEFF3_HI		0xF4480003
+
+/* ALLPASSFILT10 */
+#define	R367_QAM_ALLPASSFILT10		0xF449
+#define	F367_QAM_ALLPASSFILT_COEFF4_ME		0xF44900FF
+
+/* ALLPASSFILT11 */
+#define	R367_QAM_ALLPASSFILT11		0xF44A
+#define	F367_QAM_ALLPASSFILT_COEFF4_HI		0xF44A00FF
+
+/* TRL_AGC_CFG */
+#define	R367_QAM_TRL_AGC_CFG		0xF450
+#define	F367_QAM_TRL_AGC_FREEZE		0xF4500080
+#define	F367_QAM_TRL_AGC_REF		0xF450007F
+
+/* TRL_LPF_CFG */
+#define	R367_QAM_TRL_LPF_CFG		0xF454
+#define	F367_QAM_NYQPOINT_INV		0xF4540040
+#define	F367_QAM_TRL_SHIFT		0xF4540030
+#define	F367_QAM_NYQ_COEFF_SEL		0xF454000C
+#define	F367_QAM_TRL_LPF_FREEZE		0xF4540002
+#define	F367_QAM_TRL_LPF_CRT		0xF4540001
+
+/* TRL_LPF_ACQ_GAIN */
+#define	R367_QAM_TRL_LPF_ACQ_GAIN		0xF455
+#define	F367_QAM_TRL_GDIR_ACQ		0xF4550070
+#define	F367_QAM_TRL_GINT_ACQ		0xF4550007
+
+/* TRL_LPF_TRK_GAIN */
+#define	R367_QAM_TRL_LPF_TRK_GAIN		0xF456
+#define	F367_QAM_TRL_GDIR_TRK		0xF4560070
+#define	F367_QAM_TRL_GINT_TRK		0xF4560007
+
+/* TRL_LPF_OUT_GAIN */
+#define	R367_QAM_TRL_LPF_OUT_GAIN		0xF457
+#define	F367_QAM_TRL_GAIN_OUT		0xF4570007
+
+/* TRL_LOCKDET_LTH */
+#define	R367_QAM_TRL_LOCKDET_LTH		0xF458
+#define	F367_QAM_TRL_LCK_THLO		0xF4580007
+
+/* TRL_LOCKDET_HTH */
+#define	R367_QAM_TRL_LOCKDET_HTH		0xF459
+#define	F367_QAM_TRL_LCK_THHI		0xF45900FF
+
+/* TRL_LOCKDET_TRGVAL */
+#define	R367_QAM_TRL_LOCKDET_TRGVAL		0xF45A
+#define	F367_QAM_TRL_LCK_TRG		0xF45A00FF
+
+/* IQ_QAM */
+#define	R367_QAM_IQ_QAM		0xF45C
+#define	F367_QAM_IQ_INPUT		0xF45C0008
+#define	F367_QAM_DETECT_MODE		0xF45C0007
+
+/* FSM_STATE */
+#define	R367_QAM_FSM_STATE		0xF460
+#define	F367_QAM_CRL_DFE		0xF4600080
+#define	F367_QAM_DFE_START		0xF4600040
+#define	F367_QAM_CTRLG_START		0xF4600030
+#define	F367_QAM_FSM_FORCESTATE		0xF460000F
+
+/* FSM_CTL */
+#define	R367_QAM_FSM_CTL		0xF461
+#define	F367_QAM_FEC2_EN		0xF4610040
+#define	F367_QAM_SIT_EN		0xF4610020
+#define	F367_QAM_TRL_AHEAD		0xF4610010
+#define	F367_QAM_TRL2_EN		0xF4610008
+#define	F367_QAM_FSM_EQA1_EN		0xF4610004
+#define	F367_QAM_FSM_BKP_DIS		0xF4610002
+#define	F367_QAM_FSM_FORCE_EN		0xF4610001
+
+/* FSM_STS */
+#define	R367_QAM_FSM_STS		0xF462
+#define	F367_QAM_FSM_STATUS		0xF462000F
+
+/* FSM_SNR0_HTH */
+#define	R367_QAM_FSM_SNR0_HTH		0xF463
+#define	F367_QAM_SNR0_HTH		0xF46300FF
+
+/* FSM_SNR1_HTH */
+#define	R367_QAM_FSM_SNR1_HTH		0xF464
+#define	F367_QAM_SNR1_HTH		0xF46400FF
+
+/* FSM_SNR2_HTH */
+#define	R367_QAM_FSM_SNR2_HTH		0xF465
+#define	F367_QAM_SNR2_HTH		0xF46500FF
+
+/* FSM_SNR0_LTH */
+#define	R367_QAM_FSM_SNR0_LTH		0xF466
+#define	F367_QAM_SNR0_LTH		0xF46600FF
+
+/* FSM_SNR1_LTH */
+#define	R367_QAM_FSM_SNR1_LTH		0xF467
+#define	F367_QAM_SNR1_LTH		0xF46700FF
+
+/* FSM_EQA1_HTH */
+#define	R367_QAM_FSM_EQA1_HTH		0xF468
+#define	F367_QAM_SNR3_HTH_LO		0xF46800F0
+#define	F367_QAM_EQA1_HTH		0xF468000F
+
+/* FSM_TEMPO */
+#define	R367_QAM_FSM_TEMPO		0xF469
+#define	F367_QAM_SIT		0xF46900C0
+#define	F367_QAM_WST		0xF4690038
+#define	F367_QAM_ELT		0xF4690006
+#define	F367_QAM_SNR3_HTH_HI		0xF4690001
+
+/* FSM_CONFIG */
+#define	R367_QAM_FSM_CONFIG		0xF46A
+#define	F367_QAM_FEC2_DFEOFF		0xF46A0004
+#define	F367_QAM_PRIT_STATE		0xF46A0002
+#define	F367_QAM_MODMAP_STATE		0xF46A0001
+
+/* EQU_I_TESTTAP_L */
+#define	R367_QAM_EQU_I_TESTTAP_L		0xF474
+#define	F367_QAM_I_TEST_TAP_L		0xF47400FF
+
+/* EQU_I_TESTTAP_M */
+#define	R367_QAM_EQU_I_TESTTAP_M		0xF475
+#define	F367_QAM_I_TEST_TAP_M		0xF47500FF
+
+/* EQU_I_TESTTAP_H */
+#define	R367_QAM_EQU_I_TESTTAP_H		0xF476
+#define	F367_QAM_I_TEST_TAP_H		0xF476001F
+
+/* EQU_TESTAP_CFG */
+#define	R367_QAM_EQU_TESTAP_CFG		0xF477
+#define	F367_QAM_TEST_FFE_DFE_SEL		0xF4770040
+#define	F367_QAM_TEST_TAP_SELECT		0xF477003F
+
+/* EQU_Q_TESTTAP_L */
+#define	R367_QAM_EQU_Q_TESTTAP_L		0xF478
+#define	F367_QAM_Q_TEST_TAP_L		0xF47800FF
+
+/* EQU_Q_TESTTAP_M */
+#define	R367_QAM_EQU_Q_TESTTAP_M		0xF479
+#define	F367_QAM_Q_TEST_TAP_M		0xF47900FF
+
+/* EQU_Q_TESTTAP_H */
+#define	R367_QAM_EQU_Q_TESTTAP_H		0xF47A
+#define	F367_QAM_Q_TEST_TAP_H		0xF47A001F
+
+/* EQU_TAP_CTRL */
+#define	R367_QAM_EQU_TAP_CTRL		0xF47B
+#define	F367_QAM_MTAP_FRZ		0xF47B0010
+#define	F367_QAM_PRE_FREEZE		0xF47B0008
+#define	F367_QAM_DFE_TAPMON_EN		0xF47B0004
+#define	F367_QAM_FFE_TAPMON_EN		0xF47B0002
+#define	F367_QAM_MTAP_ONLY		0xF47B0001
+
+/* EQU_CTR_CRL_CONTROL_L */
+#define	R367_QAM_EQU_CTR_CRL_CONTROL_L		0xF47C
+#define	F367_QAM_EQU_CTR_CRL_CONTROL_LO		0xF47C00FF
+
+/* EQU_CTR_CRL_CONTROL_H */
+#define	R367_QAM_EQU_CTR_CRL_CONTROL_H		0xF47D
+#define	F367_QAM_EQU_CTR_CRL_CONTROL_HI		0xF47D00FF
+
+/* EQU_CTR_HIPOW_L */
+#define	R367_QAM_EQU_CTR_HIPOW_L		0xF47E
+#define	F367_QAM_CTR_HIPOW_L		0xF47E00FF
+
+/* EQU_CTR_HIPOW_H */
+#define	R367_QAM_EQU_CTR_HIPOW_H		0xF47F
+#define	F367_QAM_CTR_HIPOW_H		0xF47F00FF
+
+/* EQU_I_EQU_LO */
+#define	R367_QAM_EQU_I_EQU_LO		0xF480
+#define	F367_QAM_EQU_I_EQU_L		0xF48000FF
+
+/* EQU_I_EQU_HI */
+#define	R367_QAM_EQU_I_EQU_HI		0xF481
+#define	F367_QAM_EQU_I_EQU_H		0xF4810003
+
+/* EQU_Q_EQU_LO */
+#define	R367_QAM_EQU_Q_EQU_LO		0xF482
+#define	F367_QAM_EQU_Q_EQU_L		0xF48200FF
+
+/* EQU_Q_EQU_HI */
+#define	R367_QAM_EQU_Q_EQU_HI		0xF483
+#define	F367_QAM_EQU_Q_EQU_H		0xF4830003
+
+/* EQU_MAPPER */
+#define	R367_QAM_EQU_MAPPER		0xF484
+#define	F367_QAM_QUAD_AUTO		0xF4840080
+#define	F367_QAM_QUAD_INV		0xF4840040
+#define	F367_QAM_QAM_MODE		0xF4840007
+
+/* EQU_SWEEP_RATE */
+#define	R367_QAM_EQU_SWEEP_RATE		0xF485
+#define	F367_QAM_SNR_PER		0xF48500C0
+#define	F367_QAM_SWEEP_RATE		0xF485003F
+
+/* EQU_SNR_LO */
+#define	R367_QAM_EQU_SNR_LO		0xF486
+#define	F367_QAM_SNR_LO		0xF48600FF
+
+/* EQU_SNR_HI */
+#define	R367_QAM_EQU_SNR_HI		0xF487
+#define	F367_QAM_SNR_HI		0xF48700FF
+
+/* EQU_GAMMA_LO */
+#define	R367_QAM_EQU_GAMMA_LO		0xF488
+#define	F367_QAM_GAMMA_LO		0xF48800FF
+
+/* EQU_GAMMA_HI */
+#define	R367_QAM_EQU_GAMMA_HI		0xF489
+#define	F367_QAM_GAMMA_ME		0xF48900FF
+
+/* EQU_ERR_GAIN */
+#define	R367_QAM_EQU_ERR_GAIN		0xF48A
+#define	F367_QAM_EQA1MU		0xF48A0070
+#define	F367_QAM_CRL2MU		0xF48A000E
+#define	F367_QAM_GAMMA_HI		0xF48A0001
+
+/* EQU_RADIUS */
+#define	R367_QAM_EQU_RADIUS		0xF48B
+#define	F367_QAM_RADIUS		0xF48B00FF
+
+/* EQU_FFE_MAINTAP */
+#define	R367_QAM_EQU_FFE_MAINTAP		0xF48C
+#define	F367_QAM_FFE_MAINTAP_INIT		0xF48C00FF
+
+/* EQU_FFE_LEAKAGE */
+#define	R367_QAM_EQU_FFE_LEAKAGE		0xF48E
+#define	F367_QAM_LEAK_PER		0xF48E00F0
+#define	F367_QAM_EQU_OUTSEL		0xF48E0002
+#define	F367_QAM_PNT2DFE		0xF48E0001
+
+/* EQU_FFE_MAINTAP_POS */
+#define	R367_QAM_EQU_FFE_MAINTAP_POS		0xF48F
+#define	F367_QAM_FFE_LEAK_EN		0xF48F0080
+#define	F367_QAM_DFE_LEAK_EN		0xF48F0040
+#define	F367_QAM_FFE_MAINTAP_POS		0xF48F003F
+
+/* EQU_GAIN_WIDE */
+#define	R367_QAM_EQU_GAIN_WIDE		0xF490
+#define	F367_QAM_DFE_GAIN_WIDE		0xF49000F0
+#define	F367_QAM_FFE_GAIN_WIDE		0xF490000F
+
+/* EQU_GAIN_NARROW */
+#define	R367_QAM_EQU_GAIN_NARROW		0xF491
+#define	F367_QAM_DFE_GAIN_NARROW		0xF49100F0
+#define	F367_QAM_FFE_GAIN_NARROW		0xF491000F
+
+/* EQU_CTR_LPF_GAIN */
+#define	R367_QAM_EQU_CTR_LPF_GAIN		0xF492
+#define	F367_QAM_CTR_GTO		0xF4920080
+#define	F367_QAM_CTR_GDIR		0xF4920070
+#define	F367_QAM_SWEEP_EN		0xF4920008
+#define	F367_QAM_CTR_GINT		0xF4920007
+
+/* EQU_CRL_LPF_GAIN */
+#define	R367_QAM_EQU_CRL_LPF_GAIN		0xF493
+#define	F367_QAM_CRL_GTO		0xF4930080
+#define	F367_QAM_CRL_GDIR		0xF4930070
+#define	F367_QAM_SWEEP_DIR		0xF4930008
+#define	F367_QAM_CRL_GINT		0xF4930007
+
+/* EQU_GLOBAL_GAIN */
+#define	R367_QAM_EQU_GLOBAL_GAIN		0xF494
+#define	F367_QAM_CRL_GAIN		0xF49400F8
+#define	F367_QAM_CTR_INC_GAIN		0xF4940004
+#define	F367_QAM_CTR_FRAC		0xF4940003
+
+/* EQU_CRL_LD_SEN */
+#define	R367_QAM_EQU_CRL_LD_SEN		0xF495
+#define	F367_QAM_CTR_BADPOINT_EN		0xF4950080
+#define	F367_QAM_CTR_GAIN		0xF4950070
+#define	F367_QAM_LIMANEN		0xF4950008
+#define	F367_QAM_CRL_LD_SEN		0xF4950007
+
+/* EQU_CRL_LD_VAL */
+#define	R367_QAM_EQU_CRL_LD_VAL		0xF496
+#define	F367_QAM_CRL_BISTH_LIMIT		0xF4960080
+#define	F367_QAM_CARE_EN		0xF4960040
+#define	F367_QAM_CRL_LD_PER		0xF4960030
+#define	F367_QAM_CRL_LD_WST		0xF496000C
+#define	F367_QAM_CRL_LD_TFS		0xF4960003
+
+/* EQU_CRL_TFR */
+#define	R367_QAM_EQU_CRL_TFR		0xF497
+#define	F367_QAM_CRL_LD_TFR		0xF49700FF
+
+/* EQU_CRL_BISTH_LO */
+#define	R367_QAM_EQU_CRL_BISTH_LO		0xF498
+#define	F367_QAM_CRL_BISTH_LO		0xF49800FF
+
+/* EQU_CRL_BISTH_HI */
+#define	R367_QAM_EQU_CRL_BISTH_HI		0xF499
+#define	F367_QAM_CRL_BISTH_HI		0xF49900FF
+
+/* EQU_SWEEP_RANGE_LO */
+#define	R367_QAM_EQU_SWEEP_RANGE_LO		0xF49A
+#define	F367_QAM_SWEEP_RANGE_LO		0xF49A00FF
+
+/* EQU_SWEEP_RANGE_HI */
+#define	R367_QAM_EQU_SWEEP_RANGE_HI		0xF49B
+#define	F367_QAM_SWEEP_RANGE_HI		0xF49B00FF
+
+/* EQU_CRL_LIMITER */
+#define	R367_QAM_EQU_CRL_LIMITER		0xF49C
+#define	F367_QAM_BISECTOR_EN		0xF49C0080
+#define	F367_QAM_PHEST128_EN		0xF49C0040
+#define	F367_QAM_CRL_LIM		0xF49C003F
+
+/* EQU_MODULUS_MAP */
+#define	R367_QAM_EQU_MODULUS_MAP		0xF49D
+#define	F367_QAM_PNT_DEPTH		0xF49D00E0
+#define	F367_QAM_MODULUS_CMP		0xF49D001F
+
+/* EQU_PNT_GAIN */
+#define	R367_QAM_EQU_PNT_GAIN		0xF49E
+#define	F367_QAM_PNT_EN		0xF49E0080
+#define	F367_QAM_MODULUSMAP_EN		0xF49E0040
+#define	F367_QAM_PNT_GAIN		0xF49E003F
+
+/* FEC_AC_CTR_0 */
+#define	R367_QAM_FEC_AC_CTR_0		0xF4A8
+#define	F367_QAM_BE_BYPASS		0xF4A80020
+#define	F367_QAM_REFRESH47		0xF4A80010
+#define	F367_QAM_CT_NBST		0xF4A80008
+#define	F367_QAM_TEI_ENA		0xF4A80004
+#define	F367_QAM_DS_ENA		0xF4A80002
+#define	F367_QAM_TSMF_EN		0xF4A80001
+
+/* FEC_AC_CTR_1 */
+#define	R367_QAM_FEC_AC_CTR_1		0xF4A9
+#define	F367_QAM_DEINT_DEPTH		0xF4A900FF
+
+/* FEC_AC_CTR_2 */
+#define	R367_QAM_FEC_AC_CTR_2		0xF4AA
+#define	F367_QAM_DEINT_M		0xF4AA00F8
+#define	F367_QAM_DIS_UNLOCK		0xF4AA0004
+#define	F367_QAM_DESCR_MODE		0xF4AA0003
+
+/* FEC_AC_CTR_3 */
+#define	R367_QAM_FEC_AC_CTR_3		0xF4AB
+#define	F367_QAM_DI_UNLOCK		0xF4AB0080
+#define	F367_QAM_DI_FREEZE		0xF4AB0040
+#define	F367_QAM_MISMATCH		0xF4AB0030
+#define	F367_QAM_ACQ_MODE		0xF4AB000C
+#define	F367_QAM_TRK_MODE		0xF4AB0003
+
+/* FEC_STATUS */
+#define	R367_QAM_FEC_STATUS		0xF4AC
+#define	F367_QAM_DEINT_SMCNTR		0xF4AC00E0
+#define	F367_QAM_DEINT_SYNCSTATE		0xF4AC0018
+#define	F367_QAM_DEINT_SYNLOST		0xF4AC0004
+#define	F367_QAM_DESCR_SYNCSTATE		0xF4AC0002
+
+/* RS_COUNTER_0 */
+#define	R367_QAM_RS_COUNTER_0		0xF4AE
+#define	F367_QAM_BK_CT_L		0xF4AE00FF
+
+/* RS_COUNTER_1 */
+#define	R367_QAM_RS_COUNTER_1		0xF4AF
+#define	F367_QAM_BK_CT_H		0xF4AF00FF
+
+/* RS_COUNTER_2 */
+#define	R367_QAM_RS_COUNTER_2		0xF4B0
+#define	F367_QAM_CORR_CT_L		0xF4B000FF
+
+/* RS_COUNTER_3 */
+#define	R367_QAM_RS_COUNTER_3		0xF4B1
+#define	F367_QAM_CORR_CT_H		0xF4B100FF
+
+/* RS_COUNTER_4 */
+#define	R367_QAM_RS_COUNTER_4		0xF4B2
+#define	F367_QAM_UNCORR_CT_L		0xF4B200FF
+
+/* RS_COUNTER_5 */
+#define	R367_QAM_RS_COUNTER_5		0xF4B3
+#define	F367_QAM_UNCORR_CT_H		0xF4B300FF
+
+/* BERT_0 */
+#define	R367_QAM_BERT_0		0xF4B4
+#define	F367_QAM_RS_NOCORR		0xF4B40004
+#define	F367_QAM_CT_HOLD		0xF4B40002
+#define	F367_QAM_CT_CLEAR		0xF4B40001
+
+/* BERT_1 */
+#define	R367_QAM_BERT_1		0xF4B5
+#define	F367_QAM_BERT_ON		0xF4B50020
+#define	F367_QAM_BERT_ERR_SRC		0xF4B50010
+#define	F367_QAM_BERT_ERR_MODE		0xF4B50008
+#define	F367_QAM_BERT_NBYTE		0xF4B50007
+
+/* BERT_2 */
+#define	R367_QAM_BERT_2		0xF4B6
+#define	F367_QAM_BERT_ERRCOUNT_L		0xF4B600FF
+
+/* BERT_3 */
+#define	R367_QAM_BERT_3		0xF4B7
+#define	F367_QAM_BERT_ERRCOUNT_H		0xF4B700FF
+
+/* OUTFORMAT_0 */
+#define	R367_QAM_OUTFORMAT_0		0xF4B8
+#define	F367_QAM_CLK_POLARITY		0xF4B80080
+#define	F367_QAM_FEC_TYPE		0xF4B80040
+#define	F367_QAM_SYNC_STRIP		0xF4B80008
+#define	F367_QAM_TS_SWAP		0xF4B80004
+#define	F367_QAM_OUTFORMAT		0xF4B80003
+
+/* OUTFORMAT_1 */
+#define	R367_QAM_OUTFORMAT_1		0xF4B9
+#define	F367_QAM_CI_DIVRANGE		0xF4B900FF
+
+/* SMOOTHER_2 */
+#define	R367_QAM_SMOOTHER_2		0xF4BE
+#define	F367_QAM_FIFO_BYPASS		0xF4BE0020
+
+/* TSMF_CTRL_0 */
+#define	R367_QAM_TSMF_CTRL_0		0xF4C0
+#define	F367_QAM_TS_NUMBER		0xF4C0001E
+#define	F367_QAM_SEL_MODE		0xF4C00001
+
+/* TSMF_CTRL_1 */
+#define	R367_QAM_TSMF_CTRL_1		0xF4C1
+#define	F367_QAM_CHECK_ERROR_BIT		0xF4C10080
+#define	F367_QAM_CHCK_F_SYNC		0xF4C10040
+#define	F367_QAM_H_MODE		0xF4C10008
+#define	F367_QAM_D_V_MODE		0xF4C10004
+#define	F367_QAM_MODE		0xF4C10003
+
+/* TSMF_CTRL_3 */
+#define	R367_QAM_TSMF_CTRL_3		0xF4C3
+#define	F367_QAM_SYNC_IN_COUNT		0xF4C300F0
+#define	F367_QAM_SYNC_OUT_COUNT		0xF4C3000F
+
+/* TS_ON_ID_0 */
+#define	R367_QAM_TS_ON_ID_0		0xF4C4
+#define	F367_QAM_TS_ID_L		0xF4C400FF
+
+/* TS_ON_ID_1 */
+#define	R367_QAM_TS_ON_ID_1		0xF4C5
+#define	F367_QAM_TS_ID_H		0xF4C500FF
+
+/* TS_ON_ID_2 */
+#define	R367_QAM_TS_ON_ID_2		0xF4C6
+#define	F367_QAM_ON_ID_L		0xF4C600FF
+
+/* TS_ON_ID_3 */
+#define	R367_QAM_TS_ON_ID_3		0xF4C7
+#define	F367_QAM_ON_ID_H		0xF4C700FF
+
+/* RE_STATUS_0 */
+#define	R367_QAM_RE_STATUS_0		0xF4C8
+#define	F367_QAM_RECEIVE_STATUS_L		0xF4C800FF
+
+/* RE_STATUS_1 */
+#define	R367_QAM_RE_STATUS_1		0xF4C9
+#define	F367_QAM_RECEIVE_STATUS_LH		0xF4C900FF
+
+/* RE_STATUS_2 */
+#define	R367_QAM_RE_STATUS_2		0xF4CA
+#define	F367_QAM_RECEIVE_STATUS_HL		0xF4CA00FF
+
+/* RE_STATUS_3 */
+#define	R367_QAM_RE_STATUS_3		0xF4CB
+#define	F367_QAM_RECEIVE_STATUS_HH		0xF4CB003F
+
+/* TS_STATUS_0 */
+#define	R367_QAM_TS_STATUS_0		0xF4CC
+#define	F367_QAM_TS_STATUS_L		0xF4CC00FF
+
+/* TS_STATUS_1 */
+#define	R367_QAM_TS_STATUS_1		0xF4CD
+#define	F367_QAM_TS_STATUS_H		0xF4CD007F
+
+/* TS_STATUS_2 */
+#define	R367_QAM_TS_STATUS_2		0xF4CE
+#define	F367_QAM_ERROR		0xF4CE0080
+#define	F367_QAM_EMERGENCY		0xF4CE0040
+#define	F367_QAM_CRE_TS		0xF4CE0030
+#define	F367_QAM_VER		0xF4CE000E
+#define	F367_QAM_M_LOCK		0xF4CE0001
+
+/* TS_STATUS_3 */
+#define	R367_QAM_TS_STATUS_3		0xF4CF
+#define	F367_QAM_UPDATE_READY		0xF4CF0080
+#define	F367_QAM_END_FRAME_HEADER		0xF4CF0040
+#define	F367_QAM_CONTCNT		0xF4CF0020
+#define	F367_QAM_TS_IDENTIFIER_SEL		0xF4CF000F
+
+/* T_O_ID_0 */
+#define	R367_QAM_T_O_ID_0		0xF4D0
+#define	F367_QAM_ON_ID_I_L		0xF4D000FF
+
+/* T_O_ID_1 */
+#define	R367_QAM_T_O_ID_1		0xF4D1
+#define	F367_QAM_ON_ID_I_H		0xF4D100FF
+
+/* T_O_ID_2 */
+#define	R367_QAM_T_O_ID_2		0xF4D2
+#define	F367_QAM_TS_ID_I_L		0xF4D200FF
+
+/* T_O_ID_3 */
+#define	R367_QAM_T_O_ID_3		0xF4D3
+#define	F367_QAM_TS_ID_I_H		0xF4D300FF
+
+#endif
-- 
1.8.4.2

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

* [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (2 preceding siblings ...)
  2013-11-03  0:28 ` [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator Maik Broemme
@ 2013-11-03  0:31 ` Maik Broemme
  2013-11-03  9:56   ` Mauro Carvalho Chehab
  2013-11-03  0:32 ` [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2 Maik Broemme
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:31 UTC (permalink / raw)
  To: Linux Media Mailing List

Added support for the NXP TDA18212 silicon tuner used by recent
Digital Devices hardware. This will allow update of ddbridge driver
to support newer devices.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/dvb-frontends/Kconfig      |   9 +
 drivers/media/dvb-frontends/Makefile     |   1 +
 drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
 drivers/media/dvb-frontends/tda18212dd.h |  37 ++
 4 files changed, 981 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/tda18212dd.c
 create mode 100644 drivers/media/dvb-frontends/tda18212dd.h

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 7cac015..a34c1c7 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -65,6 +65,15 @@ config DVB_STV0367DD
 
           Say Y when you want to support this frontend.
 
+config DVB_TDA18212DD
+	tristate "NXP TDA18212 silicon tuner (DD)"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  NXP TDA18212 silicon tuner (Digital Devices driver).
+
+	  Say Y when you want to support this tuner.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index de100f1..ed12424 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
 obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
+obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
 obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
 obj-$(CONFIG_DVB_A8293) += a8293.o
 obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c
new file mode 100644
index 0000000..3d2e04e
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda18212dd.c
@@ -0,0 +1,934 @@
+/*
+ *  tda18212dd.c: Driver for the TDA18212 tuner
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#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 <asm/div64.h>
+
+#include "dvb_frontend.h"
+
+#ifndef CHK_ERROR
+    #define CHK_ERROR(s) if ((status = s) < 0) break
+#endif
+
+#define MASTER_PSM_AGC1     0
+#define MASTER_AGC1_6_15dB  1
+
+#define SLAVE_PSM_AGC1      1
+#define SLAVE_AGC1_6_15dB   0
+
+// 0 = 2 Vpp ... 2 = 1 Vpp,   7 = 0.5 Vpp
+#define IF_LEVEL_DVBC    2
+#define IF_LEVEL_DVBT    2
+
+enum {
+	ID_1                = 0x00,
+	ID_2                = 0x01,
+	ID_3                = 0x02,
+	THERMO_1,
+	THERMO_2,
+	POWER_STATE_1,
+	POWER_STATE_2,
+	INPUT_POWER_LEVEL,
+	IRQ_STATUS,
+	IRQ_ENABLE,
+	IRQ_CLEAR,
+	IRQ_SET,
+	AGC1_1,
+	AGC2_1,
+	AGCK_1,
+	RF_AGC_1,
+	IR_MIXER_1          = 0x10,
+	AGC5_1,
+	IF_AGC,
+	IF_1,
+	REFERENCE,
+	IF_FREQUENCY_1,
+	RF_FREQUENCY_1,
+	RF_FREQUENCY_2,
+	RF_FREQUENCY_3,
+	MSM_1,
+	MSM_2,
+	PSM_1,
+	DCC_1,
+	FLO_MAX,
+	IR_CAL_1,
+	IR_CAL_2,
+	IR_CAL_3            = 0x20,
+	IR_CAL_4,
+	VSYNC_MGT,
+	IR_MIXER_2,
+	AGC1_2,
+	AGC5_2,
+	RF_CAL_1,
+	RF_CAL_2,
+	RF_CAL_3,
+	RF_CAL_4,
+	RF_CAL_5,
+	RF_CAL_6,
+	RF_FILTER_1,
+	RF_FILTER_2,
+	RF_FILTER_3,
+	RF_BAND_PASS_FILTER,
+	CP_CURRENT          = 0x30,
+	AGC_DET_OUT         = 0x31,
+	RF_AGC_GAIN_1       = 0x32,
+	RF_AGC_GAIN_2       = 0x33,
+	IF_AGC_GAIN         = 0x34,
+	POWER_1             = 0x35,
+	POWER_2             = 0x36,
+	MISC_1,
+	RFCAL_LOG_1,
+	RFCAL_LOG_2,
+	RFCAL_LOG_3,
+	RFCAL_LOG_4,
+	RFCAL_LOG_5,
+	RFCAL_LOG_6,
+	RFCAL_LOG_7,
+	RFCAL_LOG_8,
+	RFCAL_LOG_9         = 0x40,
+	RFCAL_LOG_10        = 0x41,
+	RFCAL_LOG_11        = 0x42,
+	RFCAL_LOG_12        = 0x43,
+	REG_MAX,
+};
+
+enum HF_Standard {
+	HF_None=0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
+	HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
+	HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
+	HF_DVBC_8MHZ, HF_DVBC
+};
+
+struct SStandardParams {
+	s32   m_IFFrequency;
+	u32   m_BandWidth;
+	u8    m_IF_1;         // FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3
+	u8    m_IR_MIXER_2;   // 03 :6 HI_Pass:1 DC_Notch:1
+	u8    m_AGC1_1;       // 0F :4 AGC1_Top:4
+	u8    m_AGC2_1;       // 0F :4 AGC2_Top:4
+	u8    m_RF_AGC_1_Low; // EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
+	u8    m_RF_AGC_1_High;// EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
+	u8    m_IR_MIXER_1;   // 0F :4 IR_mixer_Top:4
+	u8    m_AGC5_1;       // 1F :3 AGC5_Ana AGC5_Top:4
+	u8    m_AGCK_1;       // 0F :4 AGCK_Step:2 AGCK_Mode:2
+	u8    m_PSM_1;        // 20 :2 PSM_StoB:1 :5
+	bool  m_AGC1_Freeze;
+	bool  m_LTO_STO_immune;
+};
+
+#if 0
+static struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] =
+{
+	{ 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_6MHZ
+	{ 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_7MHZ
+	{ 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_8MHZ
+	{       0,       0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false },    // HF_DVBT (Unused)
+	{ 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false },    // HF_ATSC
+	{ 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_6MHZ
+//    { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+//    { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+	{ 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+	{ 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+};
+#else
+static struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] =
+{
+     { 4000000, 6000000, 0x41, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_6MHZ
+     { 4500000, 7000000, 0x42, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_7MHZ
+     { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_8MHZ
+     // ------------------------------
+     {       0,       0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false },    // HF_DVBT (Unused)
+     { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false },    // HF_ATSC
+     { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_6MHZ
+//    { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+//    { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+     { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+     { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+};
+#endif
+struct tda_state {
+	struct i2c_adapter *i2c;
+	u8 adr;
+
+	enum HF_Standard m_Standard;
+	u32   m_Frequency;
+	u32   IF;
+
+	bool    m_isMaster;
+	bool    m_bPowerMeasurement;
+	bool    m_bLTEnable;
+	bool    m_bEnableFreeze;
+
+	u16   m_ID;
+
+	s32    m_SettlingTime;
+
+	u8    m_IFLevelDVBC;
+	u8    m_IFLevelDVBT;
+	u8    m_Regs[REG_MAX];
+	u8    m_LastPowerLevel;
+};
+
+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = data, .len   = len}};
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+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) {
+		printk("tda18212dd: i2c_read error\n");
+		return -1;
+	}
+	return 0;
+}
+
+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) {
+		printk("tda18212: i2c_write error\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int write_regs(struct tda_state *state,
+		      u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+	u8 data[nRegs+1];
+
+	data[0] = SubAddr;
+	memcpy(data + 1, Regs, nRegs);
+	return i2c_write(state->i2c, state->adr, data, nRegs+1);
+}
+
+static int write_reg(struct tda_state *state, u8 SubAddr,u8 Reg)
+{
+	u8 msg[2] = {SubAddr, Reg};
+
+	return i2c_write(state->i2c, state->adr, msg, 2);
+}
+
+static int Read(struct tda_state *state, u8 * Regs)
+{
+	return i2c_readn(state->i2c, state->adr, Regs, REG_MAX);
+}
+
+static int update_regs(struct tda_state *state, u8 RegFrom,u8 RegTo)
+{
+	return write_regs(state, RegFrom,
+			  &state->m_Regs[RegFrom], RegTo-RegFrom+1);
+}
+
+static int update_reg(struct tda_state *state, u8 Reg)
+{
+	return write_reg(state, Reg,state->m_Regs[Reg]);
+}
+
+
+static int read_regs(struct tda_state *state,
+		    u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+	return i2c_read(state->i2c, state->adr,
+			&SubAddr, 1, Regs, nRegs);
+}
+
+static int read_reg(struct tda_state *state,
+		   u8 SubAddr, u8 *Reg)
+{
+	return i2c_read(state->i2c, state->adr,
+			&SubAddr, 1, Reg, 1);
+}
+
+static int read_reg1(struct tda_state *state, u8 Reg)
+{
+	return read_reg(state, Reg, &state->m_Regs[Reg]);
+}
+
+static void init_state(struct tda_state *state)
+{
+    u32   ulIFLevelDVBC = IF_LEVEL_DVBC;
+    u32   ulIFLevelDVBT = IF_LEVEL_DVBT;
+    u32   ulPowerMeasurement = 1;
+    u32   ulLTEnable = 1;
+    u32   ulEnableFreeze = 0;
+
+    state->m_Frequency    = 0;
+    state->m_isMaster = true;
+    state->m_ID = 0;
+    state->m_LastPowerLevel = 0xFF;
+    state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07);
+    state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07);
+    state->m_bPowerMeasurement = (ulPowerMeasurement != 0);
+    state->m_bLTEnable = (ulLTEnable != 0);
+    state->m_bEnableFreeze = (ulEnableFreeze != 0);
+}
+
+static int StartCalibration(struct tda_state *state)
+{
+	int  status = 0;
+	do {
+		state->m_Regs[POWER_2] &= ~0x02; // RSSI CK = 31.25 kHz
+		CHK_ERROR(update_reg(state, POWER_2));
+
+		state->m_Regs[AGC1_2] = (state->m_Regs[AGC1_2] & ~0x60) | 0x40;    // AGC1 Do Step = 2
+		CHK_ERROR(update_reg(state, AGC1_2));        // AGC
+
+		state->m_Regs[RF_FILTER_3] = (state->m_Regs[RF_FILTER_3] & ~0xC0) | 0x40;    // AGC2 Do Step = 1
+		CHK_ERROR(update_reg(state, RF_FILTER_3));
+
+		state->m_Regs[AGCK_1] |= 0xC0; // AGCs Assym Up Step = 3      // Datasheet sets all bits to 1!
+		CHK_ERROR(update_reg(state, AGCK_1));
+
+		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x60) | 0x40;    // AGCs Assym Do Step = 2
+		CHK_ERROR(update_reg(state, AGC5_1));
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		state->m_Regs[MSM_1] = 0x3B; // Set Calibration
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+	} while(0);
+	return status;
+}
+
+static int FinishCalibration(struct tda_state *state)
+{
+	int status = 0;
+	u8 RFCal_Log[12];
+
+	do {
+		u8 IRQ = 0;
+		int Timeout = 150; // 1.5 s
+		while(true) {
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if ((IRQ & 0x80) != 0 )
+				break;
+			Timeout -= 1;
+			if (Timeout == 0) {
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		state->m_Regs[FLO_MAX] = 0x0A;
+		CHK_ERROR(update_reg(state, FLO_MAX));
+
+		state->m_Regs[AGC1_1] &= ~0xC0;
+		if( state->m_bLTEnable ) state->m_Regs[AGC1_1] |= 0x80;    // LTEnable
+
+		state->m_Regs[AGC1_1] |= (state->m_isMaster ? MASTER_AGC1_6_15dB : SLAVE_AGC1_6_15dB ) << 6;
+		CHK_ERROR(update_reg(state, AGC1_1));
+
+		state->m_Regs[PSM_1] &= ~0xC0;
+		state->m_Regs[PSM_1] |= (state->m_isMaster ? MASTER_PSM_AGC1 : SLAVE_PSM_AGC1 ) << 6;
+		CHK_ERROR(update_reg(state, PSM_1));
+
+		state->m_Regs[REFERENCE] |= 0x03; // XTOUT = 3
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		CHK_ERROR(read_regs(state, RFCAL_LOG_1,RFCal_Log,sizeof(RFCal_Log)));
+	} while(0);
+	return status;
+}
+
+static int PowerOn(struct tda_state *state)
+{
+	state->m_Regs[POWER_STATE_2] &= ~0x0F;
+	update_reg(state, POWER_STATE_2);
+	state->m_Regs[REFERENCE] |= 0x40;  // Digital clock source = Sigma Delta
+	update_reg(state, REFERENCE);
+	return 0;
+}
+
+static int Standby(struct tda_state *state)
+{
+	int status = 0;
+
+	do {
+		state->m_Regs[REFERENCE] &= ~0x40;  // Digital clock source = Quarz
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		state->m_Regs[POWER_STATE_2] &= ~0x0F;
+		state->m_Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E;
+		CHK_ERROR(update_reg(state, POWER_STATE_2));
+	} while(0);
+	return status;
+}
+
+static int attach_init(struct tda_state *state)
+{
+	int stat = 0;
+	u8 Id[2];
+	u8 PowerState = 0x00;
+
+	state->m_Standard = HF_None;
+
+	/* first read after cold reset sometimes fails on some cards,
+	   try twice */
+	stat = read_regs(state, ID_1, Id, sizeof(Id));
+	stat = read_regs(state, ID_1, Id, sizeof(Id));
+	if (stat < 0)
+		return -1;
+
+	state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1];
+	state->m_isMaster = ((Id[0] & 0x80) != 0);
+	if( !state->m_isMaster )
+		state->m_bLTEnable = false;
+
+	printk("tda18212dd: ChipID %04x\n", state->m_ID);
+
+	if( state->m_ID != 18212 )
+		return -1;
+
+	stat = read_reg(state, POWER_STATE_1 ,&PowerState);
+	if (stat < 0)
+		return stat;
+
+	printk("tda18212dd: PowerState %02x\n", PowerState);
+
+	if (state->m_isMaster) {
+		if( PowerState & 0x02 ) {
+			// msleep for XTAL Calibration (on a PC this should be long done)
+			u8 IRQStatus = 0;
+			int Timeout = 10;
+
+			while(Timeout > 0) {
+				read_reg(state, IRQ_STATUS, &IRQStatus);
+				if (IRQStatus & 0x20)
+					break;
+				Timeout -= 1;
+				msleep(10);
+			}
+			if( (IRQStatus & 0x20) == 0 ) {
+				stat = -ETIMEDOUT;
+			}
+		}
+	} else {
+		write_reg(state, FLO_MAX, 0x00);
+		write_reg(state, CP_CURRENT,0x68);
+	}
+	Read(state, state->m_Regs);
+
+	PowerOn(state);
+	StartCalibration(state);
+	FinishCalibration(state);
+	Standby(state);
+	return stat;
+}
+
+static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel)
+{
+	int status = 0;
+
+	do {
+		u8 IRQ = 0;
+		int Timeout = 70; // 700 ms
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		state->m_Regs[MSM_1] = 0x80; // power measurement
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+		while(true) {
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if( (IRQ & 0x80) != 0 )
+				break;
+			Timeout -= 1;
+			if( Timeout == 0 )
+			{
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL));
+		*pPowerLevel = state->m_Regs[INPUT_POWER_LEVEL] & 0x7F;
+
+
+		if( *pPowerLevel > 110 ) *pPowerLevel = 110;
+	} while(0);
+	/* printk("PL %d\n", *pPowerLevel); */
+	return status;
+}
+
+static int SetFrequency(struct tda_state *state, u32 Frequency, enum HF_Standard Standard)
+{
+	int status = 0;
+	struct SStandardParams *StandardParams;
+	u32   f = Frequency / 1000;
+	u8 IRQ = 0;
+	int Timeout = 25; // 250 ms
+	u32 fRatio = Frequency / 16000000;
+	u32 fDelta = Frequency - fRatio * 16000000;
+
+	if( Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ )
+		return -EINVAL;
+	StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ];
+
+	if( StandardParams->m_IFFrequency == 0 )
+		return -EINVAL;
+	state->m_Standard = HF_None;
+	state->m_Frequency = 0;
+
+	do {
+		// IF Level
+		state->m_Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? state->m_IFLevelDVBC : state->m_IFLevelDVBT;
+		CHK_ERROR(update_reg(state, IF_AGC));
+
+		// ---------------------------------------------------------------------------------
+		// Standard setup
+
+		state->m_Regs[IF_1] = StandardParams->m_IF_1;
+		CHK_ERROR(update_reg(state, IF_1));
+
+		state->m_Regs[IR_MIXER_2] = (state->m_Regs[IR_MIXER_2] & ~0x03) | StandardParams->m_IR_MIXER_2;
+		CHK_ERROR(update_reg(state, IR_MIXER_2));
+
+		state->m_Regs[AGC1_1] = (state->m_Regs[AGC1_1] & ~0x0F) | StandardParams->m_AGC1_1;
+		CHK_ERROR(update_reg(state, AGC1_1));
+
+		state->m_Regs[AGC2_1] = (state->m_Regs[AGC2_1] & ~0x0F) | StandardParams->m_AGC2_1;
+		CHK_ERROR(update_reg(state, AGC2_1));
+
+		state->m_Regs[RF_AGC_1] &= ~0xEF;
+		if( Frequency < 291000000 )
+			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low;
+		else
+			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_High;
+		CHK_ERROR(update_reg(state, RF_AGC_1));
+
+		state->m_Regs[IR_MIXER_1] = (state->m_Regs[IR_MIXER_1] & ~0x0F) | StandardParams->m_IR_MIXER_1;
+		CHK_ERROR(update_reg(state, IR_MIXER_1));
+
+		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x1F) | StandardParams->m_AGC5_1;
+		CHK_ERROR(update_reg(state, AGC5_1));
+
+		state->m_Regs[AGCK_1] = (state->m_Regs[AGCK_1] & ~0x0F) | StandardParams->m_AGCK_1;
+		CHK_ERROR(update_reg(state, AGCK_1));
+
+		state->m_Regs[PSM_1] = (state->m_Regs[PSM_1] & ~0x20) | StandardParams->m_PSM_1;
+		CHK_ERROR(update_reg(state, PSM_1));
+
+		state->m_Regs[IF_FREQUENCY_1] = ( StandardParams->m_IFFrequency / 50000 );
+		CHK_ERROR(update_reg(state, IF_FREQUENCY_1));
+
+		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
+		{
+			u8 tmp;
+			u8 RF_Filter_Gain;
+
+			CHK_ERROR(read_reg(state, RF_AGC_GAIN_1,&tmp));
+			RF_Filter_Gain = (tmp & 0x30) >> 4;
+
+			state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+
+			state->m_Regs[RF_FILTER_1] |= 0x10;    // Force
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+
+			while( RF_Filter_Gain != 0 )
+			{
+				RF_Filter_Gain -= 1;
+				state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
+				CHK_ERROR(update_reg(state, RF_FILTER_1));
+				msleep(10);
+			}
+			CHK_ERROR(status);
+
+			state->m_Regs[RF_AGC_1] |=  0x08;
+			CHK_ERROR(update_reg(state, RF_AGC_1));
+		}
+
+		// ---------------------------------------------------------------------------------
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		CHK_ERROR(PowerOn(state));
+
+		state->m_Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF);
+		state->m_Regs[RF_FREQUENCY_2] = ((f >>  8) & 0xFF);
+		state->m_Regs[RF_FREQUENCY_3] = ((f      ) & 0xFF);
+		CHK_ERROR(update_regs(state, RF_FREQUENCY_1,RF_FREQUENCY_3));
+
+		state->m_Regs[MSM_1] = 0x41; // Tune
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1, MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+		while(true)
+		{
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if( (IRQ & 0x80) != 0 ) break;
+			Timeout -= 1;
+			if (Timeout == 0) {
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		// ---------------------------------------------------------------------------------
+
+		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
+		{
+			state->m_Regs[RF_AGC_1] &=  ~0x08;
+			CHK_ERROR(update_reg(state, RF_AGC_1));
+
+			msleep(50);
+
+			state->m_Regs[RF_FILTER_1] &= ~0x10;    // remove force
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+		}
+
+		// ---------------------------------------------------------------------------------
+		//  Spur reduction
+
+		if( Frequency < 72000000 )
+		{
+			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+		}
+		else if( Frequency < 104000000 )
+		{
+			state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+		}
+		else if( Frequency < 120000000 )
+		{
+			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+		}
+		else
+		{
+			if( fDelta <= 8000000 )
+			{
+				if( fRatio & 1 ) state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+				else             state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+			}
+			else
+			{
+				if( fRatio & 1 ) state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+				else             state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+			}
+
+		}
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		if( StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze )
+		{
+			u8 tmp;
+			int AGC1GainMin = 0;
+			int nSteps = 10;
+			int Step  = 0;
+
+			CHK_ERROR(read_reg(state, AGC1_2,&tmp));
+
+			if( (tmp & 0x80) == 0 )
+			{
+				state->m_Regs[AGC1_2] |= 0x80;         // Loop off
+				CHK_ERROR(update_reg(state, AGC1_2));
+				state->m_Regs[AGC1_2] |= 0x10 ;        // Force gain
+				CHK_ERROR(update_reg(state, AGC1_2));
+			}
+			// Adapt
+			if( state->m_Regs[AGC1_1] & 0x40 ) // AGC1_6_15dB set
+			{
+				AGC1GainMin = 6;
+				nSteps = 4;
+			}
+			while( Step < nSteps )
+			{
+				int Down = 0;
+				int Up = 0, i;
+				u8 AGC1_Gain;
+
+				Step = Step + 1;
+
+				for (i = 0; i < 40; i += 1) {
+					CHK_ERROR(read_reg(state, AGC_DET_OUT, &tmp));
+					Up   += (tmp & 0x02) ?  1 : -4;
+					Down += (tmp & 0x01) ? 14 : -1;
+					msleep(1);
+				}
+				CHK_ERROR(status);
+				AGC1_Gain = (state->m_Regs[AGC1_2] & 0x0F);
+				if( Up >= 15 && AGC1_Gain != 9 )
+				{
+					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain + 1);
+					CHK_ERROR(update_reg(state, AGC1_2));
+				}
+				else if ( Down >= 10 && AGC1_Gain != AGC1GainMin )
+				{
+					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain - 1);
+					CHK_ERROR(update_reg(state, AGC1_2));
+				}
+				else
+				{
+					Step = nSteps;
+				}
+			}
+		}
+		else
+		{
+			state->m_Regs[AGC1_2] &= ~0x10 ;       // unforce gain
+			CHK_ERROR(update_reg(state, AGC1_2));
+			state->m_Regs[AGC1_2] &= ~0x80;         // Loop on
+			CHK_ERROR(update_reg(state, AGC1_2));
+		}
+
+		state->m_Standard = Standard;
+		state->m_Frequency = Frequency;
+
+		if( state->m_bPowerMeasurement )
+			PowerMeasurement(state, &state->m_LastPowerLevel);
+	} while(0);
+
+	return status;
+}
+
+static int sleep(struct dvb_frontend* fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	Standby(state);
+	return 0;
+}
+
+static int init(struct dvb_frontend* fe)
+{
+	//struct tda_state *state = fe->tuner_priv;
+	return 0;
+}
+
+static int release(struct dvb_frontend* fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+#ifndef USE_API3
+static int set_params(struct dvb_frontend *fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int status = 0;
+	int Standard;
+	u32 bw;
+
+	bw = (p->bandwidth_hz + 999999) / 1000000;
+	state->m_Frequency = p->frequency;
+	if (p->delivery_system == SYS_DVBT ||
+	    p->delivery_system == SYS_DVBT2 ||
+	    p->delivery_system == SYS_ISDBT ||
+	    p->delivery_system == SYS_DVBC2) {
+		switch (bw) {
+		case 6:
+			Standard = HF_DVBT_6MHZ;
+			break;
+		case 7:
+			Standard = HF_DVBT_7MHZ;
+			break;
+		default:
+		case 8:
+			Standard = HF_DVBT_8MHZ;
+			break;
+		}
+	} else if (p->delivery_system == SYS_DVBC_ANNEX_A) {
+		switch (bw) {
+		case 6:
+			Standard = HF_DVBC_6MHZ;
+			break;
+		case 7:
+			Standard = HF_DVBC_7MHZ;
+			break;
+		default:
+		case 8:
+			Standard = HF_DVBC_8MHZ;
+			break;
+		}
+	} else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	SetFrequency(state, state->m_Frequency, Standard);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return status;
+}
+#else
+static int set_params(struct dvb_frontend *fe,
+		      struct dvb_frontend_parameters *params)
+{
+	struct tda_state *state = fe->tuner_priv;
+	int status = 0;
+	int Standard;
+
+	state->m_Frequency = params->frequency;
+
+	if (fe->ops.info.type == FE_OFDM)
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			Standard = HF_DVBT_6MHZ;
+			break;
+		case BANDWIDTH_7_MHZ:
+			Standard = HF_DVBT_7MHZ;
+			break;
+		default:
+		case BANDWIDTH_8_MHZ:
+			Standard = HF_DVBT_8MHZ;
+			break;
+		}
+	else if (fe->ops.info.type == FE_QAM) {
+		Standard = HF_DVBC_8MHZ;
+	} else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	SetFrequency(state, state->m_Frequency, Standard);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return status;
+}
+#endif
+
+static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	*frequency = state->IF;
+	return 0;
+}
+
+static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	*st = state->m_LastPowerLevel;
+	return 0;
+}
+
+static int get_if(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	state->IF = 0;
+	if (state->m_Standard < HF_DVBT_6MHZ ||
+	    state->m_Standard > HF_DVBC_8MHZ)
+		return 0;
+	state->IF = m_StandardTable[state->m_Standard - HF_DVBT_6MHZ].m_IFFrequency;
+	*frequency = state->IF;
+	return 0;
+}
+
+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	//struct tda_state *state = fe->tuner_priv;
+	//*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+
+static struct dvb_tuner_ops tuner_ops = {
+	.info = {
+		.name = "NXP TDA18212",
+		.frequency_min  =  47125000,
+		.frequency_max  = 865000000,
+		.frequency_step =     62500
+	},
+	.init              = init,
+	.sleep             = sleep,
+	.set_params        = set_params,
+	.release           = release,
+	.get_frequency     = get_frequency,
+	.get_if_frequency  = get_if,
+	.get_bandwidth     = get_bandwidth,
+	.get_rf_strength   = get_rf_strength,
+};
+
+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
+				       struct i2c_adapter *i2c, u8 adr)
+{
+	struct tda_state *state;
+	int stat;
+
+	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	state->adr = adr;
+	state->i2c = i2c;
+	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
+	init_state(state);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	stat = attach_init(state);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (stat < 0) {
+		kfree(state);
+		return 0;
+	}
+	fe->tuner_priv = state;
+	return fe;
+}
+
+EXPORT_SYMBOL_GPL(tda18212dd_attach);
+MODULE_DESCRIPTION("TDA18212 driver");
+MODULE_AUTHOR("DD");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h
new file mode 100644
index 0000000..e276eff
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda18212dd.h
@@ -0,0 +1,37 @@
+/*
+ *  tda18212dd.h: Driver for the TDA18212 tuner
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#ifndef _TDA18212DD_H_
+#define _TDA18212DD_H_
+
+#if IS_ENABLED(CONFIG_DVB_TDA18212DD)
+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
+				       struct i2c_adapter *i2c, u8 adr);
+#else
+static inline struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
+						     struct i2c_adapter *i2c, u8 adr);
+{
+        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+        return NULL;
+}
+#endif
+
+#endif
-- 
1.8.4.2

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

* [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (3 preceding siblings ...)
  2013-11-03  0:31 ` [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner Maik Broemme
@ 2013-11-03  0:32 ` Maik Broemme
  2013-11-03 10:11   ` Mauro Carvalho Chehab
  2013-11-03  0:33 ` [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants Maik Broemme
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:32 UTC (permalink / raw)
  To: Linux Media Mailing List

Added support for the CXD2843ER demodulator for DVB-T/T2/C/C2
used by recent Digital Devices hardware.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/dvb-frontends/Kconfig   |    9 +
 drivers/media/dvb-frontends/Makefile  |    1 +
 drivers/media/dvb-frontends/cxd2843.c | 1647 +++++++++++++++++++++++++++++++++
 drivers/media/dvb-frontends/cxd2843.h |   47 +
 4 files changed, 1704 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 a34c1c7..3e39319 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -74,6 +74,15 @@ config DVB_TDA18212DD
 
 	  Say Y when you want to support this tuner.
 
+config DVB_CXD2843
+	tristate "CXD2843ER based for DVB-T/T2/C/C2"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Sony CXD2843ER/CXD2837ER DVB-T/T2/C/C2 demodulator.
+
+	  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 ed12424..90cad36 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
 obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
 obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
+obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
 obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
 obj-$(CONFIG_DVB_A8293) += a8293.o
 obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
new file mode 100644
index 0000000..87a3000
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2843.c
@@ -0,0 +1,1647 @@
+/*
+ *  cxd2843.c: 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) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#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"
+
+
+enum EDemodType { CXD2843, CXD2837, CXD2838 };
+enum EDemodState { Unknown, Shutdown, Sleep, ActiveT, ActiveT2, ActiveC, ActiveC2, ActiveIT };
+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 omode omode;
+
+	u8    IF_FS;
+	int   ContinuousClock;
+	int   SerialMode;
+	u8    SerialClockFrequency;
+	
+	u32   LockTimeout;
+	u32   TSLockTimeout;
+	u32   L1PostTimeout;
+	u32   DataSliceID;	
+	int   FirstTimeLock;
+	u32   PLPNumber;
+	u32   last_status;
+	
+	u32 bandwidth;
+	u32 bw;
+};
+
+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) {
+		printk("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) {
+		printk("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 FreezeRegsT(struct cxd_state *cxd)
+{
+	mutex_lock(&cxd->mutex);
+	return writereg(cxd, cxd->adrt, 1, 1);
+}
+
+static int UnFreezeRegsT(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;
+}
+
+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 // This looks broken (see enable)
+        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 // This looks broken (see enable)
+        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 // This looks broken (see enable)
+        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;
+
+       ///* OSERCKMODE  OSERDUTYMODE  OTSCKPERIOD  OREG_CKSEL_TSIF                            */
+       // {      1,          1,            8,             0        }, /* High Freq, full rate */
+       // {      1,          1,            8,             1        }, /* Mid Freq,  full rate */
+       // {      1,          1,            8,             2        }, /* Low Freq,  full rate */
+       // {      2,          2,            16,            0        }, /* High Freq, half rate */
+       // {      2,          2,            16,            1        }, /* Mid Freq,  half rate */
+       // {      2,          2,            16,            2        }  /* Low Freq,  half rate */
+
+        u8 OSERCKMODE = 1;
+        u8 OSERDUTYMODE = 1;
+        u8 OTSCKPERIOD = 8;
+        u8 OREG_CKSEL_TSIF = state->SerialClockFrequency;
+	
+        if (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
+        writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); // OREG_CKSEL_TSIF
+        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) {
+	case 8:
+	{
+		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		static u8 CL_data[] = { 0x01, 0xE0 };
+		static u8 NF_data[] = { 0x01, 0x02 };
+		
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
+		break;
+	}
+	case 7:
+	{
+		static u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
+		static u8 CL_data[] = { 0x12, 0xF8 };
+		static u8 NF_data[] = { 0x00, 0x03 };
+		
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x02,0x07);   // System Bandwidth
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
+		break;
+	}
+	case 6:
+	{
+		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		static u8 CL_data[] = { 0x1F, 0xDC };
+		static u8 NF_data[] = { 0x00, 0x03 };
+
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
+		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));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		
+		writebitst(state, 0x10,0xD7,0x06,0x07);   // System Bandwidth
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
+                break;
+	}
+	}
+}
+
+static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq)
+{
+	printk("%s\n", __FUNCTION__);
+
+        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
+	
+        // -- till here identical to DVB-C (apart from mode)
+	
+        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);
+
+        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:
+	{
+		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
+	}
+	break;
+	case 7:
+	{
+		static u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x02,0x07);   // System Bandwidth
+	}
+	break;
+	case 6:
+	{
+		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
+	}
+	break;
+	case 5:
+	{
+		static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x06,0x07);   // System Bandwidth
+	}
+	break;
+	case 1: // 1.7 MHz
+	{
+		static u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC };
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+
+		writebitst(state, 0x10,0xD7,0x03,0x07);   // System Bandwidth
+	}
+	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);
+
+        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);   // iffreq
+}
+
+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);
+
+        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) {
+	case 8:
+	{
+		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
+		static u8 data[2] = { 0x11, 0x9E };
+
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+
+		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
+		
+		writeregst(state, 0x50,0xEC,data,sizeof(data));   // timeout
+		writeregt(state, 0x50,0xEF,0x11);
+		writeregt(state, 0x50,0xF1,0x9E);
+	}
+	break;
+	case 6:
+	{
+		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
+		static u8 data[2] = { 0x17, 0x70 };
+
+		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
+		
+		writeregst(state, 0x50,0xEC,data,sizeof(data));   // timeout
+		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:
+	{
+		static u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 };   // 20.5/41
+		static u8 CL_data[] = { 0x15, 0xA8 };
+
+		// static u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 };  // 24
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		
+		writeregt(state, 0x10,0xD7,0x00);   // System Bandwidth
+		//static u8 CL_data[] = { 0x13, 0xFC };
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+	}
+	break;
+	case 7:
+	{
+		static u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 };
+		static u8 CL_data[] = { 0x1B, 0x5D };
+
+		//static u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 };
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		
+		writeregt(state, 0x10,0xD7,0x02);   // System Bandwidth
+		//static u8 CL_data[] = { 0x1A, 0xFA };
+		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
+	}
+	break;
+	case 6:
+	{
+		static u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 };
+		static u8 CL_data[] = { 0x1F, 0xEC };
+		//static u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 };
+		//static u8 CL_data[] = { 0x1F, 0x79 };
+		
+		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
+		// Add EQ Optimisation for tuner here
+		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
+		
+		writeregt(state, 0x10,0xD7,0x04);   // System Bandwidth
+		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));   // core latency 
+	}
+	break;
+        }
+}
+
+static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq)
+{
+	static u8 data2[3] = { 0xB9,0xBA,0x63 };  // 20.5/41 MHz
+        //static u8 data2[3] = { 0xB7,0x1B,0x00 };  // 24 MHz
+        static u8 TSIF_data[2] = { 0x61,0x60 } ; // 20.5/41 MHz
+        //static u8 TSIF_data[2] = { 0x60,0x00 } ; // 24 MHz
+
+	printk("%s\n", __FUNCTION__);
+
+        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
+	
+        //u8 Profile = 0x05;       // Lite
+        //u8 notT2time = 40;
+	
+        //u8 Profile = 0x00;       // Any
+        //u8 notT2time = 40;
+	
+	
+        if (state->PLPNumber != 0xffffffff) {
+		writeregt(state, 0x23, 0xAF, state->PLPNumber);
+		writeregt(state, 0x23, 0xAD, 0x01);
+	} else {
+		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;
+
+	printk("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->PLPNumber & 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->FirstTimeLock = 1;
+	
+	if (state->state == newDemodState ) {
+		writeregt(state, 0x00, 0xC3, 0x01);   /* Disable TS Output */
+		switch (newDemodState) {
+		case ActiveT:  
+			writeregt(state, 0x10,0x67, 0x00);  /* Stick with HP ( 0x01 = LP ) */
+			BandSettingT(state, iffreq);  
+			break;
+		case ActiveT2: 
+			T2_SetParameters(state);
+			BandSettingT2(state, iffreq);
+			break;
+		case ActiveC:
+			BandSettingC(state, iffreq);
+			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:  
+			writeregt(state, 0x10,0x67, 0x00);  // Stick with HP ( 0x01 = LP )
+			Sleep_to_ActiveT(state, iffreq);  
+			break;
+		case ActiveT2: 
+			T2_SetParameters(state);
+			Sleep_to_ActiveT2(state, iffreq);
+			break;
+		case ActiveC:  
+			Sleep_to_ActiveC(state, iffreq);
+			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;
+	state->DataSliceID = 0;//fe->dtv_property_cache.slice_id;
+	state->PLPNumber = fe->dtv_property_cache.stream_id;
+	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);
+	msleep(4);
+	writeregx(state, 0x00, 0x10, 0x01);
+        
+	writeregsx(state, 0x00, 0x13, data, 2);
+        writeregx(state, 0x00, 0x10, 0x00);
+        msleep(2);
+        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, 0x80, 0x98);
+        writebitst(state, 0x00, 0xC5, 0x00, 0x07);
+        writebitst(state, 0x00, 0xCB, 0x00, 0x01);
+        writebitst(state, 0x00, 0xC6, 0x00, 0x1D);
+        writebitst(state, 0x00, 0xC8, 0x00, 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 = 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;
+	state->IF_FS = 0x50; // IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V 
+}
+
+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 read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	//struct cxd_state *state = fe->demodulator_priv;
+
+	*ber = 0;
+	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, // 800.5 - 809.5
+		127350308, 130316678, 133352143, 136458314, 139636836,
+		142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
+		160324539, 164058977, 167880402, 171790839, 175792361,
+		179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
+		201836636, 206538016, 211348904, 216271852, 221309471,
+		226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
+		254097271, 260015956, 266072506, 272270131, 278612117,
+		285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
+		319889511, 327340695, 334965439, 342767787, 350751874,
+		358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
+		402717034, 412097519, 421696503, 431519077, 441570447,
+		451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
+		506990708, 518800039, 530884444, 543250331, 555904257,
+		568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
+		638263486, 653130553, 668343918, 683911647, 699841996,
+		716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
+		803526122, 822242650, 841395142, 860993752, 881048873,
+		901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
+	};
+	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;
+	
+	FreezeRegsT(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;
+	
+	UnFreezeRegsT(state);
+}
+#endif
+
+static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise)
+{
+	u8 Data[2];
+	u32 reg;
+        
+	FreezeRegsT(state);
+	readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data));
+	UnFreezeRegsT(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;
+        
+	FreezeRegsT(state);
+	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
+	UnFreezeRegsT(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;
+        
+	FreezeRegsT(state);
+	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
+	UnFreezeRegsT(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;
+
+	FreezeRegsT(state);
+	readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data));
+	UnFreezeRegsT(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;
+	
+	FreezeRegsT(state);
+	readregst_unlocked(state, 0x40, 0x19, &Constellation, 1);
+	readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data));
+	UnFreezeRegsT(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 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,
+};
+
+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,
+};
+
+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,
+};
+
+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;
+	}
+	printk("cxd2843: not found\n");
+	kfree(state);
+	return NULL;
+}
+
+MODULE_DESCRIPTION("CXD2843/37/38 driver");
+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cxd2843_attach);
+
diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h
new file mode 100644
index 0000000..b6bbc90
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2843.h
@@ -0,0 +1,47 @@
+/*
+ *  cxd2843.h: 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) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#ifndef _CXD2843_H_
+#define _CXD2843_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct cxd2843_cfg {
+	u8  adr;
+	u32 ts_clock;
+};
+
+#if IS_ENABLED(CONFIG_DVB_CXD2843)
+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);
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
-- 
1.8.4.2

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

* [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (4 preceding siblings ...)
  2013-11-03  0:32 ` [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2 Maik Broemme
@ 2013-11-03  0:33 ` Maik Broemme
  2013-11-03 10:16   ` Mauro Carvalho Chehab
  2013-11-03  0:35 ` [PATCH 07/12] ddbridge: Updated ddbridge registers Maik Broemme
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:33 UTC (permalink / raw)
  To: Linux Media Mailing List

Added EXPORT_SYMBOL(dvb_usercopy) to allow new ddbridge driver to
use it. It is questionable if I should use it in this way or not.
If not I will fix it.

Added two new DVB device constants DVB_DEVICE_CI and DVB_DEVICE_MOD
required by newer ddbridge driver. Again it is questionable to use
them or modify ddbridge driver.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/dvb-core/dvbdev.c | 1 +
 drivers/media/dvb-core/dvbdev.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 401ef64..e451e9e 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -438,6 +438,7 @@ out:
 	kfree(mbuf);
 	return err;
 }
+EXPORT_SYMBOL(dvb_usercopy);
 
 static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 93a9470..016c46e 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -47,6 +47,8 @@
 #define DVB_DEVICE_CA         6
 #define DVB_DEVICE_NET        7
 #define DVB_DEVICE_OSD        8
+#define DVB_DEVICE_CI         9
+#define DVB_DEVICE_MOD       10
 
 #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
 	static short adapter_nr[] = \
-- 
1.8.4.2

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

* [PATCH 07/12] ddbridge: Updated ddbridge registers
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (5 preceding siblings ...)
  2013-11-03  0:33 ` [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants Maik Broemme
@ 2013-11-03  0:35 ` Maik Broemme
  2013-11-03 10:17   ` Mauro Carvalho Chehab
  2013-11-03  0:40 ` [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file Maik Broemme
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:35 UTC (permalink / raw)
  To: Linux Media Mailing List

Updated ddbridge registers:

  - Added GPIO and MDIO registers
  - Added Clock Generator (Sil598 @ 0xAA I2c)
  - Added DAC (AD9781/AD9783 SPI)
  - Added Temperature Monitor (2x LM75A @ 0x90,0x92 I2c)
  - Added CI Interface (only CI-Bridge)
  - Added output control registers
  - Added modulator channels
  - Removed unneded defines (might be added later again if needed)

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/ddbridge-regs.h | 273 ++++++++++++++++++-----------
 1 file changed, 168 insertions(+), 105 deletions(-)

diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
index a3ccb31..7d8bda4 100644
--- a/drivers/media/pci/ddbridge/ddbridge-regs.h
+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h
@@ -1,47 +1,53 @@
 /*
- * ddbridge-regs.h: Digital Devices PCIe bridge driver
+ *  ddbridge-regs.h: Digital Devices PCIe bridge driver
  *
- * Copyright (C) 2010-2011 Digital Devices GmbH
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
  *
- * 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 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.
  *
- * 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
+ *  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
  */
 
-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
+#ifndef _DDBRIDGE_REGS_H_
+#define _DDBRIDGE_REGS_H_
 
 /* Register Definitions */
+#define CUR_REGISTERMAP_VERSION     0x10003
+#define CUR_REGISTERMAP_VERSION_CI  0x10000
+#define CUR_REGISTERMAP_VERSION_MOD 0x10000
 
-#define CUR_REGISTERMAP_VERSION 0x10000
-
-#define HARDWARE_VERSION       0x00
-#define REGISTERMAP_VERSION    0x04
+#define HARDWARE_VERSION            0x00
+#define REGISTERMAP_VERSION         0x04
 
-/* ------------------------------------------------------------------------- */
 /* SPI Controller */
+#define SPI_CONTROL      0x10
+#define SPI_DATA         0x14
 
-#define SPI_CONTROL     0x10
-#define SPI_DATA        0x14
+/* GPIO */
+#define GPIO_OUTPUT      0x20
+#define GPIO_DIRECTION   0x28
 
-/* ------------------------------------------------------------------------- */
+/* MDIO */
+#define MDIO_CTRL        0x20
+#define MDIO_ADR         0x24
+#define MDIO_REG         0x28
+#define MDIO_VAL         0x2C
 
-/* Interrupt controller                                     */
-/* How many MSI's are available depends on HW (Min 2 max 8) */
-/* How many are usable also depends on Host platform        */
+/* How many MSI's are available depends on HW (Min 2 max 8)
+   How many are usable also depends on Host platform */
 
+/* Interrupt controller */
 #define INTERRUPT_BASE   (0x40)
 
 #define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
@@ -57,95 +63,152 @@
 #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
 #define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
 
-#define INTMASK_I2C1        (0x00000001)
-#define INTMASK_I2C2        (0x00000002)
-#define INTMASK_I2C3        (0x00000004)
-#define INTMASK_I2C4        (0x00000008)
-
-#define INTMASK_CIRQ1       (0x00000010)
-#define INTMASK_CIRQ2       (0x00000020)
-#define INTMASK_CIRQ3       (0x00000040)
-#define INTMASK_CIRQ4       (0x00000080)
-
-#define INTMASK_TSINPUT1    (0x00000100)
-#define INTMASK_TSINPUT2    (0x00000200)
-#define INTMASK_TSINPUT3    (0x00000400)
-#define INTMASK_TSINPUT4    (0x00000800)
-#define INTMASK_TSINPUT5    (0x00001000)
-#define INTMASK_TSINPUT6    (0x00002000)
-#define INTMASK_TSINPUT7    (0x00004000)
-#define INTMASK_TSINPUT8    (0x00008000)
-
-#define INTMASK_TSOUTPUT1   (0x00010000)
-#define INTMASK_TSOUTPUT2   (0x00020000)
-#define INTMASK_TSOUTPUT3   (0x00040000)
-#define INTMASK_TSOUTPUT4   (0x00080000)
-
-/* ------------------------------------------------------------------------- */
-/* I2C Master Controller */
-
-#define I2C_BASE        (0x80)  /* Byte offset */
-
-#define I2C_COMMAND     (0x00)
-#define I2C_TIMING      (0x04)
-#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
-#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
+/* Clock Generator (Sil598 @ 0xAA I2c) */
+#define CLOCKGEN_BASE       (0x80)
+#define CLOCKGEN_CONTROL    (CLOCKGEN_BASE + 0x00)
+#define CLOCKGEN_INDEX      (CLOCKGEN_BASE + 0x04)
+#define CLOCKGEN_WRITEDATA  (CLOCKGEN_BASE + 0x08)
+#define CLOCKGEN_READDATA   (CLOCKGEN_BASE + 0x0C)
 
-#define I2C_MONITOR     (0x1C)
+/* DAC (AD9781/AD9783 SPI) */
+#define DAC_BASE            (0x090)
+#define DAC_CONTROL         (DAC_BASE)
+#define DAC_WRITE_DATA      (DAC_BASE+4)
+#define DAC_READ_DATA       (DAC_BASE+8)
 
-#define I2C_BASE_1      (I2C_BASE + 0x00)
-#define I2C_BASE_2      (I2C_BASE + 0x20)
-#define I2C_BASE_3      (I2C_BASE + 0x40)
-#define I2C_BASE_4      (I2C_BASE + 0x60)
+#define DAC_CONTROL_STARTIO (0x100)
+#define DAC_CONTROL_RESET   (0x200)
 
-#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
+/* Temperature Monitor (2x LM75A @ 0x90,0x92 I2c) */
+#define TEMPMON_BASE        (0xA0)
+#define TEMPMON_CONTROL     (TEMPMON_BASE + 0x00)
+#define TEMPMON_SENSOR1     (TEMPMON_BASE + 0x08)    // SHORT Temperature in °C x 256
+#define TEMPMON_SENSOR2     (TEMPMON_BASE + 0x0C)    // SHORT Temperature in °C x 256
 
-#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
-#define I2C_TASKMEM_SIZE    (0x1000)
-
-#define I2C_SPEED_400   (0x04030404)
-#define I2C_SPEED_200   (0x09080909)
-#define I2C_SPEED_154   (0x0C0B0C0C)
-#define I2C_SPEED_100   (0x13121313)
-#define I2C_SPEED_77    (0x19181919)
-#define I2C_SPEED_50    (0x27262727)
-
-
-/* ------------------------------------------------------------------------- */
-/* DMA  Controller */
-
-#define DMA_BASE_WRITE        (0x100)
-#define DMA_BASE_READ         (0x140)
+/* I2C Master Controller */
+#define I2C_BASE            (0x80)   /* Byte offset */
 
-#define DMA_CONTROL     (0x00)                  /* 64 */
-#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
+#define I2C_COMMAND         (0x00)
+#define I2C_TIMING          (0x04)
+#define I2C_TASKLENGTH      (0x08)   /* High read, low write */
+#define I2C_TASKADDRESS     (0x0C)   /* High read, low write */
+#define I2C_TASKMEM_BASE    (0x1000) /* Byte offset */
+#define I2C_TASKMEM_SIZE    (0x0800)
 
-#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
-#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
-#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
-#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
-#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
-#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
-#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
-#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
-#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
+#define I2C_SPEED_400       (0x04030404)
+#define I2C_SPEED_100       (0x13121313)
 
-/* ------------------------------------------------------------------------- */
-/* DMA  Buffer */
+/* DMA Controller */
+#define DMA_BASE_WRITE      (0x100)
+#define DMA_BASE_READ       (0x140)
 
+/* DMA Buffer */
 #define TS_INPUT_BASE       (0x200)
-#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
+#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 0x10 + 0x00) 
+#define TS_INPUT_CONTROL2(i)        (TS_INPUT_BASE + (i) * 0x10 + 0x04) 
 
-#define TS_OUTPUT_BASE       (0x280)
-#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
+#define TS_OUTPUT_BASE      (0x280)
+#define TS_OUTPUT_CONTROL(i)        (TS_OUTPUT_BASE + (i) * 0x10 + 0x00) 
+#define TS_OUTPUT_CONTROL2(i)       (TS_OUTPUT_BASE + (i) * 0x10 + 0x04) 
 
 #define DMA_BUFFER_BASE     (0x300)
-
-#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
-#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
-#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
-#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
+#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) 
+#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 0x10 + 0x04)
+#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
+#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
 
 #define DMA_BASE_ADDRESS_TABLE  (0x2000)
-#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
 
+/* CI Interface (only CI-Bridge) */
+#define CI_BASE                     (0x400)
+#define CI_CONTROL(i)               (CI_BASE + (i) * 32 + 0x00)
+
+#define CI_DO_ATTRIBUTE_RW(i)       (CI_BASE + (i) * 32 + 0x04)
+#define CI_DO_IO_RW(i)              (CI_BASE + (i) * 32 + 0x08)
+#define CI_READDATA(i)              (CI_BASE + (i) * 32 + 0x0c)
+#define CI_DO_READ_ATTRIBUTES(i)    (CI_BASE + (i) * 32 + 0x10)
+
+#define CI_RESET_CAM                    (0x00000001)
+#define CI_POWER_ON                     (0x00000002)
+#define CI_ENABLE                       (0x00000004)
+#define CI_BYPASS_DISABLE               (0x00000010)
+
+#define CI_CAM_READY                    (0x00010000)
+#define CI_CAM_DETECT                   (0x00020000)
+#define CI_READY                        (0x80000000)
+
+#define CI_READ_CMD                     (0x40000000)
+#define CI_WRITE_CMD                    (0x80000000)
+
+#define CI_BUFFER_BASE                  (0x3000)
+#define CI_BUFFER_SIZE                  (0x0800)
+
+#define CI_BUFFER(i)                    (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE )
+
+#define VCO1_BASE           (0xC0)
+#define VCO1_CONTROL        (VCO1_BASE + 0x00)
+#define VCO1_DATA           (VCO1_BASE + 0x04)  // 24 Bit
+#define VCO1_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
+#define VCO1_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
+
+#define VCO2_BASE           (0xC8)
+#define VCO2_CONTROL        (VCO2_BASE + 0x00)
+#define VCO2_DATA           (VCO2_BASE + 0x04)  // 24 Bit
+#define VCO2_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
+#define VCO2_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
+
+#define VCO3_BASE           (0xD0)
+#define VCO3_CONTROL        (VCO3_BASE + 0x00)
+#define VCO3_DATA           (VCO3_BASE + 0x04)  // 32 Bit
+#define VCO3_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
+#define VCO3_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
+
+#define RF_ATTENUATOR   (0xD8)
+
+/* Output control */
+#define IQOUTPUT_BASE           (0x240)
+#define IQOUTPUT_CONTROL        (IQOUTPUT_BASE + 0x00)
+#define IQOUTPUT_CONTROL2       (IQOUTPUT_BASE + 0x04)    
+#define IQOUTPUT_POSTSCALER     (IQOUTPUT_BASE + 0x0C)
+#define IQOUTPUT_PRESCALER      (IQOUTPUT_BASE + 0x10)
+
+#define IQOUTPUT_EQUALIZER_0    (IQOUTPUT_BASE + 0x14)
+
+#define IQOUTPUT_CONTROL_RESET              (0x00000001)
+#define IQOUTPUT_CONTROL_ENABLE             (0x00000002)
+#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER   (0x00000010)
+
+#define MODULATOR_BASE            (0x200)
+#define MODULATOR_CONTROL         (MODULATOR_BASE)
+#define MODULATOR_IQTABLE_END     (MODULATOR_BASE+4)
+#define MODULATOR_IQTABLE_INDEX   (MODULATOR_BASE+8)
+#define MODULATOR_IQTABLE_DATA    (MODULATOR_BASE+12)
+
+#define MODULATOR_IQTABLE_INDEX_IQ_MASK       ( 0x00008000 )
+#define MODULATOR_IQTABLE_INDEX_SEL_I         ( 0x00000000 )
+#define MODULATOR_IQTABLE_INDEX_SEL_Q         ( MODULATOR_IQTABLE_INDEX_IQ_MASK )
+
+/* Modulator Channels */
+#define CHANNEL_BASE                (0x400)
+#define CHANNEL_CONTROL(i)          (CHANNEL_BASE + (i) * 64 + 0x00)
+#define CHANNEL_SETTINGS(i)         (CHANNEL_BASE + (i) * 64 + 0x04)
+#define CHANNEL_RATE_INCR(i)        (CHANNEL_BASE + (i) * 64 + 0x0C)
+#define CHANNEL_PCR_ADJUST_OUTL(i)  (CHANNEL_BASE + (i) * 64 + 0x10)
+#define CHANNEL_PCR_ADJUST_OUTH(i)  (CHANNEL_BASE + (i) * 64 + 0x14)
+#define CHANNEL_PCR_ADJUST_INL(i)   (CHANNEL_BASE + (i) * 64 + 0x18)
+#define CHANNEL_PCR_ADJUST_INH(i)   (CHANNEL_BASE + (i) * 64 + 0x1C)
+#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20)
+#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24)
+#define CHANNEL_PKT_COUNT_OUT(i)    (CHANNEL_BASE + (i) * 64 + 0x28)
+#define CHANNEL_PKT_COUNT_IN(i)     (CHANNEL_BASE + (i) * 64 + 0x2C)
+
+#define CHANNEL_CONTROL_RESET               (0x00000001)
+#define CHANNEL_CONTROL_ENABLE_DVB          (0x00000002)
+#define CHANNEL_CONTROL_ENABLE_IQ           (0x00000004)
+#define CHANNEL_CONTROL_ENABLE_SOURCE       (0x00000008)
+#define CHANNEL_CONTROL_ENABLE_PCRADJUST    (0x00000010)
+#define CHANNEL_CONTROL_FREEZE_STATUS       (0x00000100)
+
+#define CHANNEL_CONTROL_BUSY                (0x01000000)
+
+#endif
-- 
1.8.4.2

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

* [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (6 preceding siblings ...)
  2013-11-03  0:35 ` [PATCH 07/12] ddbridge: Updated ddbridge registers Maik Broemme
@ 2013-11-03  0:40 ` Maik Broemme
  2013-11-03 10:23   ` Mauro Carvalho Chehab
  2013-11-03  0:41 ` [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card Maik Broemme
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:40 UTC (permalink / raw)
  To: Linux Media Mailing List

Moved i2c interfaces from ddbridge-core.c into separate file.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/ddbridge-i2c.c | 239 ++++++++++++++++++++++++++++++
 1 file changed, 239 insertions(+)
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c

diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
new file mode 100644
index 0000000..5e9788c
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
@@ -0,0 +1,239 @@
+/*
+ *  ddbridge-i2c.c: Digital Devices bridge i2c driver
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#include "ddbridge.h"
+#include "ddbridge-regs.h"
+
+static int i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
+{
+	struct ddb *dev = i2c->dev;
+	int stat;
+	u32 val;
+	u32 istat;
+
+	// i2c->done = 0;
+	ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+
+	// TODO: fix timeout issue.
+	// stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
+	stat = wait_for_completion_timeout(&i2c->completion, HZ);
+	if (stat <= 0) {
+		printk(KERN_ERR "DDBridge I2C timeout, card %d, port %d\n",
+		       dev->nr, i2c->nr);
+		istat = ddbreadl(dev, INTERRUPT_STATUS);
+		printk(KERN_ERR "DDBridge IRS %08x\n", istat);
+		ddbwritel(dev, istat, INTERRUPT_ACK);
+		return -EIO;
+	}
+	val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
+	if (val & 0x70000)
+		return -EIO;
+	return 0;
+}
+
+static int i2c_master_xfer(struct i2c_adapter *adapter,
+			   struct i2c_msg msg[], int num)
+{
+	struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
+	struct ddb *dev = i2c->dev;
+	u8 addr = 0;
+
+	if (num)
+		addr = msg[0].addr;
+	if (num == 2 && msg[1].flags & I2C_M_RD &&
+	    !(msg[0].flags & I2C_M_RD)) {
+		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
+			    msg[0].buf, msg[0].len);
+		ddbwritel(dev, msg[0].len|(msg[1].len << 16),
+			  i2c->regs + I2C_TASKLENGTH);
+		if (!i2c_cmd(i2c, addr, 1)) {
+			memcpy_fromio(msg[1].buf,
+				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
+				      msg[1].len);
+			return num;
+		}
+	}
+	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+		ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, 
+			 msg[0].buf, msg[0].len);
+		ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
+		if (!i2c_cmd(i2c, addr, 2)) {
+			return num;
+		}
+	}
+	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+		ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+		if (!i2c_cmd(i2c, addr, 3)) {
+			ddbcpyfrom(dev, msg[0].buf,
+				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
+			return num;
+		}
+	}
+	return -EIO;
+}
+
+static u32 i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static void i2c_handler(unsigned long priv)
+{
+	struct ddb_i2c *i2c = (struct ddb_i2c *) priv; 
+
+	complete(&i2c->completion);
+}
+
+static struct i2c_algorithm i2c_algo = {
+	.master_xfer   = i2c_master_xfer,
+	.functionality = i2c_functionality,
+};
+
+int ddb_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;
+}
+
+int ddb_i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+int ddb_i2c_read_regs(struct i2c_adapter *adapter,
+			 u8 adr, u8 reg, u8 *val, u8 len)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = &reg, .len   = 1 },
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = len } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_regs16(struct i2c_adapter *adapter, 
+			   u8 adr, u16 reg, u8 *val, u8 len)
+{
+	u8 reg16[2] = { reg >> 8, reg };
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = reg16, .len   = 2 },
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = len } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = &reg, .len   = 1},
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+			  u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+int ddb_i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
+			   u16 reg, u8 val)
+{
+	u8 msg[3] = {reg >> 8, reg & 0xff, val};
+
+	return ddb_i2c_write(adap, adr, msg, 3);
+}
+
+int ddb_i2c_write_reg(struct i2c_adapter *adap, u8 adr,
+			  u8 reg, u8 val)
+{
+	u8 msg[2] = {reg, val};
+
+	return ddb_i2c_write(adap, adr, msg, 2);
+}
+
+void ddb_i2c_release(struct ddb *dev)
+{
+	int i;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		i2c = &dev->i2c[i];
+		adap = &i2c->adap;
+		i2c_del_adapter(adap);
+	}
+}
+
+int ddb_i2c_init(struct ddb *dev)
+{
+	int i, j, stat = 0;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+	
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		i2c = &dev->i2c[i];
+		dev->handler[i] = i2c_handler;
+		dev->handler_data[i] = (unsigned long) i2c;
+		i2c->dev = dev;
+		i2c->nr = i;
+		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
+		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
+		i2c->regs = 0x80 + i * 0x20;
+		ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
+		ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf,
+			  i2c->regs + I2C_TASKADDRESS);
+		// init_waitqueue_head(&i2c->wq);
+		init_completion(&i2c->completion);
+
+		adap = &i2c->adap;
+		i2c_set_adapdata(adap, i2c);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
+#else
+#ifdef I2C_CLASS_TV_ANALOG
+		adap->class = I2C_CLASS_TV_ANALOG;
+#endif
+#endif
+		strcpy(adap->name, "ddbridge");
+		adap->algo = &i2c_algo;
+		adap->algo_data = (void *)i2c;
+		adap->dev.parent = dev->dev;
+		stat = i2c_add_adapter(adap);
+		if (stat)
+			break;
+	}
+	if (stat)
+		for (j = 0; j < i; j++) {
+			i2c = &dev->i2c[j];
+			adap = &i2c->adap;
+			i2c_del_adapter(adap);
+		}
+	return stat;
+}
-- 
1.8.4.2

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

* [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (7 preceding siblings ...)
  2013-11-03  0:40 ` [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file Maik Broemme
@ 2013-11-03  0:41 ` Maik Broemme
  2013-11-03 10:44   ` Mauro Carvalho Chehab
  2013-11-03  0:44 ` [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10 Maik Broemme
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:41 UTC (permalink / raw)
  To: Linux Media Mailing List

Added support for the Digital Devices Resi DVB-C Modulator card.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/ddbridge-mod.c | 1033 +++++++++++++++++++++++++++++
 1 file changed, 1033 insertions(+)
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-mod.c

diff --git a/drivers/media/pci/ddbridge/ddbridge-mod.c b/drivers/media/pci/ddbridge/ddbridge-mod.c
new file mode 100644
index 0000000..8f7c256
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-mod.c
@@ -0,0 +1,1033 @@
+/*
+ *  ddbridge-mod.c: Digital Devices DVB modulator driver
+ *
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
+ *
+ *  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
+ */
+
+#include "ddbridge.h"
+#include "ddbridge-regs.h"
+
+inline s64 ConvertPCR(s64 a)
+{
+	s32 ext;
+	s64 b;
+	
+	b = div_s64_rem(a, 300 << 22, &ext);
+	
+	return (b << 31) | ext;
+
+}
+
+inline s64 NegConvertPCR(s64 a)
+{
+	s32 ext;
+	s64 b;
+	
+	b = -div_s64_rem(a, 300 << 22, &ext);
+
+	if( ext != 0 ) {
+		ext = (300 << 22) - ext;
+		b -= 1;
+	}
+	return (b << 31) | ext;
+}
+
+inline s64 RoundPCR(s64 a)
+{
+	s64 b = a + (HW_LSB_MASK>>1);
+	return b & ~(HW_LSB_MASK - 1);
+}
+
+inline s64 RoundPCRUp(s64 a)
+{
+	s64 b = a + (HW_LSB_MASK - 1);
+	return b & ~(HW_LSB_MASK - 1);
+}
+
+inline s64 RoundPCRDown(s64 a)
+{
+	return a & ~(HW_LSB_MASK - 1);
+}
+
+static int mod_busy(struct ddb *dev, int chan)
+{
+	u32 creg;
+
+	while (1) {
+		creg = ddbreadl(dev, CHANNEL_CONTROL(chan));
+		if (creg == 0xffffffff) 
+			return -EFAULT;
+		if ((creg & CHANNEL_CONTROL_BUSY) == 0)
+			break;
+	}
+	return 0;
+}
+
+void ddbridge_mod_output_stop(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+	struct mod_state *mod= &dev->mod[output->nr];
+
+	mod->State = CM_IDLE;
+	mod->Control = 0;
+	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
+
+	mod_busy(dev, output->nr);
+	printk("mod_output_stop %d.%d\n", dev->nr, output->nr);
+}
+
+static void mod_set_incs(struct ddb_output *output)
+{
+	s64 pcr;
+	struct ddb *dev = output->port->dev;
+	struct mod_state *mod= &dev->mod[output->nr];
+
+	pcr = ConvertPCR(mod->PCRIncrement);
+	ddbwritel(dev, 	pcr & 0xffffffff, 
+		  CHANNEL_PCR_ADJUST_OUTL(output->nr));
+	ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
+		  CHANNEL_PCR_ADJUST_OUTH(output->nr));
+	mod_busy(dev, output->nr);
+	
+	pcr = NegConvertPCR(mod->PCRDecrement);
+	ddbwritel(dev, 	pcr & 0xffffffff, 
+		  CHANNEL_PCR_ADJUST_INL(output->nr));
+	ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
+		  CHANNEL_PCR_ADJUST_INH(output->nr));
+	mod_busy(dev, output->nr);
+
+}
+
+static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 };
+
+void ddbridge_mod_output_start(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+	struct mod_state *mod= &dev->mod[output->nr];
+
+	// PCRIncrement = RoundPCR(PCRIncrement);
+	// PCRDecrement = RoundPCR(PCRDecrement);
+
+	mod->LastInPacketCount = 0;
+	mod->LastOutPacketCount = 0;
+	mod->InOverflowPacketCount = 0;
+	mod->OutOverflowPacketCount = 0;
+	mod->LastInPackets = 0;
+	mod->LastOutPackets = 0;
+	mod->LastPCRAdjust = 0;
+	mod->PCRRunningCorr = 0;
+	mod->MinInputPackets = 524288/2;   // we interrupt every 0x80000=524288 packets
+	mod->PCRIncrement = 0;   // PCRIncrement;
+	mod->PCRDecrement = 0;   // PCRDecrement;
+
+	mod->State = CM_STARTUP;
+	mod->StateCounter = CM_STARTUP_DELAY;
+
+	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
+	udelay(10);
+	ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr));
+	udelay(10);
+	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
+
+	// QAM: 600 601 602 903 604 = 16 32 64 128 256
+	// ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr));
+	ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr));
+
+	ddbwritel(dev, 	mod->rate_inc, CHANNEL_RATE_INCR(output->nr));
+	mod_busy(dev, output->nr);
+
+	mod_set_incs(output);
+
+	mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | 
+			CHANNEL_CONTROL_ENABLE_DVB |
+			CHANNEL_CONTROL_ENABLE_SOURCE);
+
+	ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
+	printk("mod_output_start %d.%d\n", dev->nr, output->nr);
+}
+
+static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value)
+{
+	u32 RegValue = 0;
+	
+	ddbwritel(dev, Value, DAC_WRITE_DATA);
+	ddbwritel(dev, DAC_CONTROL_STARTIO | Index, DAC_CONTROL);
+	do {
+		RegValue = ddbreadl(dev, DAC_CONTROL);
+	} while ((RegValue & DAC_CONTROL_STARTIO) != 0 );
+}
+
+static void mod_write_dac_register2(struct ddb *dev, u8 Index, u16 Value)
+{
+	u32 RegValue = 0;
+	
+	ddbwritel(dev, Value, DAC_WRITE_DATA);
+	ddbwritel(dev, DAC_CONTROL_STARTIO | 0x20 | Index, DAC_CONTROL);
+	do {
+		RegValue = ddbreadl(dev, DAC_CONTROL);
+	} while ((RegValue & DAC_CONTROL_STARTIO) != 0 );
+}
+
+static int mod_read_dac_register(struct ddb *dev, u8 Index, u8 *pValue)
+{
+	u32 RegValue = 0;
+	
+	ddbwritel(dev, DAC_CONTROL_STARTIO | 0x80 | Index, DAC_CONTROL);
+	do {
+		RegValue = ddbreadl(dev, DAC_CONTROL);
+	} while( (RegValue & DAC_CONTROL_STARTIO) != 0 );
+	
+	RegValue = ddbreadl(dev, DAC_READ_DATA);
+	*pValue = (u8) RegValue;
+	return 0;
+}
+
+static void mod_set_up_converter_vco1(struct ddb *dev, u32 Value)
+{
+	u32 RegValue = 0;
+
+	/* Extra delay before writing N divider */
+	if ((Value & 0x03) == 0x02) 
+		msleep(50);
+	do {
+		RegValue = ddbreadl(dev, VCO1_CONTROL);
+	} while( (RegValue & VCO1_CONTROL_WRITE) != 0 ); 
+	
+	if ((RegValue & VCO1_CONTROL_CE) == 0) {
+		RegValue |= VCO1_CONTROL_CE;
+		ddbwritel(dev, RegValue, VCO1_CONTROL);
+		msleep(10);
+	}
+	
+	ddbwritel(dev, Value, VCO1_DATA);
+	ddbwritel(dev, RegValue | VCO1_CONTROL_WRITE, VCO1_CONTROL);
+}
+
+static void mod_set_up_converter_vco2(struct ddb *dev, u32 Value)
+{
+	u32 RegValue = 0;
+
+	/* Extra delay before writing N divider */
+	if ((Value & 0x03) == 0x02)
+		msleep(50);
+	do {
+		RegValue = ddbreadl(dev, VCO2_CONTROL);
+	} while ((RegValue & VCO2_CONTROL_WRITE) != 0); 
+	
+	if ((RegValue & VCO2_CONTROL_CE) == 0) {
+		RegValue |= VCO2_CONTROL_CE;
+		ddbwritel(dev, RegValue, VCO2_CONTROL);
+		msleep(10);
+	}
+	
+	ddbwritel(dev, Value, VCO2_DATA);
+	ddbwritel(dev, RegValue | VCO2_CONTROL_WRITE, VCO2_CONTROL);
+}
+
+static void mod_set_down_converter_vco(struct ddb *dev, u32 Value)
+{
+	u32 RegValue = 0;
+
+	do {
+		RegValue = ddbreadl(dev, VCO3_CONTROL);
+	} while( (RegValue & VCO3_CONTROL_WRITE) != 0 ); 
+	
+	if ((RegValue & VCO3_CONTROL_CE) == 0) {
+		RegValue |= VCO3_CONTROL_CE;
+		ddbwritel(dev, RegValue, VCO3_CONTROL);
+		msleep(10);
+	}
+	ddbwritel(dev, Value, VCO3_DATA);
+	ddbwritel(dev, RegValue | VCO3_CONTROL_WRITE, VCO3_CONTROL);
+}
+
+static int mod_set_attenuator(struct ddb *dev, u32 Value)
+{
+	if (Value > 31)
+		return -EINVAL;
+	ddbwritel(dev, Value, RF_ATTENUATOR);
+	return 0;
+}
+
+static void mod_si598_readreg(struct ddb *dev, u8 index, u8 *val)
+{
+	ddbwritel(dev, index, CLOCKGEN_INDEX);
+	ddbwritel(dev, 1, CLOCKGEN_CONTROL);
+	msleep(5);
+	*val = ddbreadl(dev, CLOCKGEN_READDATA);
+}
+
+static void mod_si598_writereg(struct ddb *dev, u8 index, u8 val)
+{
+	ddbwritel(dev, index, CLOCKGEN_INDEX);
+	ddbwritel(dev, val, CLOCKGEN_WRITEDATA);
+	ddbwritel(dev, 3, CLOCKGEN_CONTROL);
+	msleep(5);
+}
+
+static int mod_set_si598(struct ddb *dev, u32 freq)
+{
+	u8 Data[6];
+	u64 fDCO = 0;
+	u64 RFreq = 0;
+	u32 fOut = 10000000;
+	u64 m_fXtal = 0;
+	u32 N = 0;
+	u64 HSDiv = 0;
+
+	u32 fxtal;
+	u64 MinDiv, MaxDiv, Div;
+	u64 RF;
+
+	if (freq < 10000000 || freq > 525000000 )
+		return -EINVAL;
+	mod_si598_writereg(dev, 137, 0x10);
+
+	if (m_fXtal == 0) {
+		mod_si598_writereg(dev, 135, 0x01);
+		mod_si598_readreg(dev, 7, &Data[0]);
+		mod_si598_readreg(dev, 8, &Data[1]);
+		mod_si598_readreg(dev, 9, &Data[2]);
+		mod_si598_readreg(dev, 10, &Data[3]);
+		mod_si598_readreg(dev, 11, &Data[4]);
+		mod_si598_readreg(dev, 12, &Data[5]);
+		
+		printk(" Data = %02x %02x %02x %02x %02x %02x\n",
+		       Data[0],Data[1],Data[2],Data[3],Data[4],Data[5]);
+		RFreq = (((u64)Data[1] & 0x3F) << 32) | ((u64)Data[2] << 24) |
+			((u64)Data[3] << 16) | ((u64)Data[4] << 8) | ((u64)Data[5]);
+		if (RFreq == 0)
+			return -EINVAL;
+		HSDiv = ((Data[0] & 0xE0) >> 5) + 4;
+		if (HSDiv == 8 || HSDiv == 10 ) 
+			return -EINVAL;
+		N = (((u32)(Data[0] & 0x1F) << 2) | ((u32)(Data[1] & 0xE0) >> 6)) + 1;
+		fDCO = fOut * (u64)(HSDiv * N);  
+		m_fXtal = fDCO << 28;
+		printk("fxtal %016llx  rfreq %016llx\n", m_fXtal, RFreq);
+		
+		m_fXtal += RFreq >> 1;
+		m_fXtal = div64_u64(m_fXtal, RFreq);
+		
+		printk(" fOut = %d fXtal = %d fDCO = %d HDIV = %2d, N = %3d \n",
+		       (u32) fOut, (u32) m_fXtal, (u32) fDCO, (u32) HSDiv, N);
+	}
+	
+	fOut = freq;
+	MinDiv = 4850000000ULL; do_div(MinDiv, freq); MinDiv += 1;
+	MaxDiv = 5670000000ULL; do_div(MaxDiv, freq);
+	Div    = 5260000000ULL; do_div(Div, freq);
+
+	if( Div < MinDiv ) 
+		Div = Div + 1;
+	printk(" fOut = %d MinDiv = %4d MaxDiv = %4d StartDiv = %d\n", fOut, (u32) MinDiv, (u32) MaxDiv, (u32) Div);
+	
+	if( Div <= 11 ) {
+		N = 1;
+		HSDiv = Div;
+	} else {
+		int retry = 100;
+		while (retry > 0) {
+			N = 0;
+			HSDiv = Div;
+			while( (HSDiv > 11) /*|| ((HSDiv * N) != Div)*/ ) {
+				N = N + 2;
+				HSDiv = Div;
+				do_div(HSDiv, N);
+				if (N > 128) 
+					break;
+			}
+			printk(" %3d: %llu %u %u %u\n", retry, Div, (u32) HSDiv*N, (u32) HSDiv, N);
+			if (HSDiv * N < MinDiv) {
+				Div = Div + 2;
+			} else if (HSDiv * N > MaxDiv) {
+				Div = Div - 2;
+			} else
+				break;
+			retry = retry - 1;
+		}
+		if( retry == 0 ) {
+			printk(" FAIL \n");
+			return -EINVAL;
+		}
+	}
+	
+	if (HSDiv == 8 || HSDiv == 10)	{
+		HSDiv = HSDiv >> 1;
+		N = N * 2;
+	}
+	
+	if (HSDiv < 4)
+		return -EINVAL;
+	
+
+	fDCO = (u64)fOut * (u64)N * (u64)HSDiv;
+	printk("fdco %16llx\n", fDCO);
+	RFreq = fDCO<<28;
+	printk("%16llx %16llx\n", fDCO, RFreq);
+
+	fxtal = m_fXtal; 
+	do_div(RFreq, fxtal);
+	printk("%16llx %d\n", RFreq, fxtal);
+	RF = RFreq;
+	
+	// printk("fOut = %d fXtal = %d fDCO = %d HDIV = %d, N = %d, RFreq = %d\n",fOut,m_fXtal,fDCO,HSDiv,N,RFreq);
+	// printk("%16llx\n", RF);
+
+	Data[0] = (u8)( ((HSDiv - 4) << 5) | ((N - 1) >> 2) );
+	Data[1] = (u8)( (((N - 1) & 0x03) << 6) | (( RF >> 32 ) & 0x3F ) );
+	Data[2] = (u8)( (RF >> 24) & 0xFF );
+	Data[3] = (u8)( (RF >> 16) & 0xFF );
+	Data[4] = (u8)( (RF >>  8) & 0xFF );
+	Data[5] = (u8)( (RF      ) & 0xFF );
+	
+	printk(" Data = %02x %02x %02x %02x %02x %02x\n",
+	       Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]);
+	mod_si598_writereg(dev, 7, Data[0]);
+	mod_si598_writereg(dev, 8, Data[1]);
+	mod_si598_writereg(dev, 9, Data[2]);
+	mod_si598_writereg(dev, 10, Data[3]);
+	mod_si598_writereg(dev, 11, Data[4]);
+	mod_si598_writereg(dev, 12, Data[5]);
+
+	mod_si598_writereg(dev, 137, 0x00);
+	mod_si598_writereg(dev, 135, 0x40);
+	return 0;
+}
+
+
+static void mod_bypass_equalizer(struct ddb *dev, int bypass)
+{
+	u32  RegValue;
+	
+	RegValue = ddbreadl(dev, IQOUTPUT_CONTROL);
+	RegValue &= ~IQOUTPUT_CONTROL_BYPASS_EQUALIZER;
+	RegValue |= (bypass ? IQOUTPUT_CONTROL_BYPASS_EQUALIZER : 0x00);
+	ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
+}
+
+static int mod_set_equalizer(struct ddb *dev, u32 Num, s16 *cTable)
+{
+	u32 i, adr = IQOUTPUT_EQUALIZER_0;
+	
+	if (Num > 11) 
+		return -EINVAL;
+
+	for (i = 0; i < 11 - Num; i += 1) {
+		ddbwritel(dev, 0, adr);
+		adr += 4;
+	}
+	for (i = 0; i < Num; i += 1) {
+		ddbwritel(dev, (u32) cTable[i], adr);
+		adr += 4;
+	}
+	return 0;
+}
+
+static int mod_init_dac_input(struct ddb *dev)
+{
+	u8 Set = 0;
+	u8 Hld = 0;
+	u8 Sample = 0; 
+	
+	u8 Seek = 0;
+	u8 ReadSeek = 0;
+	
+	u8 SetTable[32];
+	u8 HldTable[32];
+	u8 SeekTable[32];
+
+	u8 Sample1 = 0xFF;
+	u8 Sample2 = 0xFF;
+	
+	u8 SelectSample = 0xFF;
+	u8 DiffMin = 0xFF;
+
+	for (Sample = 0; Sample < 32; Sample++ ) {
+		Set = 0;
+		Hld = 0;
+		
+		mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
+		mod_write_dac_register(dev, 0x05, Sample);
+		mod_read_dac_register(dev, 0x06, &ReadSeek);
+		Seek = ReadSeek & 0x01;
+		SeekTable[Sample] = Seek;
+		
+		HldTable[Sample] = 15;
+
+		for (Hld = 1; Hld < 16; Hld += 1) {
+			mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
+			mod_read_dac_register(dev, 0x06, &ReadSeek);
+			
+			if ((ReadSeek & 0x01) != Seek) 
+			{
+				HldTable[Sample] = Hld;
+				break;
+			}
+		}
+		
+		Hld = 0;
+		SetTable[Sample] = 15;
+		for (Set = 1; Set < 16; Set += 1) {
+			mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
+			mod_read_dac_register(dev, 0x06, &ReadSeek);
+			
+			if( (ReadSeek & 0x01) != Seek ) {
+				SetTable[Sample] = Set;
+				break;
+			}
+		}
+	}
+	
+	Seek = 1;
+	for (Sample = 0; Sample < 32; Sample += 1 ) {
+		// printk(" %2d: %d %2d %2d\n", Sample,SeekTable[Sample],SetTable[Sample],HldTable[Sample]);
+		
+		if (Sample1 == 0xFF && SeekTable[Sample] == 1 && Seek == 0 ) 
+			Sample1 = Sample;
+		if (Sample1 != 0xFF && Sample2 == 0xFF && SeekTable[Sample] == 0 && Seek == 1 )
+			Sample2 = Sample;
+		Seek = SeekTable[Sample];
+	}
+	
+	if (Sample1 == 0xFF || Sample2 == 0xFF ) {
+		printk(" No valid window found\n");
+		return -EINVAL;
+	}
+	
+	printk(" Window = %d - %d\n", Sample1, Sample2);
+
+	for (Sample = Sample1; Sample < Sample2; Sample += 1) {
+		if (SetTable[Sample] < HldTable[Sample]) {
+			if (HldTable[Sample] - SetTable[Sample] < DiffMin) {
+				DiffMin = HldTable[Sample] - SetTable[Sample];
+				SelectSample = Sample;
+			}
+		}
+	}
+	
+	printk("Select Sample %d\n", SelectSample);
+	
+	if (SelectSample == 0xFF) {
+		printk("No valid sample found\n");
+		return -EINVAL;
+	}
+	
+	if (HldTable[SelectSample] + SetTable[SelectSample] < 8 ) {
+		printk("Too high jitter\n");
+		return -EINVAL;
+	}
+	
+	mod_write_dac_register(dev, 0x04, 0x00);
+	mod_write_dac_register(dev, 0x05, (SelectSample - 1) & 0x1F);
+	mod_read_dac_register(dev, 0x06, &Seek);
+	mod_write_dac_register(dev, 0x05, (SelectSample + 1) & 0x1F);
+	mod_read_dac_register(dev, 0x06,&ReadSeek);
+	Seek &= ReadSeek;
+	
+	mod_write_dac_register(dev, 0x05, SelectSample);
+	mod_read_dac_register(dev, 0x06, &ReadSeek);
+	Seek &= ReadSeek;
+	if( (Seek & 0x01) == 0 ) {
+		printk("Insufficient timing margin\n");
+		return -EINVAL;
+	}
+	printk("Done\n");
+	return 0;
+}
+
+static void mod_set_up1(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
+{
+	u32 RDiv = Ext / Ref;
+
+	Frequency = Frequency / Ref;
+	mod_set_up_converter_vco1(dev, 0x360001 | (RDiv << 2)); 
+	mod_set_up_converter_vco1(dev, 0x0ff128);
+	mod_set_up_converter_vco1(dev, 0x02 | (Frequency << 8));
+}
+
+static void mod_set_up2(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
+{
+	u32 Rdiv = Ext / Ref;
+	u32 PreScale = 8;
+
+	Frequency = Frequency / Ref;
+	mod_set_up_converter_vco2(dev, 0x360001 | (Rdiv << 2));
+	mod_set_up_converter_vco2(dev, 0x0fc128 | (((PreScale - 8) / 8) << 22));
+	mod_set_up_converter_vco2(dev, 0x02 | ((Frequency / PreScale) << 8) 
+				  | (Frequency & (PreScale - 1)) << 2);
+}
+
+static int mod_set_down(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
+{
+	u32 BandSelect = Ref * 8;
+	u32 RefMul = 1;
+	u32 RefDiv2 = 1;
+	u32 RefDiv = Ext * RefMul / (Ref * RefDiv2);
+	
+	if (Frequency < 2200 || Frequency > 4000) 
+		return -EINVAL; 
+
+	Frequency = Frequency / Ref;
+
+	mod_set_down_converter_vco(dev, 0x0080003C | ((BandSelect & 0xFF) << 12));
+	mod_set_down_converter_vco(dev, 0x00000003);
+	mod_set_down_converter_vco(dev, 0x18001E42 | ((RefMul-1) << 25) | 
+				   ((RefDiv2-1) << 24) | (RefDiv << 14) );
+	mod_set_down_converter_vco(dev, 0x08008021);
+	mod_set_down_converter_vco(dev, Frequency << 15);
+	return 0;
+}
+
+static int mod_set_dac_clock(struct ddb *dev, u32 Frequency)
+{
+	int hr, i;
+
+	if (Frequency) {
+		ddbwritel(dev, DAC_CONTROL_RESET, DAC_CONTROL);
+		msleep(10);
+		if (mod_set_si598(dev, Frequency)) {
+			printk("mod_set_si598 failed\n");
+			return -1;
+		}
+		msleep(50);
+		ddbwritel(dev, 0x000, DAC_CONTROL);
+		msleep(10);
+		mod_write_dac_register(dev, 0, 0x02);
+	}
+	
+	for (i = 0; i < 10; i++) { 
+		hr = mod_init_dac_input(dev);
+		if (hr == 0)
+			break;
+		msleep(100);
+	}
+	printk("mod_set_dac_clock OK\n");
+	return hr;
+}
+
+static void mod_set_dac_current(struct ddb *dev, u32 Current1, u32 Current2)
+{
+	mod_write_dac_register2(dev, 0x0b, Current1 & 0x3ff);
+	mod_write_dac_register2(dev, 0x0f, Current2 & 0x3ff);
+}
+
+static void mod_output_enable(struct ddb *dev, int enable)
+{
+
+	u32  RegValue;
+	
+	RegValue = ddbreadl(dev, IQOUTPUT_CONTROL);
+	RegValue &= ~(IQOUTPUT_CONTROL_ENABLE | IQOUTPUT_CONTROL_RESET);
+	ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
+
+	if (enable) {
+		ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_RESET, IQOUTPUT_CONTROL);
+		msleep(10);
+		ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
+		ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_ENABLE, IQOUTPUT_CONTROL);
+	}
+}
+
+static int mod_set_iq(struct ddb *dev, u32 steps, u32 chan, u32 freq)
+{
+	u32 i, j, k, fac = 8;
+	u32 s1 = 22, s2 = 33;
+	u64 amp = (1ULL << 17) - 1ULL; 
+	u64 s = 0, c = (amp << s1), ss;
+	u64 frq = 0xC90FDAA22168C234ULL;
+	u32 *iqtab;
+	u32 iqtabadr;
+	u32 volatile regval;
+
+	iqtab = kmalloc((steps + 1) * 4, GFP_KERNEL);
+	if (!iqtab)
+		return -ENOMEM;
+	frq = div64_u64(frq, steps * fac) >> (61 - s2);
+
+	/* create sine table */
+	for (i = 0; i <= steps * fac / 4; i++) {
+		if (!(i & (fac - 1))) {
+			j = i / fac;
+			ss = s >> s1;
+			// ss = ((s >> (s1 - 1)) + 1) >> 1;
+					
+			iqtab[j] = iqtab[steps / 2 - j] = ss;
+			iqtab[steps / 2 + j] = iqtab[steps - j] = -ss;
+		}
+		c -= ((s * frq) >> s2);
+		s += ((c * frq) >> s2);
+	}
+
+	iqtabadr = chan << 16;
+	ddbwritel(dev, chan & 0x0f, MODULATOR_IQTABLE_INDEX);
+	for (i = j = 0, k = steps / 4; i < steps; i++) {
+		ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_I,
+			  MODULATOR_IQTABLE_INDEX);
+		ddbwritel(dev, iqtab[j], MODULATOR_IQTABLE_DATA);
+		regval = ddbreadl(dev, MODULATOR_CONTROL);
+		ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_Q,
+			  MODULATOR_IQTABLE_INDEX);
+		ddbwritel(dev, iqtab[k], MODULATOR_IQTABLE_DATA);
+		regval = ddbreadl(dev, MODULATOR_CONTROL);
+		j += freq;
+		j %= steps;
+		k += freq;
+		k %= steps;
+	}
+	ddbwritel(dev, steps - 1, MODULATOR_IQTABLE_END);
+	kfree(iqtab);
+	return 0;
+}
+
+u32 eqtab[] = {
+	0x0000FFDB, 0x00000121, 0x0000FF0A, 0x000003D7, 
+	0x000001C4, 0x000005A5, 0x000009CC, 0x0000F50D, 
+	0x00001B23, 0x0000EEB7, 0x00006A28
+};
+
+static void mod_set_channelsumshift(struct ddb *dev, u32 shift)
+{
+	ddbwritel(dev, (shift & 3) << 2, MODULATOR_CONTROL);
+}
+
+static void mod_pre_eq_gain(struct ddb *dev, u16 gain)
+{
+	ddbwritel(dev, gain, IQOUTPUT_PRESCALER);
+}
+
+static void mod_post_eq_gain(struct ddb *dev, u16 igain, u16 qgain)
+{
+	ddbwritel(dev, ((u32)qgain << 16) | igain, IQOUTPUT_POSTSCALER);
+}
+
+static int set_base_frequency(struct ddb *dev, u32 freq)
+{
+	u32 Ext = 40;
+        u32 UP1Frequency = 290;
+        u32 UP2Frequency = 1896;
+	u32 down, freq10;
+
+	printk("set base to %u\n", freq);
+	dev->mod_base.frequency = freq;
+	freq /= 1000000;
+        freq10 = dev->mod_base.flat_start + 4;
+	down = freq + 9 * 8 + freq10 + UP1Frequency + UP2Frequency;
+
+        if ((freq10 + 9 * 8) > (dev->mod_base.flat_end - 4)) {
+		printk("Frequency out of range %d\n", freq10);
+		return -EINVAL;
+        }
+        if (down % 8) {
+		printk(" Invalid Frequency %d\n", down);
+		return -EINVAL;
+        }
+	return mod_set_down(dev, down, 8, Ext);
+}
+
+static int mod_init(struct ddb *dev, u32 Frequency)
+{
+	int stat = 0;
+	u8 *buffer;
+	struct DDMOD_FLASH *flash;
+	u32 Ext = 40;
+        u32 UP1Frequency = 290;
+        u32 UP2Frequency = 1896;
+	u32 DownFrequency;
+        u32 FrequencyCH10;
+	u32 iqfreq, iqsteps, i;
+
+	buffer = kmalloc(4096, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+	flash = (struct DDMOD_FLASH *) buffer;
+	
+	ddbridge_flashread(dev, buffer, DDMOD_FLASH_START, 4096);
+	
+	if (flash->Magic != DDMOD_FLASH_MAGIC && flash->Magic != 1) {
+		stat = -EINVAL;
+		goto fail;
+	}
+	printk("srate = %d\n", flash->DataSet[0].Symbolrate * 1000);
+
+	mod_output_enable(dev, 0);
+	stat = mod_set_dac_clock(dev, flash->DataSet[0].DACFrequency * 1000);
+	if (stat < 0) {
+		printk("setting DAC clock failed\n");
+		goto fail;
+	}
+	mod_set_dac_current(dev, 512, 512);
+
+	ddbwritel(dev, flash->DataSet[0].Control2, IQOUTPUT_CONTROL2);	
+
+	mod_set_up1(dev, UP1Frequency, 5, Ext);
+	mod_set_up2(dev, UP2Frequency, 8, Ext);
+
+        dev->mod_base.flat_start = flash->DataSet[0].FlatStart;
+        dev->mod_base.flat_end = flash->DataSet[0].FlatEnd;
+	
+	Frequency /= 1000000;
+        FrequencyCH10 = flash->DataSet[0].FlatStart + 4;
+	DownFrequency = Frequency + 9 * 8 + FrequencyCH10 + UP1Frequency + UP2Frequency;
+	printk("CH10 = %d, Down = %d\n", FrequencyCH10, DownFrequency);
+
+
+        if ((FrequencyCH10 + 9 * 8) > (flash->DataSet[0].FlatEnd - 4)) {
+		printk("Frequency out of range %d\n", FrequencyCH10);
+		stat = -EINVAL;
+		goto fail;
+        }
+
+        if (DownFrequency % 8 != 0 ) {
+		printk(" Invalid Frequency %d\n", DownFrequency);
+		stat = -EINVAL;
+		goto fail;
+        }
+
+	mod_set_down(dev, DownFrequency, 8, Ext);
+
+	for (i = 0; i < 10; i++) {
+		ddbwritel(dev, 0, CHANNEL_CONTROL(i));
+		
+		iqfreq = flash->DataSet[0].FrequencyFactor * (FrequencyCH10 + (9 - i) * 8);
+		iqsteps = flash->DataSet[0].IQTableLength;
+		mod_set_iq(dev, iqsteps, i, iqfreq);
+
+		dev->mod[i].modulation = QAM_256;
+	}
+	
+	mod_bypass_equalizer(dev, 1);
+	mod_set_equalizer(dev, 11, flash->DataSet[0].EQTap);
+	mod_bypass_equalizer(dev, 0);
+	mod_post_eq_gain(dev, flash->DataSet[0].PostScaleI, flash->DataSet[0].PostScaleQ);
+	mod_pre_eq_gain(dev, flash->DataSet[0].PreScale);
+	// mod_pre_eq_gain(dev, 0x0680);
+	printk("prescaler %04x\n", flash->DataSet[0].PreScale);
+	mod_set_channelsumshift(dev, 2);
+	mod_output_enable(dev, 1);
+
+	// mod_set_attenuator(dev, 10);
+fail:
+	kfree(buffer);
+	return stat;
+}
+
+
+void ddbridge_mod_rate_handler(unsigned long data)
+{
+	struct ddb_output *output = (struct ddb_output *) data;
+	struct ddb_dma *dma = output->dma;
+	struct ddb *dev = output->port->dev;
+	struct mod_state *mod= &dev->mod[output->nr];
+	
+	u32 chan = output->nr;
+	u32 OutPacketCount;
+	u32 InPacketCount;
+	u64 OutPackets, InPackets;
+	s64 PCRAdjust;
+	u32 PCRAdjustExt, PCRAdjustExtFrac, InPacketDiff, OutPacketDiff;
+	s32 PCRCorr;
+
+	s64 pcr;
+	s64 PCRIncrementDiff;
+	s64 PCRIncrement;
+	u64 mul;
+
+	if (!mod->do_handle)
+		return;
+	printk("rate_handler\n");
+
+	spin_lock(&dma->lock);
+	ddbwritel(dev, mod->Control | CHANNEL_CONTROL_FREEZE_STATUS,
+		  CHANNEL_CONTROL(output->nr));
+	
+	OutPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_OUT(chan));
+	if (OutPacketCount < mod->LastOutPacketCount )
+		mod->OutOverflowPacketCount += 1;
+	mod->LastOutPacketCount = OutPacketCount;
+
+	InPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_IN(chan));
+	if (InPacketCount < mod->LastInPacketCount )
+		mod->InOverflowPacketCount += 1;
+	mod->LastInPacketCount = InPacketCount;
+	
+	OutPackets = ((u64) (mod->OutOverflowPacketCount) << 20) | OutPacketCount;
+	InPackets = ((u64) (mod->InOverflowPacketCount) << 20) | InPacketCount;
+	
+	PCRAdjust = (s64) ((u64) ddbreadl(dev, CHANNEL_PCR_ADJUST_ACCUL(chan)) | 
+			   (((u64) ddbreadl(dev, CHANNEL_PCR_ADJUST_ACCUH(chan)) << 32)));
+	PCRAdjustExt = (u32)((PCRAdjust & 0x7FFFFFFF) >> 22);
+	PCRAdjustExtFrac = (u32)((PCRAdjust & 0x003FFFFF) >> 12);
+	PCRAdjust >>= 31;
+	InPacketDiff = (u32) (InPackets - mod->LastInPackets);
+	OutPacketDiff = (u32) (OutPackets - mod->LastOutPackets);
+	PCRCorr = 0;
+	
+	switch (mod->State) {
+	case CM_STARTUP:
+		if (mod->StateCounter) {
+			if (mod->StateCounter == 1) {
+				mul = (0x1000000 * (u64) (OutPacketDiff - InPacketDiff - InPacketDiff/1000));
+				if (OutPacketDiff)
+					mod->rate_inc = div_u64(mul, OutPacketDiff);
+				else
+					mod->rate_inc = 0;
+				printk("RI %08x\n", mod->rate_inc);
+				ddbwritel(dev, 	mod->rate_inc, CHANNEL_RATE_INCR(output->nr));
+				mod_busy(dev, output->nr);
+// #define PACKET_CLOCKS  (27000000ULL*1504)
+// #define FACTOR  (1024<<12)
+// double Increment =  FACTOR*PACKET_CLOCKS/double(m_OutputBitrate);
+// double Decrement =  FACTOR*PACKET_CLOCKS/double(m_InputBitrate);
+				mod->PCRIncrement = 3348148758ULL;
+				if (InPacketDiff)
+					mod->PCRDecrement = div_u64(3348148758ULL * (u64) OutPacketDiff, 
+								    InPacketDiff); 
+				else
+					mod->PCRDecrement = 0;
+				mod_set_incs(output);
+			}
+			mod->StateCounter--; 
+			break;
+		}
+		if (InPacketDiff >= mod->MinInputPackets) {
+			mod->State = CM_ADJUST;
+			mod->Control |= CHANNEL_CONTROL_ENABLE_PCRADJUST;
+			mod->InPacketsSum = 0;
+			mod->OutPacketsSum = 0;
+			mod->PCRAdjustSum = 0;
+			mod->StateCounter = CM_AVERAGE;
+		}
+		break;
+		
+	case CM_ADJUST:
+		if (InPacketDiff < mod->MinInputPackets) {
+			printk("PCR Adjust reset  IN: %u  Min: %u\n",
+			       InPacketDiff, mod->MinInputPackets);
+			mod->InPacketsSum = 0;
+			mod->OutPacketsSum = 0;
+			mod->PCRAdjustSum = 0;
+			mod->StateCounter = CM_AVERAGE;
+			ddbwritel(dev, 
+				  (mod->Control | CHANNEL_CONTROL_FREEZE_STATUS) & 
+				  ~CHANNEL_CONTROL_ENABLE_PCRADJUST,
+				  CHANNEL_CONTROL(chan));
+			break;
+		} 
+
+		mod->PCRAdjustSum += (s32) PCRAdjust;
+		mod->InPacketsSum += InPacketDiff;
+		mod->OutPacketsSum += OutPacketDiff;
+		if (mod->StateCounter--) 
+			break;
+
+		if (mod->OutPacketsSum)
+			PCRIncrement = div_s64((s64)mod->InPacketsSum * 
+					       (s64)mod->PCRDecrement + 
+					       (s64)(mod->OutPacketsSum >> 1) ,
+					       mod->OutPacketsSum);
+		else
+			PCRIncrement = 0;
+		
+		if( mod->PCRAdjustSum > 0 ) 
+			PCRIncrement = RoundPCRDown(PCRIncrement);
+		else    
+			PCRIncrement = RoundPCRUp(PCRIncrement);
+		
+		PCRIncrementDiff = PCRIncrement - mod->PCRIncrement;
+		if( PCRIncrementDiff > HW_LSB_MASK )
+			PCRIncrementDiff = HW_LSB_MASK;
+		if( PCRIncrementDiff < -HW_LSB_MASK ) 
+			PCRIncrementDiff = -HW_LSB_MASK;
+		
+		mod->PCRIncrement += PCRIncrementDiff;
+		pcr = ConvertPCR(mod->PCRIncrement);
+		printk("outl %016llx\n", pcr);
+		ddbwritel(dev, 	pcr & 0xffffffff, 
+			  CHANNEL_PCR_ADJUST_OUTL(output->nr));
+		ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
+			  CHANNEL_PCR_ADJUST_OUTH(output->nr));
+		mod_busy(dev, chan);
+
+		PCRCorr = (s32) (PCRIncrementDiff >> HW_LSB_SHIFT);
+		mod->PCRRunningCorr += PCRCorr;
+		
+		mod->InPacketsSum = 0;
+		mod->OutPacketsSum = 0;
+		mod->PCRAdjustSum = 0;
+		mod->StateCounter = CM_AVERAGE;
+		break;
+		
+	default:
+		break;
+	}
+	ddbwritel(dev, mod->Control, CHANNEL_CONTROL(chan));
+	
+	mod->LastInPackets = InPackets;
+	mod->LastOutPackets = OutPackets;
+	mod->LastPCRAdjust = (s32) PCRAdjust;
+
+	printk("chan %d out %016llx in %016llx indiff %08x\n", chan, OutPackets, InPackets, InPacketDiff);
+	printk("cnt  %d pcra %016llx pcraext %08x pcraextfrac %08x pcrcorr %08x pcri %016llx\n", 
+	       mod->StateCounter, PCRAdjust, PCRAdjustExt, PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement);
+	// Channel,OutPackets,InPackets,InPacketDiff,PCRAdjust,PCRAdjustExt,PCRAdjustExtFrac,PCRCorr, mod->PCRRunningCorr,mod->StateCounter ));
+	spin_unlock(&dma->lock);
+}
+	      
+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb *dev = output->port->dev;
+	
+	// unsigned long arg = (unsigned long) parg;
+	int ret = 0;
+
+	switch (cmd) {
+	case DVB_MOD_SET:
+	{
+		struct dvb_mod_params *mp = parg;
+		
+		if (mp->base_frequency != dev->mod_base.frequency)
+			if (set_base_frequency(dev, mp->base_frequency))
+				return -EINVAL;
+		mod_set_attenuator(dev, mp->attenuator);
+		break;
+	}
+	case DVB_MOD_CHANNEL_SET:
+	{
+		struct dvb_mod_channel_params *cp = parg;
+
+		if (cp->modulation > QAM_256)
+			return -EINVAL;
+		dev->mod[output->nr].modulation = cp->modulation;
+		dev->mod[output->nr].rate_inc = cp->rate_increment;
+		ddbwritel(dev, dev->mod[output->nr].rate_inc, CHANNEL_RATE_INCR(output->nr));
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+int ddbridge_mod_init(struct ddb *dev)
+{
+	return mod_init(dev, 722000000);
+}
-- 
1.8.4.2

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

* [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (8 preceding siblings ...)
  2013-11-03  0:41 ` [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card Maik Broemme
@ 2013-11-03  0:44 ` Maik Broemme
  2013-11-03 10:49   ` Mauro Carvalho Chehab
  2013-11-03  0:45 ` [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes Maik Broemme
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:44 UTC (permalink / raw)
  To: Linux Media Mailing List

Updated ddbridge driver to version 0.9.10.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/ddbridge-core.c | 3085 ++++++++++++++++++++--------
 1 file changed, 2236 insertions(+), 849 deletions(-)

diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 9375f30..1d8ee74 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1,284 +1,216 @@
 /*
- * ddbridge.c: Digital Devices PCIe bridge driver
+ *  ddbridge-core.c: Digital Devices PCIe bridge driver
  *
- * Copyright (C) 2010-2011 Digital Devices GmbH
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
  *
- * 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 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.
  *
- * 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
+ *  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
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/timer.h>
-#include <linux/i2c.h>
-#include <linux/swab.h>
-#include <linux/vmalloc.h>
 #include "ddbridge.h"
-
 #include "ddbridge-regs.h"
 
-#include "tda18271c2dd.h"
+#include "cxd2843.h"
+#include "lnbh24.h"
 #include "stv6110x.h"
 #include "stv090x.h"
-#include "lnbh24.h"
+#include "tda18212dd.h"
+#include "stv0367dd.h"
+#ifdef CONFIG_DVB_TDA18212
+#include "tda18212.h"
+#endif
+#ifdef CONFIG_DVB_DRXK
 #include "drxk.h"
+#include "tda18271c2dd.h"
+#endif
 
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* MSI had problems with lost interrupts, fixed but needs testing */
-#undef CONFIG_PCI_MSI
+static DEFINE_MUTEX(redirect_lock);
 
-/******************************************************************************/
+static struct workqueue_struct *ddb_wq;
+static int adapter_alloc;
 
-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
-}
+module_param(adapter_alloc, int, 0444);
+MODULE_PARM_DESC(adapter_alloc, "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
 
-static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
-{
-	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
-				   .buf  = &reg, .len   = 1 },
-				  {.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
+static int ci_bitrate = 72000;
+module_param(ci_bitrate, int, 0444);
+MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI.");
 
-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
-			  u16 reg, u8 *val)
-{
-	u8 msg[2] = {reg>>8, reg&0xff};
-	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-				   .buf  = msg, .len   = 2},
-				  {.addr = adr, .flags = I2C_M_RD,
-				   .buf  = val, .len   = 1} };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
+static int ts_loop = -1;
+module_param(ts_loop, int, 0444);
+MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop");
 
-static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
-{
-	struct ddb *dev = i2c->dev;
-	int stat;
-	u32 val;
+#define DDB_MAX_ADAPTER 32
+static struct ddb *ddbs[DDB_MAX_ADAPTER];
 
-	i2c->done = 0;
-	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
-	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
-	if (stat <= 0) {
-		printk(KERN_ERR "I2C timeout\n");
-		{ /* MSI debugging*/
-			u32 istat = ddbreadl(INTERRUPT_STATUS);
-			printk(KERN_ERR "IRS %08x\n", istat);
-			ddbwritel(istat, INTERRUPT_ACK);
-		}
-		return -EIO;
-	}
-	val = ddbreadl(i2c->regs+I2C_COMMAND);
-	if (val & 0x70000)
-		return -EIO;
-	return 0;
-}
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
-			       struct i2c_msg msg[], int num)
+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
 {
-	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
-	struct ddb *dev = i2c->dev;
-	u8 addr = 0;
-
-	if (num)
-		addr = msg[0].addr;
-
-	if (num == 2 && msg[1].flags & I2C_M_RD &&
-	    !(msg[0].flags & I2C_M_RD)) {
-		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
-			    msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len|(msg[1].len << 16),
-			  i2c->regs+I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 1)) {
-			memcpy_fromio(msg[1].buf,
-				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
-				      msg[1].len);
-			return num;
-		}
-	}
+	u32 i, base;
+	u64 mem;
 
-	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
-		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 2))
-			return num;
-	}
-	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
-		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 3)) {
-			ddbcpyfrom(msg[0].buf,
-				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
-			return num;
-		}
+	if (!dma)
+		return;
+	base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100;
+	for (i = 0; i < dma->num; i++) {
+		mem = dma->pbuf[i];
+		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
+		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
 	}
-	return -EIO;
+	dma->bufreg = (dma->div << 16) | 
+		((dma->num & 0x1f) << 11) | 
+		((dma->size >> 7) & 0x7ff);
 }
 
-
-static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
+static void ddb_set_dma_tables(struct ddb *dev)
 {
-	return I2C_FUNC_SMBUS_EMUL;
-}
+	u32 i;
 
-struct i2c_algorithm ddb_i2c_algo = {
-	.master_xfer   = ddb_i2c_master_xfer,
-	.functionality = ddb_i2c_functionality,
-};
+	for (i = 0; i < dev->info->port_num * 2; i++)
+		ddb_set_dma_table(dev, dev->input[i].dma);
+	for (i = 0; i < dev->info->port_num; i++)
+		ddb_set_dma_table(dev, dev->output[i].dma);
+}
 
-static void ddb_i2c_release(struct ddb *dev)
+static void ddb_redirect_dma(struct ddb *dev,
+			     struct ddb_dma *sdma,
+			     struct ddb_dma *ddma)
 {
-	int i;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
+	u32 i, base;
+	u64 mem;
 
-	for (i = 0; i < dev->info->port_num; i++) {
-		i2c = &dev->i2c[i];
-		adap = &i2c->adap;
-		i2c_del_adapter(adap);
+	sdma->bufreg = ddma->bufreg;
+	base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100;
+	for (i = 0; i < ddma->num; i++) {
+		mem = ddma->pbuf[i];
+		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
+		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
 	}
 }
 
-static int ddb_i2c_init(struct ddb *dev)
+static int ddb_unredirect(struct ddb_port *port)
 {
-	int i, j, stat = 0;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		i2c = &dev->i2c[i];
-		i2c->dev = dev;
-		i2c->nr = i;
-		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
-		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
-		i2c->regs = 0x80 + i * 0x20;
-		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
-		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
-			  i2c->regs + I2C_TASKADDRESS);
-		init_waitqueue_head(&i2c->wq);
-
-		adap = &i2c->adap;
-		i2c_set_adapdata(adap, i2c);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
-#else
-#ifdef I2C_CLASS_TV_ANALOG
-		adap->class = I2C_CLASS_TV_ANALOG;
-#endif
-#endif
-		strcpy(adap->name, "ddbridge");
-		adap->algo = &ddb_i2c_algo;
-		adap->algo_data = (void *)i2c;
-		adap->dev.parent = &dev->pdev->dev;
-		stat = i2c_add_adapter(adap);
-		if (stat)
-			break;
+	struct ddb_input *oredi, *iredi = 0;
+	struct ddb_output *iredo = 0;
+	
+	// printk("unredirect %d.%d\n", port->dev->nr, port->nr);
+	mutex_lock(&redirect_lock);
+	if (port->output->dma->running) {
+		mutex_unlock(&redirect_lock);
+		return -EBUSY;
 	}
-	if (stat)
-		for (j = 0; j < i; j++) {
-			i2c = &dev->i2c[j];
-			adap = &i2c->adap;
-			i2c_del_adapter(adap);
-		}
-	return stat;
+	oredi = port->output->redi;
+	if (!oredi)
+		goto done;
+	if (port->input[0]) {
+		iredi = port->input[0]->redi;
+		iredo = port->input[0]->redo;
+		
+		if (iredo) {
+			iredo->port->output->redi = oredi;
+			if (iredo->port->input[0]) {
+				iredo->port->input[0]->redi = iredi;
+				ddb_redirect_dma(oredi->port->dev, 
+						 oredi->dma, iredo->dma);
+			}
+			port->input[0]->redo = 0;
+			ddb_set_dma_table(port->dev, port->input[0]->dma);
+		} 
+		oredi->redi = iredi;
+		port->input[0]->redi = 0;
+	}
+	oredi->redo = 0;
+	port->output->redi = 0;
+
+	ddb_set_dma_table(oredi->port->dev, oredi->dma);
+done:
+	mutex_unlock(&redirect_lock);
+	return 0;
 }
 
+static int ddb_redirect(u32 i, u32 p)
+{
+	struct ddb *idev = ddbs[(i >> 4) & 0x1f];
+	struct ddb_input *input, *input2;
+	struct ddb *pdev = ddbs[(p >> 4) & 0x1f];
+	struct ddb_port *port;
 
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
+	if (!idev->has_dma || !pdev->has_dma)
+		return -EINVAL;
+	if (!idev || !pdev)
+		return -EINVAL;
 
-#if 0
-static void set_table(struct ddb *dev, u32 off,
-		      dma_addr_t *pbuf, u32 num)
-{
-	u32 i, base;
-	u64 mem;
+	port = &pdev->port[p & 0x0f];
+	if (!port->output)
+		return -EINVAL;
+	if (ddb_unredirect(port))
+		return -EBUSY;
 
-	base = DMA_BASE_ADDRESS_TABLE + off;
-	for (i = 0; i < num; i++) {
-		mem = pbuf[i];
-		ddbwritel(mem & 0xffffffff, base + i * 8);
-		ddbwritel(mem >> 32, base + i * 8 + 4);
-	}
-}
-#endif
+	if (i == 8)
+		return 0;
 
-static void ddb_address_table(struct ddb *dev)
-{
-	u32 i, j, base;
-	u64 mem;
-	dma_addr_t *pbuf;
-
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
-		pbuf = dev->input[i].pbuf;
-		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
+	input = &idev->input[i & 7];
+	if (!input) 
+		return -EINVAL;
+
+	mutex_lock(&redirect_lock);
+	if (port->output->dma->running || input->dma->running) {
+		mutex_unlock(&redirect_lock);
+		return -EBUSY;
 	}
-	for (i = 0; i < dev->info->port_num; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
-		pbuf = dev->output[i].pbuf;
-		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
+	if ((input2 = port->input[0])) {
+		if (input->redi) {
+			input2->redi = input->redi;
+			input->redi = 0;
+		} else
+			input2->redi = input;
 	}
+	input->redo = port->output;
+	port->output->redi = input;
+
+	ddb_redirect_dma(input->port->dev, input->dma, port->output->dma);
+	mutex_unlock(&redirect_lock);
+	return 0;
 }
 
-static void io_free(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
 {
 	int i;
 
-	for (i = 0; i < num; i++) {
-		if (vbuf[i]) {
-			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
-			vbuf[i] = 0;
+	if (!dma)
+		return;
+	for (i = 0; i < dma->num; i++) {
+		if (dma->vbuf[i]) {
+			pci_free_consistent(pdev, dma->size,
+					    dma->vbuf[i], dma->pbuf[i]);
+			dma->vbuf[i] = 0;
 		}
 	}
 }
 
-static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
 {
 	int i;
 
-	for (i = 0; i < num; i++) {
-		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
-		if (!vbuf[i])
+	if (!dma)
+		return 0;
+	for (i = 0; i < dma->num; i++) {
+		dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size,
+						    &dma->pbuf[i]);
+		if (!dma->vbuf[i])
 			return -ENOMEM;
 	}
 	return 0;
@@ -293,34 +225,24 @@ static int ddb_buffers_alloc(struct ddb *dev)
 		port = &dev->port[i];
 		switch (port->class) {
 		case DDB_PORT_TUNER:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
+			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
 				return -1;
-			if (io_alloc(dev->pdev, port->input[1]->vbuf,
-				     port->input[1]->pbuf,
-				     port->input[1]->dma_buf_size,
-				     port->input[1]->dma_buf_num) < 0)
+			if (dma_alloc(dev->pdev, port->input[1]->dma, 0) < 0)
 				return -1;
 			break;
 		case DDB_PORT_CI:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
+		case DDB_PORT_LOOP:
+			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
 				return -1;
-			if (io_alloc(dev->pdev, port->output->vbuf,
-				     port->output->pbuf,
-				     port->output->dma_buf_size,
-				     port->output->dma_buf_num) < 0)
+		case DDB_PORT_MOD:
+			if (dma_alloc(dev->pdev, port->output->dma, 1) < 0)
 				return -1;
 			break;
 		default:
 			break;
 		}
 	}
-	ddb_address_table(dev);
+	ddb_set_dma_tables(dev);
 	return 0;
 }
 
@@ -328,112 +250,171 @@ static void ddb_buffers_free(struct ddb *dev)
 {
 	int i;
 	struct ddb_port *port;
-
+	
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
-		io_free(dev->pdev, port->input[0]->vbuf,
-			port->input[0]->pbuf,
-			port->input[0]->dma_buf_size,
-			port->input[0]->dma_buf_num);
-		io_free(dev->pdev, port->input[1]->vbuf,
-			port->input[1]->pbuf,
-			port->input[1]->dma_buf_size,
-			port->input[1]->dma_buf_num);
-		io_free(dev->pdev, port->output->vbuf,
-			port->output->pbuf,
-			port->output->dma_buf_size,
-			port->output->dma_buf_num);
+		
+		if (port->input[0])
+			dma_free(dev->pdev, port->input[0]->dma, 0);
+		if (port->input[1])
+			dma_free(dev->pdev, port->input[1]->dma, 0);
+		if (port->output)
+			dma_free(dev->pdev, port->output->dma, 1);
 	}
 }
 
-static void ddb_input_start(struct ddb_input *input)
+static void ddb_output_start(struct ddb_output *output)
 {
-	struct ddb *dev = input->port->dev;
+	struct ddb *dev = output->port->dev;
+	u32 con2;
 
-	spin_lock_irq(&input->lock);
-	input->cbuf = 0;
-	input->coff = 0;
+	con2 = ((output->port->obr << 13) + 71999) / 72000; 
+	con2 = (con2 << 16) | output->port->gap;
 
-	/* reset */
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+	if (output->dma) {
+		spin_lock_irq(&output->dma->lock);
+		output->dma->cbuf = 0;
+		output->dma->coff = 0;
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
+	}
+	if (output->port->class == DDB_PORT_MOD) 
+		ddbridge_mod_output_start(output);
+	else {
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr));
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+		ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr));
+		ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr));
+	}
+	if (output->dma) {
+		ddbwritel(dev, output->dma->bufreg, DMA_BUFFER_SIZE(output->dma->nr));
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
+		ddbwritel(dev, 1, DMA_BASE_READ);
+		ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr));
+	}
+	if (output->port->class != DDB_PORT_MOD) {
+		if (output->port->input[0]->port->class == DDB_PORT_LOOP)
+			// ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr));
+			// ddbwritel(dev, 0x45, TS_OUTPUT_CONTROL(output->nr));
+			ddbwritel(dev, (1 << 13) | 0x15, TS_OUTPUT_CONTROL(output->nr));
+		else
+			ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr));
+	}
+	if (output->dma) { 
+		output->dma->running = 1;
+		spin_unlock_irq(&output->dma->lock);
+	}
+}
 
-	ddbwritel((1 << 16) |
-		  (input->dma_buf_num << 11) |
-		  (input->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(input->nr));
-	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
+static void ddb_output_stop(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
 
-	ddbwritel(1, DMA_BASE_WRITE);
-	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
-	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
-	input->running = 1;
-	spin_unlock_irq(&input->lock);
+	if (output->dma)
+		spin_lock_irq(&output->dma->lock);
+	if (output->port->class == DDB_PORT_MOD) 
+		ddbridge_mod_output_stop(output);
+	else
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+	if (output->dma) {
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
+		output->dma->running = 0;
+		spin_unlock_irq(&output->dma->lock);
+	}
 }
 
 static void ddb_input_stop(struct ddb_input *input)
 {
 	struct ddb *dev = input->port->dev;
 
-	spin_lock_irq(&input->lock);
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
-	input->running = 0;
-	spin_unlock_irq(&input->lock);
+	if (input->dma)
+		spin_lock_irq(&input->dma->lock);
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	if (input->dma) {
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
+		input->dma->running = 0;
+		spin_unlock_irq(&input->dma->lock);
+	}
+	// printk("input_stop %d.%d\n", dev->nr, input->nr);
 }
 
-static void ddb_output_start(struct ddb_output *output)
+static void ddb_input_start(struct ddb_input *input)
 {
-	struct ddb *dev = output->port->dev;
+	struct ddb *dev = input->port->dev;
 
-	spin_lock_irq(&output->lock);
-	output->cbuf = 0;
-	output->coff = 0;
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel((1 << 16) |
-		  (output->dma_buf_num << 11) |
-		  (output->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(output->nr + 8));
-	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
-
-	ddbwritel(1, DMA_BASE_READ);
-	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
-	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
-	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
-	output->running = 1;
-	spin_unlock_irq(&output->lock);
+	if (input->dma) {
+		spin_lock_irq(&input->dma->lock);
+		input->dma->cbuf = 0;
+		input->dma->coff = 0;
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
+	}
+	ddbwritel(dev, 0, TS_INPUT_CONTROL2(input->nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+
+	if (input->dma) {
+		ddbwritel(dev, input->dma->bufreg, DMA_BUFFER_SIZE(input->dma->nr));
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
+		ddbwritel(dev, 1, DMA_BASE_WRITE);
+		ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr));
+	}
+	if (dev->info->type == DDB_OCTONET) 
+		ddbwritel(dev, 0x01, TS_INPUT_CONTROL(input->nr));
+	else
+		ddbwritel(dev, 0x09, TS_INPUT_CONTROL(input->nr));
+	if (input->dma) {
+		input->dma->running = 1;
+		spin_unlock_irq(&input->dma->lock);
+	}
+	// printk("input_start %d.%d\n", dev->nr, input->nr);
 }
 
-static void ddb_output_stop(struct ddb_output *output)
+static void ddb_input_start_all(struct ddb_input *input)
 {
-	struct ddb *dev = output->port->dev;
+	struct ddb_input *i = input;
+	struct ddb_output *o;
+	
+	mutex_lock(&redirect_lock);
+	while (i && (o = i->redo)) {
+		ddb_output_start(o);
+		if ((i = o->port->input[0]))
+			ddb_input_start(i);
+	}
+	ddb_input_start(input);
+	mutex_unlock(&redirect_lock);
+}
 
-	spin_lock_irq(&output->lock);
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
-	output->running = 0;
-	spin_unlock_irq(&output->lock);
+static void ddb_input_stop_all(struct ddb_input *input)
+{
+	struct ddb_input *i = input;
+	struct ddb_output *o;
+	
+	mutex_lock(&redirect_lock);
+	ddb_input_stop(input);
+	while (i && (o = i->redo)) {
+		ddb_output_stop(o);
+		if ((i = o->port->input[0]))
+			ddb_input_stop(i);
+	}
+	mutex_unlock(&redirect_lock);
 }
 
 static u32 ddb_output_free(struct ddb_output *output)
 {
-	u32 idx, off, stat = output->stat;
+	u32 idx, off, stat = output->dma->stat;
 	s32 diff;
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
-
-	if (output->cbuf != idx) {
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
-		    (output->dma_buf_size - output->coff <= 188))
+ 
+	if (output->dma->cbuf != idx) {
+		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
+		    (output->dma->size - output->dma->coff <= 188))
 			return 0;
 		return 188;
 	}
-	diff = off - output->coff;
+	diff = off - output->dma->coff;
 	if (diff <= 0 || diff > 188)
 		return 188;
 	return 0;
@@ -443,46 +424,46 @@ static ssize_t ddb_output_write(struct ddb_output *output,
 				const u8 *buf, size_t count)
 {
 	struct ddb *dev = output->port->dev;
-	u32 idx, off, stat = output->stat;
+	u32 idx, off, stat = output->dma->stat;
 	u32 left = count, len;
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
 
 	while (left) {
-		len = output->dma_buf_size - output->coff;
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+		len = output->dma->size - output->dma->coff;
+		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
 		    (off == 0)) {
 			if (len <= 188)
 				break;
 			len -= 188;
 		}
-		if (output->cbuf == idx) {
-			if (off > output->coff) {
-#if 1
-				len = off - output->coff;
+		if (output->dma->cbuf == idx) {
+			if (off > output->dma->coff) {
+				len = off - output->dma->coff;
 				len -= (len % 188);
 				if (len <= 188)
-
-#endif
 					break;
 				len -= 188;
 			}
 		}
 		if (len > left)
 			len = left;
-		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
+		if (copy_from_user(output->dma->vbuf[output->dma->cbuf] +
+				   output->dma->coff,
 				   buf, len))
 			return -EIO;
 		left -= len;
 		buf += len;
-		output->coff += len;
-		if (output->coff == output->dma_buf_size) {
-			output->coff = 0;
-			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
+		output->dma->coff += len;
+		if (output->dma->coff == output->dma->size) {
+			output->dma->coff = 0;
+			output->dma->cbuf = ((output->dma->cbuf + 1) %
+					     output->dma->num);
 		}
-		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
-			  DMA_BUFFER_ACK(output->nr + 8));
+		ddbwritel(dev, 
+			  (output->dma->cbuf << 11) | (output->dma->coff >> 7),
+			  DMA_BUFFER_ACK(output->dma->nr));
 	}
 	return count - left;
 }
@@ -490,139 +471,410 @@ static ssize_t ddb_output_write(struct ddb_output *output,
 static u32 ddb_input_avail(struct ddb_input *input)
 {
 	struct ddb *dev = input->port->dev;
-	u32 idx, off, stat = input->stat;
-	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
+	u32 idx, off, stat = input->dma->stat;
+	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr));
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
 
 	if (ctrl & 4) {
 		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
-		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
+		ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr));
 		return 0;
 	}
-	if (input->cbuf != idx)
+	if (input->dma->cbuf != idx || off < input->dma->coff)
 		return 188;
 	return 0;
 }
 
-static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
 {
 	struct ddb *dev = input->port->dev;
 	u32 left = count;
-	u32 idx, free, stat = input->stat;
+	u32 idx, off, free, stat = input->dma->stat;
 	int ret;
 
 	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
 
 	while (left) {
-		if (input->cbuf == idx)
+		if (input->dma->cbuf == idx)
 			return count - left;
-		free = input->dma_buf_size - input->coff;
+		free = input->dma->size - input->dma->coff;
 		if (free > left)
 			free = left;
-		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
-				   input->coff, free);
+		ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] +
+				   input->dma->coff, free);
 		if (ret)
 			return -EFAULT;
-		input->coff += free;
-		if (input->coff == input->dma_buf_size) {
-			input->coff = 0;
-			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
+		input->dma->coff += free;
+		if (input->dma->coff == input->dma->size) {
+			input->dma->coff = 0;
+			input->dma->cbuf = (input->dma->cbuf + 1) %
+				input->dma->num;
 		}
 		left -= free;
-		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
-			  DMA_BUFFER_ACK(input->nr));
+		ddbwritel(dev, 
+			  (input->dma->cbuf << 11) | (input->dma->coff >> 7),
+			  DMA_BUFFER_ACK(input->dma->nr));
 	}
 	return count;
 }
 
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
+static ssize_t ts_write(struct file *file, const char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb *dev = output->port->dev;
+	size_t left = count;
+	int stat;
+
+	if (!dev->has_dma)
+		return -EINVAL;
+	while (left) {
+		if (ddb_output_free(output) < 188) {
+			if (file->f_flags & O_NONBLOCK) 
+				break;
+			if (wait_event_interruptible(
+				    output->dma->wq,
+				    ddb_output_free(output) >= 188) < 0) 
+				break;
+		}
+		stat = ddb_output_write(output, buf, left);
+		if (stat < 0)
+			return stat;
+		buf += stat;
+		left -= stat;
+	}
+	return (left == count) ? -EAGAIN : (count - left);
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+		       size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	struct ddb *dev = output->port->dev;
+	int left, read;
+
+	if (!dev->has_dma)
+		return -EINVAL;
+	count -= count % 188;
+	left = count;
+	while (left) {
+		if (ddb_input_avail(input) < 188) {
+			if (file->f_flags & O_NONBLOCK)
+				break;
+			if (wait_event_interruptible(
+				    input->dma->wq, 
+				    ddb_input_avail(input) >= 188) < 0)
+				break;
+		}
+		read = ddb_input_read(input, buf, left);
+		left -= read;
+		buf += read;
+	}
+	return (left == count) ? -EAGAIN : (count - left);
+}
 
-#if 0
-static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
+static unsigned int ts_poll(struct file *file, poll_table *wait)
 {
-	int i;
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+
+	unsigned int mask = 0;
+
+	poll_wait(file, &input->dma->wq, wait);
+	poll_wait(file, &output->dma->wq, wait);
+	if (ddb_input_avail(input) >= 188)
+		mask |= POLLIN | POLLRDNORM;
+	if (ddb_output_free(output) >= 188)
+		mask |= POLLOUT | POLLWRNORM;
+	return mask;
+}
+
+static int ts_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!input)
+			return -EINVAL;
+		ddb_input_stop(input);
+	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+		ddb_output_stop(output);
+	}
+	return dvb_generic_release(inode, file);
+}
 
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		if (dev->input[i].fe == fe)
-			return &dev->input[i];
+static int ts_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!input)
+			return -EINVAL;
+		if (input->redo || input->redi)
+			return -EBUSY;
+	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
 	}
-	return NULL;
+	if ((err = dvb_generic_open(inode, file)) < 0)
+		return err;
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) 
+		ddb_input_start(input);
+	else if ((file->f_flags & O_ACCMODE) == O_WRONLY) 
+		ddb_output_start(output);
+	return err;
 }
-#endif
 
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+static int mod_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+		ddb_output_stop(output);
+	}
+	return dvb_generic_release(inode, file);
+}
+
+static int mod_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+	}
+	if ((err = dvb_generic_open(inode, file)) < 0)
+		return err;
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) 
+		ddb_output_start(output);
+	return err;
+}
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = ts_open,
+	.release = ts_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+};
+
+static struct dvb_device dvbdev_ci = {
+	.priv    = 0,
+	.readers = 1,
+	.writers = 1,
+	.users   = 2,
+	.fops    = &ci_fops,
+};
+
+static long mod_ioctl(struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
+}
+
+static const struct file_operations mod_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = mod_open,
+	.release = mod_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+	.unlocked_ioctl = mod_ioctl,
+};
+
+static struct dvb_device dvbdev_mod = {
+	.priv    = 0,
+	.readers = 1,
+	.writers = 1,
+	.users   = 2,
+	.fops    = &mod_fops,
+};
+
+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct ddb_input *input = fe->sec_priv;
 	struct ddb_port *port = input->port;
+	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
 	int status;
 
 	if (enable) {
 		mutex_lock(&port->i2c_gate_lock);
-		status = input->gate_ctrl(fe, 1);
+		status = dvb->gate_ctrl(fe, 1); 
 	} else {
-		status = input->gate_ctrl(fe, 0);
+		status = dvb->gate_ctrl(fe, 0);
 		mutex_unlock(&port->i2c_gate_lock);
 	}
 	return status;
 }
 
+#ifdef CONFIG_DVB_DRXK
 static int demod_attach_drxk(struct ddb_input *input)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct dvb_frontend *fe;
-	struct drxk_config config;
 
-	memset(&config, 0, sizeof(config));
-	config.microcode_name = "drxk_a3.mc";
-	config.qam_demod_parameter_count = 4;
-	config.adr = 0x29 + (input->nr & 1);
-
-	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
-	if (!input->fe) {
+	fe = dvb->fe = dvb_attach(drxk_attach,
+				  i2c, 0x29 + (input->nr&1),
+				  &dvb->fe2);
+	if (!fe) {
 		printk(KERN_ERR "No DRXK found!\n");
 		return -ENODEV;
 	}
 	fe->sec_priv = input;
-	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
 	return 0;
 }
+#endif
 
-static int tuner_attach_tda18271(struct ddb_input *input)
+struct cxd2843_cfg cxd2843_0 = {
+	.adr = 0x6c,
+};
+
+struct cxd2843_cfg cxd2843_1 = {
+	.adr = 0x6d,
+};
+
+static int demod_attach_cxd2843(struct ddb_input *input)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct dvb_frontend *fe;
-
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
-	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
-	if (!fe) {
-		printk(KERN_ERR "No TDA18271 found!\n");
+	
+	fe = dvb->fe = dvb_attach(cxd2843_attach, i2c,
+				  (input->nr & 1) ? &cxd2843_1 : &cxd2843_0);
+	if (!dvb->fe) {
+		printk(KERN_ERR "No cxd2843 found!\n");
 		return -ENODEV;
 	}
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
+	fe->sec_priv = input;
+	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
 	return 0;
 }
 
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
+struct stv0367_cfg stv0367dd_0 = {
+	.adr = 0x1f,
+	.xtal = 27000000,
+};
 
-static struct stv090x_config stv0900 = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
+struct stv0367_cfg stv0367dd_1 = {
+	.adr = 0x1e,
+	.xtal = 27000000,
+};
 
-	.xtal           = 27000000,
-	.address        = 0x69,
+static int demod_attach_stv0367dd(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
 
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	fe = dvb->fe = dvb_attach(stv0367_attach, i2c,
+				  (input->nr & 1) ? &stv0367dd_1 : &stv0367dd_0,
+				  &dvb->fe2);
+	if (!dvb->fe) {
+		printk(KERN_ERR "No stv0367 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+
+#ifdef CONFIG_DVB_DRXK
+static int tuner_attach_tda18271(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	if (dvb->fe->ops.i2c_gate_ctrl)
+		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1);
+	fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60);
+	if (dvb->fe->ops.i2c_gate_ctrl)
+		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18271 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+#endif
+
+static int tuner_attach_tda18212dd(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c,
+			(input->nr & 1) ? 0x63 : 0x60);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_DVB_TDA18212
+struct tda18212_config tda18212_0 = {
+	.i2c_address = 0x60,
+};
+
+struct tda18212_config tda18212_1 = {
+	.i2c_address = 0x63,
+};
+
+static int tuner_attach_tda18212(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+	struct tda18212_config *cfg;
+
+	cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0;
+	fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+#endif
+
+static struct stv090x_config stv0900 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x69,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
 
 	.repeater_level = STV090x_RPTLEVEL_16,
 
@@ -667,15 +919,16 @@ static int demod_attach_stv0900(struct ddb_input *input, int type)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
 	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 
-	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
-			       (input->nr & 1) ? STV090x_DEMODULATOR_1
-			       : STV090x_DEMODULATOR_0);
-	if (!input->fe) {
+	dvb->fe = dvb_attach(stv090x_attach, feconf, i2c,
+			     (input->nr & 1) ? STV090x_DEMODULATOR_1
+			     : STV090x_DEMODULATOR_0);
+	if (!dvb->fe) {
 		printk(KERN_ERR "No STV0900 found!\n");
 		return -ENODEV;
 	}
-	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
+	if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0,
 			0, (input->nr & 1) ?
 			(0x09 - type) : (0x0b - type))) {
 		printk(KERN_ERR "No LNBH24 found!\n");
@@ -687,18 +940,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type)
 static int tuner_attach_stv6110(struct ddb_input *input, int type)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
 	struct stv6110x_config *tunerconf = (input->nr & 1) ?
 		&stv6110b : &stv6110a;
 	struct stv6110x_devctl *ctl;
 
-	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
+	ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c);
 	if (!ctl) {
 		printk(KERN_ERR "No STV6110X found!\n");
 		return -ENODEV;
 	}
 	printk(KERN_INFO "attach tuner input %d adr %02x\n",
-			 input->nr, tunerconf->addr);
+	       input->nr, tunerconf->addr);
 
 	feconf->tuner_init          = ctl->tuner_init;
 	feconf->tuner_sleep         = ctl->tuner_sleep;
@@ -716,9 +970,9 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type)
 }
 
 static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv)
+				   int (*start_feed)(struct dvb_demux_feed *),
+				   int (*stop_feed)(struct dvb_demux_feed *),
+				   void *priv)
 {
 	dvbdemux->priv = priv;
 
@@ -734,10 +988,10 @@ static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
 }
 
 static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter)
+				      struct dvb_demux *dvbdemux,
+				      struct dmx_frontend *hw_frontend,
+				      struct dmx_frontend *mem_frontend,
+				      struct dvb_adapter *dvb_adapter)
 {
 	int ret;
 
@@ -759,318 +1013,610 @@ static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ddb_input *input = dvbdmx->priv;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 
-	if (!input->users)
-		ddb_input_start(input);
+	if (!dvb->users)
+		ddb_input_start_all(input);
 
-	return ++input->users;
+	return ++dvb->users;
 }
 
 static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ddb_input *input = dvbdmx->priv;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 
-	if (--input->users)
-		return input->users;
+	if (--dvb->users)
+		return dvb->users;
 
-	ddb_input_stop(input);
+	ddb_input_stop_all(input);
 	return 0;
 }
 
-
 static void dvb_input_detach(struct ddb_input *input)
 {
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
-
-	switch (input->attached) {
-	case 5:
-		if (input->fe2)
-			dvb_unregister_frontend(input->fe2);
-		if (input->fe) {
-			dvb_unregister_frontend(input->fe);
-			dvb_frontend_detach(input->fe);
-			input->fe = NULL;
-		}
-	case 4:
-		dvb_net_release(&input->dvbnet);
-
-	case 3:
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_demux *dvbdemux = &dvb->demux;
+
+	switch (dvb->attached) {
+	case 0x31:
+		if (dvb->fe2)
+			dvb_unregister_frontend(dvb->fe2);
+		if (dvb->fe)
+			dvb_unregister_frontend(dvb->fe);
+	case 0x30:
+		dvb_frontend_detach(dvb->fe);
+		dvb->fe = dvb->fe2 = NULL;
+	case 0x20:
+		dvb_net_release(&dvb->dvbnet);
+	case 0x11:
 		dvbdemux->dmx.close(&dvbdemux->dmx);
 		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->hw_frontend);
+					      &dvb->hw_frontend);
 		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->mem_frontend);
-		dvb_dmxdev_release(&input->dmxdev);
+					      &dvb->mem_frontend);
+		dvb_dmxdev_release(&dvb->dmxdev);
+	case 0x10:
+		dvb_dmx_release(&dvb->demux);
+	case 0x01:
+		break;
+	}
+	dvb->attached = 0x00;
+}
+
+static int dvb_register_adapters(struct ddb *dev)
+{
+	int i, ret = 0;
+	struct ddb_port *port;
+	struct dvb_adapter *adap;
+
+	if (adapter_alloc == 3 || dev->info->type == DDB_MOD) {
+		port = &dev->port[0];
+		adap = port->dvb[0].adap;
+		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+					   port->dev->dev,
+					   adapter_nr);
+		if (ret < 0)
+			return ret;
+		port->dvb[0].adap_registered = 1;
+		for (i = 0; i < dev->info->port_num; i++) {
+			port = &dev->port[i];
+			port->dvb[0].adap = adap;
+			port->dvb[1].adap = adap;
+		}
+		return 0;
+	}
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			adap = port->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge", 
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+
+			if (adapter_alloc > 0) {
+				port->dvb[1].adap = port->dvb[0].adap;
+				break;
+			}
+			adap = port->dvb[1].adap;
+			ret = dvb_register_adapter(adap, "DDBridge", 
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[1].adap_registered = 1;
+			break;
+
+		case DDB_PORT_CI:
+		case DDB_PORT_LOOP:
+			adap = port->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+			break;
+		default:
+			if (adapter_alloc < 2)
+				break;
+			adap = port->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void dvb_unregister_adapters(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+	struct ddb_dvb *dvb;
 
-	case 2:
-		dvb_dmx_release(&input->demux);
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
 
-	case 1:
-		dvb_unregister_adapter(adap);
+		dvb = &port->dvb[0];
+		if (dvb->adap_registered)
+			dvb_unregister_adapter(dvb->adap);
+		dvb->adap_registered = 0;
+		
+		dvb = &port->dvb[1];
+		if (dvb->adap_registered)
+			dvb_unregister_adapter(dvb->adap);
+		dvb->adap_registered = 0;
 	}
-	input->attached = 0;
 }
 
 static int dvb_input_attach(struct ddb_input *input)
 {
-	int ret;
+	int ret = 0;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct ddb_port *port = input->port;
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
-
-	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
-				   &input->port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0) {
-		printk(KERN_ERR "ddbridge: Could not register adapter."
-		       "Check if you enabled enough adapters in dvb-core!\n");
-		return ret;
-	}
-	input->attached = 1;
+	struct dvb_adapter *adap = dvb->adap;
+	struct dvb_demux *dvbdemux = &dvb->demux;
+
+	dvb->attached = 0x01;
 
 	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
 				      start_feed,
 				      stop_feed, input);
 	if (ret < 0)
 		return ret;
-	input->attached = 2;
+	dvb->attached = 0x10;
 
-	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
-					 &input->hw_frontend,
-					 &input->mem_frontend, adap);
+	ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev,
+					 &dvb->demux,
+					 &dvb->hw_frontend,
+					 &dvb->mem_frontend, adap);
 	if (ret < 0)
 		return ret;
-	input->attached = 3;
+	dvb->attached = 0x11;
 
-	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
+	ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux);
 	if (ret < 0)
 		return ret;
-	input->attached = 4;
+	dvb->attached = 0x20;
 
-	input->fe = 0;
+	dvb->fe = dvb->fe2 = 0;
 	switch (port->type) {
 	case DDB_TUNER_DVBS_ST:
 		if (demod_attach_stv0900(input, 0) < 0)
 			return -ENODEV;
 		if (tuner_attach_stv6110(input, 0) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
 		break;
 	case DDB_TUNER_DVBS_ST_AA:
 		if (demod_attach_stv0900(input, 1) < 0)
 			return -ENODEV;
 		if (tuner_attach_stv6110(input, 1) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
 		break;
+#ifdef CONFIG_DVB_DRXK
 	case DDB_TUNER_DVBCT_TR:
 		if (demod_attach_drxk(input) < 0)
 			return -ENODEV;
 		if (tuner_attach_tda18271(input) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		if (input->fe2) {
-			if (dvb_register_frontend(adap, input->fe2) < 0)
-				return -ENODEV;
-			input->fe2->tuner_priv = input->fe->tuner_priv;
-			memcpy(&input->fe2->ops.tuner_ops,
-			       &input->fe->ops.tuner_ops,
-			       sizeof(struct dvb_tuner_ops));
-		}
 		break;
+#endif
+	case DDB_TUNER_DVBCT_ST:
+		if (demod_attach_stv0367dd(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212dd(input) < 0)
+			return -ENODEV;
+		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_tda18212dd(input) < 0)
+			return -ENODEV;
+		break;
+	default:
+		return 0;
+	}
+	dvb->attached = 0x30;
+	if (dvb->fe) {
+		if (dvb_register_frontend(adap, dvb->fe) < 0)
+			return -ENODEV;
+	}
+	if (dvb->fe2) {
+		if (dvb_register_frontend(adap, dvb->fe2) < 0)
+			return -ENODEV;
+		dvb->fe2->tuner_priv = dvb->fe->tuner_priv;
+		memcpy(&dvb->fe2->ops.tuner_ops,
+		       &dvb->fe->ops.tuner_ops,
+		       sizeof(struct dvb_tuner_ops));
 	}
-	input->attached = 5;
+	dvb->attached = 0x31;
 	return 0;
 }
 
-/****************************************************************************/
-/****************************************************************************/
-
-static ssize_t ts_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
+static int port_has_encti(struct ddb_port *port)
 {
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	size_t left = count;
-	int stat;
+	u8 val;
+	int ret = ddb_i2c_read_reg(&port->i2c->adap, 0x20, 0, &val);
 
-	while (left) {
-		if (ddb_output_free(output) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    output->wq, ddb_output_free(output) >= 188) < 0)
-				break;
-		}
-		stat = ddb_output_write(output, buf, left);
-		if (stat < 0)
-			break;
-		buf += stat;
-		left -= stat;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
+	if (!ret) 
+		printk("[0x20]=0x%02x\n", val);
+
+	return ret ? 0 : 1;
 }
 
-static ssize_t ts_read(struct file *file, char *buf,
-		       size_t count, loff_t *ppos)
+static int port_has_cxd(struct ddb_port *port)
 {
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	int left, read;
+	u8 val;
+	u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; 
+	struct i2c_msg msgs[2] = {{ .addr = 0x40,  .flags = 0,
+				    .buf  = probe, .len   = 4 },
+				  { .addr = 0x40,  .flags = I2C_M_RD,
+				    .buf  = data,  .len   = 4 }};
+	val = i2c_transfer(&port->i2c->adap, msgs, 2);
+	if (val != 2)
+		return 0;
 
-	count -= count % 188;
-	left = count;
-	while (left) {
-		if (ddb_input_avail(input) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    input->wq, ddb_input_avail(input) >= 188) < 0)
-				break;
-		}
-		read = ddb_input_read(input, buf, left);
-		if (read < 0)
-			return read;
-		left -= read;
-		buf += read;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
+	if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43)
+		return 2;
+	return 1;
 }
 
-static unsigned int ts_poll(struct file *file, poll_table *wait)
+static int port_has_mach(struct ddb_port *port, u8 *id)
 {
-	/*
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	*/
-	unsigned int mask = 0;
+	u8 val;
+	u8 probe[1] = { 0x00 }, data[4]; 
+	struct i2c_msg msgs[2] = {{ .addr = 0x10,  .flags = 0,
+				    .buf  = probe, .len   = 1 },
+				  { .addr = 0x10,  .flags = I2C_M_RD,
+				    .buf  = data,  .len   = 4 }};
+	val = i2c_transfer(&port->i2c->adap, msgs, 2);
+	if (val != 2)
+		return 0;
+	
+	if (data[0] != 'D' || data[1] != 'F')
+		return 0;
 
-#if 0
-	if (data_avail_to_read)
-		mask |= POLLIN | POLLRDNORM;
-	if (data_avail_to_write)
-		mask |= POLLOUT | POLLWRNORM;
+	*id = data[2];
+	return 1;
+}
 
-	poll_wait(file, &read_queue, wait);
-	poll_wait(file, &write_queue, wait);
-#endif
-	return mask;
+static int port_has_stv0900(struct ddb_port *port)
+{
+	u8 val;
+	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
+		return 0;
+	return 1;
 }
 
-static const struct file_operations ci_fops = {
-	.owner   = THIS_MODULE,
-	.read    = ts_read,
-	.write   = ts_write,
-	.open    = dvb_generic_open,
-	.release = dvb_generic_release,
-	.poll    = ts_poll,
-	.mmap    = 0,
-};
+static int port_has_stv0900_aa(struct ddb_port *port)
+{
+	u8 val;
+	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
+		return 0;
+	return 1;
+}
 
-static struct dvb_device dvbdev_ci = {
-	.priv    = 0,
-	.readers = -1,
-	.writers = -1,
-	.users   = -1,
-	.fops    = &ci_fops,
-};
+static int port_has_drxks(struct ddb_port *port)
+{
+	u8 val;
+	if (ddb_i2c_read(&port->i2c->adap, 0x29, &val) < 0)
+		return 0;
+	if (ddb_i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
+		return 0;
+	return 1;
+}
 
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
+static int port_has_stv0367(struct ddb_port *port)
+{
+	u8 val;
+
+	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	return 1;
+}
 
-static void input_tasklet(unsigned long data)
+static int init_xo2(struct ddb_port *port)
 {
-	struct ddb_input *input = (struct ddb_input *) data;
-	struct ddb *dev = input->port->dev;
+	struct i2c_adapter *i2c =&port->i2c->adap;
+	u8 val, data[2];
+	int res;
+	
+	res = ddb_i2c_read_regs(i2c, 0x10, 0x04, data, 2);
+	if (res < 0)
+		return res;
 
-	spin_lock(&input->lock);
-	if (!input->running) {
-		spin_unlock(&input->lock);
-		return;
+	if (data[0] != 0x01)  {
+		printk(KERN_INFO "Port %d: invalid XO2\n", port->nr);
+		return -1;
 	}
-	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
 
-	if (input->port->class == DDB_PORT_TUNER) {
-		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
-			printk(KERN_ERR "Overflow input %d\n", input->nr);
-		while (input->cbuf != ((input->stat >> 11) & 0x1f)
-		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
-			dvb_dmx_swfilter_packets(&input->demux,
-						 input->vbuf[input->cbuf],
-						 input->dma_buf_size / 188);
-
-			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
-			ddbwritel((input->cbuf << 11),
-				  DMA_BUFFER_ACK(input->nr));
-			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
-		       }
+	ddb_i2c_read_reg(i2c, 0x10, 0x08, &val);
+	if (val != 0) {
+		ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x00); 
+		msleep(100);
 	}
-	if (input->port->class == DDB_PORT_CI)
-		wake_up(&input->wq);
-	spin_unlock(&input->lock);
+        /* Enable tuner power, disable pll, reset demods */
+	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x04); 
+	msleep(2);
+        /* Release demod resets */
+	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x07); 
+	msleep(2);
+
+        /* Start XO2 PLL */
+	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x87); 
+
+	return 0;
 }
 
-static void output_tasklet(unsigned long data)
+static void ddb_port_probe(struct ddb_port *port)
 {
-	struct ddb_output *output = (struct ddb_output *) data;
-	struct ddb *dev = output->port->dev;
+	struct ddb *dev = port->dev;
+	char *modname = "NO MODULE";
+	int val;
+	u8 id;
+
+	port->class = DDB_PORT_NONE;
 
-	spin_lock(&output->lock);
-	if (!output->running) {
-		spin_unlock(&output->lock);
+	if (dev->info->type == DDB_MOD) {
+		modname = "MOD";
+		port->class = DDB_PORT_MOD;
+		printk(KERN_INFO "Port %d: MOD\n", port->nr);
 		return;
 	}
-	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
-	wake_up(&output->wq);
-	spin_unlock(&output->lock);
-}
 
+	if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) {
+		modname = "CI internal";
+		port->class = DDB_PORT_CI;
+		port->type = DDB_CI_INTERNAL;
+	} else if ((val = port_has_cxd(port)) > 0) {
+		if (val == 1) {
+			modname = "CI";
+			port->class = DDB_PORT_CI;
+			port->type = DDB_CI_EXTERNAL_SONY;
+			ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		} else {
+			printk(KERN_INFO "Port %d: Uninitialized DuoFlex\n", port->nr);
+			return;
+		}
+	} else if (port_has_mach(port, &id)) {
+		char *xo2names[] = { "DUAL DVB-S2", "DUAL DVB-C/T/T2", "DUAL DVB-ISDBT",
+		                     "DUAL DVB-C/C2/T/T2", "DUAL ATSC", "DUAL DVB-C/C2/T/T2" };
+
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		id >>= 2;
+		if (id > 5) {
+			modname = "unknown XO2 DuoFlex";
+		} else {
+			port->class = DDB_PORT_TUNER;
+			port->type = DDB_TUNER_XO2 + id;
+			modname = xo2names[id];
+			init_xo2(port);
+		}
+	} else if (port_has_stv0900(port)) {
+		modname = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0900_aa(port)) {
+		modname = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST_AA;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_drxks(port)) {
+		modname = "DUAL DVB-C/T";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBCT_TR;
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0367(port)) {
+		modname = "DUAL DVB-C/T";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBCT_ST;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_encti(port)) {
+		modname = "ENCTI";
+		port->class = DDB_PORT_LOOP;
+	} else if (port->nr == ts_loop) {
+		modname = "TS LOOP";
+		port->class = DDB_PORT_LOOP;
+	}
+	printk(KERN_INFO "Port %d (TAB %d): %s\n", port->nr, port->nr + 1, modname);
+}
 
-struct cxd2099_cfg cxd_cfg = {
-	.bitrate =  62000,
-	.adr     =  0x40,
-	.polarity = 1,
-	.clock_mode = 1,
-};
+static int wait_ci_ready(struct ddb_ci *ci)
+{
+	u32 count = 10;
+	
+	ndelay(500);
+	do {
+		if (ddbreadl(ci->port->dev, 
+			     CI_CONTROL(ci->nr)) & CI_READY)
+			break;
+		usleep_range(1, 2);
+		if ((--count) == 0)
+			return -1;
+	} while (1);
+	return 0;
+}
 
-static int ddb_ci_attach(struct ddb_port *port)
+static int read_attribute_mem(struct dvb_ca_en50221 *ca,
+			      int slot, int address)
 {
-	int ret;
+	struct ddb_ci *ci = ca->data;
+	u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1);
 
-	ret = dvb_register_adapter(&port->output->adap,
-				   "DDBridge",
-				   THIS_MODULE,
-				   &port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0)
-		return ret;
-	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
-	if (!port->en) {
-		dvb_unregister_adapter(&port->output->adap);
-		return -ENODEV;
+	if (address > CI_BUFFER_SIZE)
+		return -1;
+	ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
+		  CI_DO_READ_ATTRIBUTES(ci->nr));
+	wait_ci_ready(ci);
+	val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
+	return val;
+}
+
+static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
+			       int address, u8 value)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
+		  CI_DO_ATTRIBUTE_RW(ci->nr));
+	wait_ci_ready(ci);
+	return 0;
+}
+
+static int read_cam_control(struct dvb_ca_en50221 *ca,
+			    int slot, u8 address)
+{
+	u32 count = 100;
+	struct ddb_ci *ci = ca->data;
+	u32 res;
+
+	ddbwritel(ci->port->dev, CI_READ_CMD | address,
+		  CI_DO_IO_RW(ci->nr));
+	ndelay(500);
+	do {
+		res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
+		if (res & CI_READY)
+			break;
+		usleep_range(1, 2);
+		if ((--count) == 0)
+			return -1;
+	} while (1);
+	return (0xff & res);
+}
+
+static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
+			     u8 address, u8 value)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
+		  CI_DO_IO_RW(ci->nr));
+	wait_ci_ready(ci);
+	return 0;
+}
+
+static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, CI_POWER_ON,
+		  CI_CONTROL(ci->nr));
+	msleep(100);
+	ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
+		  CI_CONTROL(ci->nr));
+	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
+		  CI_CONTROL(ci->nr));
+	udelay(20);
+	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
+		  CI_CONTROL(ci->nr));
+	return 0;
+}
+
+static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
+	msleep(300);
+	return 0;
+}
+
+static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
+
+	ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
+		  CI_CONTROL(ci->nr));
+	return 0;
+}
+
+static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	struct ddb_ci *ci = ca->data;
+	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
+	int stat = 0;
+	
+	if (val & CI_CAM_DETECT)
+		stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
+	if (val & CI_CAM_READY)
+		stat |= DVB_CA_EN50221_POLL_CAM_READY;
+	return stat;
+}
+
+static struct dvb_ca_en50221 en_templ = {
+	.read_attribute_mem  = read_attribute_mem,
+	.write_attribute_mem = write_attribute_mem,
+	.read_cam_control    = read_cam_control,
+	.write_cam_control   = write_cam_control,
+	.slot_reset          = slot_reset,
+	.slot_shutdown       = slot_shutdown,
+	.slot_ts_enable      = slot_ts_enable,
+	.poll_slot_status    = poll_slot_status,
+};
+
+static void ci_attach(struct ddb_port *port)
+{
+	struct ddb_ci *ci = 0;
+
+	ci = kzalloc(sizeof(*ci), GFP_KERNEL);
+	if (!ci)
+		return;
+	memcpy(&ci->en, &en_templ, sizeof(en_templ));
+	ci->en.data = ci;
+	port->en = &ci->en;
+	ci->port = port;
+	ci->nr = port->nr - 2;
+}
+
+struct cxd2099_cfg cxd_cfg = {
+	.bitrate =  72000,
+	.adr     =  0x40,
+	.polarity = 1,
+	.clock_mode = 1, // 2,
+};
+
+static int ddb_ci_attach(struct ddb_port *port)
+{
+	if (port->type == DDB_CI_EXTERNAL_SONY) {
+		cxd_cfg.bitrate = ci_bitrate;
+		port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
+		if (!port->en) 
+			return -ENODEV;
+		dvb_ca_en50221_init(port->dvb[0].adap,
+				    port->en, 0, 1);
 	}
-	ddb_input_start(port->input[0]);
-	ddb_output_start(port->output);
-	dvb_ca_en50221_init(&port->output->adap,
-			    port->en, 0, 1);
-	ret = dvb_register_device(&port->output->adap, &port->output->dev,
-				  &dvbdev_ci, (void *) port->output,
-				  DVB_DEVICE_SEC);
-	return ret;
+	if (port->type == DDB_CI_INTERNAL) {
+		ci_attach(port);
+		if (!port->en) 
+			return -ENODEV;
+		dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
+	}
+	return 0;
 }
 
 static int ddb_port_attach(struct ddb_port *port)
@@ -1083,9 +1629,26 @@ static int ddb_port_attach(struct ddb_port *port)
 		if (ret < 0)
 			break;
 		ret = dvb_input_attach(port->input[1]);
+		if (ret < 0)
+			break;
+		port->input[0]->redi = port->input[0];
+		port->input[1]->redi = port->input[1];
 		break;
 	case DDB_PORT_CI:
 		ret = ddb_ci_attach(port);
+		if (ret < 0)
+			break;
+	case DDB_PORT_LOOP:
+		ret = dvb_register_device(port->dvb[0].adap,
+					  &port->dvb[0].dev,
+					  &dvbdev_ci, (void *) port->output,
+					  DVB_DEVICE_CI);
+		break;
+	case DDB_PORT_MOD:
+		ret = dvb_register_device(port->dvb[0].adap,
+					  &port->dvb[0].dev,
+					  &dvbdev_mod, (void *) port->output,
+					  DVB_DEVICE_MOD);
 		break;
 	default:
 		break;
@@ -1100,6 +1663,11 @@ static int ddb_ports_attach(struct ddb *dev)
 	int i, ret = 0;
 	struct ddb_port *port;
 
+	if (dev->info->port_num) {
+		ret = dvb_register_adapters(dev);
+		if (ret < 0)
+			return ret;
+	}
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
 		ret = ddb_port_attach(port);
@@ -1116,125 +1684,210 @@ static void ddb_ports_detach(struct ddb *dev)
 
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
+	
 		switch (port->class) {
 		case DDB_PORT_TUNER:
 			dvb_input_detach(port->input[0]);
 			dvb_input_detach(port->input[1]);
 			break;
 		case DDB_PORT_CI:
-			if (port->output->dev)
-				dvb_unregister_device(port->output->dev);
+		case DDB_PORT_LOOP:
+			if (port->dvb[0].dev)
+				dvb_unregister_device(port->dvb[0].dev);
 			if (port->en) {
-				ddb_input_stop(port->input[0]);
-				ddb_output_stop(port->output);
 				dvb_ca_en50221_release(port->en);
 				kfree(port->en);
 				port->en = 0;
-				dvb_unregister_adapter(&port->output->adap);
 			}
 			break;
+		case DDB_PORT_MOD:
+			if (port->dvb[0].dev)
+				dvb_unregister_device(port->dvb[0].dev);
+			break;
 		}
 	}
+	dvb_unregister_adapters(dev);
 }
 
-/****************************************************************************/
-/****************************************************************************/
+/* Copy input DMA pointers to output DMA and ACK. */
+static void input_write_output(struct ddb_input *input,
+			       struct ddb_output *output)
+{
+	ddbwritel(output->port->dev,
+		  input->dma->stat, DMA_BUFFER_ACK(output->dma->nr));
+	output->dma->cbuf = (input->dma->stat >> 11) & 0x1f;
+	output->dma->coff = (input->dma->stat & 0x7ff) << 7;
+}
 
-static int port_has_ci(struct ddb_port *port)
+static void output_ack_input(struct ddb_output *output,
+			     struct ddb_input *input)
 {
-	u8 val;
-	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
+	ddbwritel(input->port->dev,
+		  output->dma->stat, DMA_BUFFER_ACK(input->dma->nr));
 }
 
-static int port_has_stv0900(struct ddb_port *port)
+static void input_write_dvb(struct ddb_input *input, 
+			    struct ddb_input *input2)
 {
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
-		return 0;
-	return 1;
+	struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1];
+	struct ddb_dma *dma, *dma2;
+	struct ddb *dev = input->port->dev;
+	int noack = 0;
+
+	dma = dma2 = input->dma;
+	/* if there also is an output connected, do not ACK. 
+	   input_write_output will ACK. */
+	if (input->redo) {
+		dma2 = input->redo->dma;
+		noack = 1;
+	}
+	while (dma->cbuf != ((dma->stat >> 11) & 0x1f)
+	       || (4 & dma->ctrl)) {
+		if (4 & dma->ctrl) {
+			// printk(KERN_ERR "Overflow dma %d\n", dma->nr);
+			if (noack) 
+				noack = 0;
+		}
+		dvb_dmx_swfilter_packets(&dvb->demux,
+					 dma2->vbuf[dma->cbuf],
+					 dma2->size / 188);
+		dma->cbuf = (dma->cbuf + 1) % dma2->num;
+		if (!noack)
+			ddbwritel(dev, (dma->cbuf << 11),  
+				  DMA_BUFFER_ACK(dma->nr));
+		dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+		dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+	}
 }
 
-static int port_has_stv0900_aa(struct ddb_port *port)
+static void input_work(struct work_struct *work)
 {
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
-		return 0;
-	return 1;
+	struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
+	struct ddb_input *input = (struct ddb_input *) dma->io;
+	struct ddb *dev = input->port->dev;
+
+	spin_lock(&dma->lock);
+	if (!dma->running) {
+		spin_unlock(&dma->lock);
+		return;
+	}
+	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+
+	if (input->redi)
+		input_write_dvb(input, input->redi);
+	if (input->redo)
+		input_write_output(input, input->redo);	
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
 }
 
-static int port_has_drxks(struct ddb_port *port)
+static void input_handler(unsigned long data)
 {
-	u8 val;
-	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
-		return 0;
-	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
-		return 0;
-	return 1;
+	struct ddb_input *input = (struct ddb_input *) data;
+	struct ddb_dma *dma = input->dma;
+
+	/* If there is no input connected, input_tasklet() will
+           just copy pointers and ACK. So, there is no need to go 
+	   through the tasklet scheduler. */
+	if (input->redi)
+		queue_work(ddb_wq, &dma->work);
+	else
+		input_work(&dma->work);
 }
 
-static void ddb_port_probe(struct ddb_port *port)
+/* TODO: hmm, don't really need this anymore. 
+   The output IRQ just copies some pointers, acks and wakes. */
+static void output_work(struct work_struct *work)
 {
-	struct ddb *dev = port->dev;
-	char *modname = "NO MODULE";
+}
 
-	port->class = DDB_PORT_NONE;
+static void output_handler(unsigned long data)
+{
+	struct ddb_output *output = (struct ddb_output *) data;
+	struct ddb_dma *dma = output->dma;
+	struct ddb *dev = output->port->dev;
 
-	if (port_has_ci(port)) {
-		modname = "CI";
-		port->class = DDB_PORT_CI;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_stv0900(port)) {
-		modname = "DUAL DVB-S2";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBS_ST;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_stv0900_aa(port)) {
-		modname = "DUAL DVB-S2";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBS_ST_AA;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_drxks(port)) {
-		modname = "DUAL DVB-C/T";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBCT_TR;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	spin_lock(&dma->lock);
+	if (!dma->running) {
+		spin_unlock(&dma->lock);
+		return;
+	}
+	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+	if (output->redi) 
+		output_ack_input(output, output->redi);
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
+}
+
+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out)
+{
+	dma->io = io;
+	dma->nr = nr;
+	spin_lock_init(&dma->lock);
+	init_waitqueue_head(&dma->wq);
+	if (out) {
+		INIT_WORK(&dma->work, output_work);
+		dma->num = OUTPUT_DMA_BUFS;
+		dma->size = OUTPUT_DMA_SIZE;
+		dma->div = OUTPUT_DMA_IRQ_DIV;
+	} else {
+		INIT_WORK(&dma->work, input_work);
+		dma->num = INPUT_DMA_BUFS;
+		dma->size = INPUT_DMA_SIZE;
+		dma->div = INPUT_DMA_IRQ_DIV;
 	}
-	printk(KERN_INFO "Port %d (TAB %d): %s\n",
-			 port->nr, port->nr+1, modname);
 }
 
-static void ddb_input_init(struct ddb_port *port, int nr)
+static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int dma_nr)
 {
 	struct ddb *dev = port->dev;
 	struct ddb_input *input = &dev->input[nr];
 
+	if (dev->has_dma) {
+		dev->handler[dma_nr + 8] = input_handler;
+		dev->handler_data[dma_nr + 8] = (unsigned long) input;
+	}
+	port->input[pnr] = input;
 	input->nr = nr;
 	input->port = port;
-	input->dma_buf_num = INPUT_DMA_BUFS;
-	input->dma_buf_size = INPUT_DMA_SIZE;
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(2, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, DMA_BUFFER_ACK(nr));
-	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
-	spin_lock_init(&input->lock);
-	init_waitqueue_head(&input->wq);
+	if (dev->has_dma) {
+		input->dma = &dev->dma[dma_nr];
+		ddb_dma_init(input->dma, dma_nr, (void *) input, 0);
+	}
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	if (dev->has_dma) 
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
 }
 
-static void ddb_output_init(struct ddb_port *port, int nr)
+static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr)
 {
 	struct ddb *dev = port->dev;
 	struct ddb_output *output = &dev->output[nr];
+
+	if (dev->has_dma) {
+		dev->handler[dma_nr + 8] = output_handler;
+		dev->handler_data[dma_nr + 8] = (unsigned long) output;
+	}
+	port->output = output;
 	output->nr = nr;
 	output->port = port;
-	output->dma_buf_num = OUTPUT_DMA_BUFS;
-	output->dma_buf_size = OUTPUT_DMA_SIZE;
-
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
-	init_waitqueue_head(&output->wq);
+	if (dev->has_dma) {
+		output->dma = &dev->dma[dma_nr];
+		ddb_dma_init(output->dma, dma_nr, (void *) output, 1);
+	}
+	if (output->port->class == DDB_PORT_MOD) {
+		// ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
+	} else {
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
+		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr));
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
+	}
+	if (dev->has_dma) 
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
 }
 
 static void ddb_ports_init(struct ddb *dev)
@@ -1247,15 +1900,31 @@ static void ddb_ports_init(struct ddb *dev)
 		port->dev = dev;
 		port->nr = i;
 		port->i2c = &dev->i2c[i];
-		port->input[0] = &dev->input[2 * i];
-		port->input[1] = &dev->input[2 * i + 1];
-		port->output = &dev->output[i];
-
+		port->gap = 4;
+		port->obr = ci_bitrate;
 		mutex_init(&port->i2c_gate_lock);
 		ddb_port_probe(port);
-		ddb_input_init(port, 2 * i);
-		ddb_input_init(port, 2 * i + 1);
-		ddb_output_init(port, i);
+		port->dvb[0].adap = &dev->adap[2 * i];
+		port->dvb[1].adap = &dev->adap[2 * i + 1];
+
+		if ((dev->info->type == DDB_OCTOPUS_CI) || 
+		    (dev->info->type == DDB_OCTONET) ||
+		    (dev->info->type == DDB_OCTOPUS)) {
+			if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) {
+				ddb_input_init(port, 2 + i, 0, 2 + i);
+				ddb_input_init(port, 4 + i, 1, 4 + i);
+			} else {
+				ddb_input_init(port, 2 * i, 0, 2 * i);
+				ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
+			}
+			ddb_output_init(port, i, i + 8);
+		} 
+		if (dev->info->type == DDB_MOD) {
+			ddb_output_init(port, i, i);
+			dev->handler[i + 18] = ddbridge_mod_rate_handler;
+			dev->handler_data[i + 18] = 
+				(unsigned long) &dev->output[i];
+		}
 	}
 }
 
@@ -1266,101 +1935,130 @@ static void ddb_ports_release(struct ddb *dev)
 
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
-		port->dev = dev;
-		tasklet_kill(&port->input[0]->tasklet);
-		tasklet_kill(&port->input[1]->tasklet);
-		tasklet_kill(&port->output->tasklet);
+		if (port->input[0])
+			cancel_work_sync(&port->input[0]->dma->work);
+		if (port->input[1])
+			cancel_work_sync(&port->input[1]->dma->work);
+		if (port->output)
+			cancel_work_sync(&port->output->dma->work);
 	}
 }
 
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
+#define IRQ_HANDLE(_nr) if ((s & (1UL << _nr)) && dev->handler[_nr]) \
+		dev->handler[_nr](dev->handler_data[_nr]);
+
+static void irq_handle_msg(struct ddb *dev, u32 s)
+{
+	dev->i2c_irq++;
+	IRQ_HANDLE(0);
+	IRQ_HANDLE(1);
+	IRQ_HANDLE(2);
+	IRQ_HANDLE(3);
+}
+
+static void irq_handle_io(struct ddb *dev, u32 s)
+{
+	dev->ts_irq++;
+	IRQ_HANDLE(8);
+	IRQ_HANDLE(9);
+	IRQ_HANDLE(10);
+	IRQ_HANDLE(11);
+	IRQ_HANDLE(12);
+	IRQ_HANDLE(13);
+	IRQ_HANDLE(14);
+	IRQ_HANDLE(15);
+	IRQ_HANDLE(16);
+	IRQ_HANDLE(17);
+	IRQ_HANDLE(18);
+	IRQ_HANDLE(19);
+	if (dev->info->type != DDB_MOD)
+		return;
+	IRQ_HANDLE(20);
+	IRQ_HANDLE(21);
+	IRQ_HANDLE(22);
+	IRQ_HANDLE(23);
+	IRQ_HANDLE(24);
+	IRQ_HANDLE(25);
+	IRQ_HANDLE(26);
+	IRQ_HANDLE(27);
+}
+
+static irqreturn_t irq_handler0(int irq, void *dev_id)
+{
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
+
+	do {
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		if (!(s & 0xfff00))
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+		irq_handle_io(dev, s);
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+	
+	return IRQ_HANDLED;
+}
 
-static void irq_handle_i2c(struct ddb *dev, int n)
+static irqreturn_t irq_handler1(int irq, void *dev_id)
 {
-	struct ddb_i2c *i2c = &dev->i2c[n];
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
 
-	i2c->done = 1;
-	wake_up(&i2c->wq);
+	do {
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		if (!(s & 0x0000f))
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+		irq_handle_msg(dev, s);
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+	
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t irq_handler(int irq, void *dev_id)
 {
 	struct ddb *dev = (struct ddb *) dev_id;
-	u32 s = ddbreadl(INTERRUPT_STATUS);
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
+	int ret = IRQ_HANDLED;
 
 	if (!s)
 		return IRQ_NONE;
-
 	do {
-		ddbwritel(s, INTERRUPT_ACK);
-
-		if (s & 0x00000001)
-			irq_handle_i2c(dev, 0);
-		if (s & 0x00000002)
-			irq_handle_i2c(dev, 1);
-		if (s & 0x00000004)
-			irq_handle_i2c(dev, 2);
-		if (s & 0x00000008)
-			irq_handle_i2c(dev, 3);
-
-		if (s & 0x00000100)
-			tasklet_schedule(&dev->input[0].tasklet);
-		if (s & 0x00000200)
-			tasklet_schedule(&dev->input[1].tasklet);
-		if (s & 0x00000400)
-			tasklet_schedule(&dev->input[2].tasklet);
-		if (s & 0x00000800)
-			tasklet_schedule(&dev->input[3].tasklet);
-		if (s & 0x00001000)
-			tasklet_schedule(&dev->input[4].tasklet);
-		if (s & 0x00002000)
-			tasklet_schedule(&dev->input[5].tasklet);
-		if (s & 0x00004000)
-			tasklet_schedule(&dev->input[6].tasklet);
-		if (s & 0x00008000)
-			tasklet_schedule(&dev->input[7].tasklet);
-
-		if (s & 0x00010000)
-			tasklet_schedule(&dev->output[0].tasklet);
-		if (s & 0x00020000)
-			tasklet_schedule(&dev->output[1].tasklet);
-		if (s & 0x00040000)
-			tasklet_schedule(&dev->output[2].tasklet);
-		if (s & 0x00080000)
-			tasklet_schedule(&dev->output[3].tasklet);
-
-		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
-	} while ((s = ddbreadl(INTERRUPT_STATUS)));
-
-	return IRQ_HANDLED;
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+		
+		if (s & 0x0000000f)
+			irq_handle_msg(dev, s);
+		if (s & 0x0fffff00)
+			irq_handle_io(dev, s);
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+	
+	return ret;
 }
 
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
 static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
 {
 	u32 data, shift;
 
 	if (wlen > 4)
-		ddbwritel(1, SPI_CONTROL);
+		ddbwritel(dev, 1, SPI_CONTROL);
 	while (wlen > 4) {
 		/* FIXME: check for big-endian */
 		data = swab32(*(u32 *)wbuf);
 		wbuf += 4;
 		wlen -= 4;
-		ddbwritel(data, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
+		ddbwritel(dev, data, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 			;
 	}
 
 	if (rlen)
-		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+		ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
 	else
-		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+		ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
 
 	data = 0;
 	shift = ((4 - wlen) * 8);
@@ -1372,33 +2070,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
 	}
 	if (shift)
 		data <<= shift;
-	ddbwritel(data, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
+	ddbwritel(dev, data, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 		;
 
 	if (!rlen) {
-		ddbwritel(0, SPI_CONTROL);
+		ddbwritel(dev, 0, SPI_CONTROL);
 		return 0;
 	}
 	if (rlen > 4)
-		ddbwritel(1, SPI_CONTROL);
+		ddbwritel(dev, 1, SPI_CONTROL);
 
 	while (rlen > 4) {
-		ddbwritel(0xffffffff, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
+		ddbwritel(dev, 0xffffffff, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 			;
-		data = ddbreadl(SPI_DATA);
+		data = ddbreadl(dev, SPI_DATA);
 		*(u32 *) rbuf = swab32(data);
 		rbuf += 4;
 		rlen -= 4;
 	}
-	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
-	ddbwritel(0xffffffff, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
+	ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
+	ddbwritel(dev, 0xffffffff, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 		;
 
-	data = ddbreadl(SPI_DATA);
-	ddbwritel(0, SPI_CONTROL);
+	data = ddbreadl(dev, SPI_DATA);
+	ddbwritel(dev, 0, SPI_CONTROL);
 
 	if (rlen < 4)
 		data <<= ((4 - rlen) * 8);
@@ -1412,6 +2110,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
 	return 0;
 }
 
+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len)
+{
+	u8 cmd[4] = {0x03, (addr >> 16) & 0xff, 
+		     (addr >> 8) & 0xff, addr & 0xff};
+	
+	return flashio(dev, cmd, 4, buf, len);
+}
+
+static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val)
+{
+	ddbwritel(dev, adr, MDIO_ADR);
+	ddbwritel(dev, reg, MDIO_REG);
+	ddbwritel(dev, val, MDIO_VAL);
+	ddbwritel(dev, 0x03, MDIO_CTRL);
+	while (ddbreadl(dev, MDIO_CTRL) & 0x02);
+	return 0;
+}
+
+static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg)
+{
+	ddbwritel(dev, adr, MDIO_ADR);
+	ddbwritel(dev, reg, MDIO_REG);
+	ddbwritel(dev, 0x07, MDIO_CTRL);
+	while (ddbreadl(dev, MDIO_CTRL) & 0x02);
+	return ddbreadl(dev, MDIO_VAL);
+}
+
 #define DDB_MAGIC 'd'
 
 struct ddb_flashio {
@@ -1421,19 +2146,69 @@ struct ddb_flashio {
 	__u32 read_len;
 };
 
-#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
+struct ddb_gpio {
+	__u32 mask;
+	__u32 data;
+};
+
+struct ddb_id {
+	__u16 vendor;
+	__u16 device;
+	__u16 subvendor;
+	__u16 subdevice;
+	__u32 hw;
+	__u32 regmap;
+};
+
+struct ddb_reg {
+	__u32 reg;
+	__u32 val;
+};
+
+struct ddb_mem {
+	__u32  off;
+	__u8  *buf;
+	__u32  len;
+};
+
+struct ddb_mdio {
+	__u8   adr;
+	__u8   reg;
+	__u16  val;
+};
+
+#define IOCTL_DDB_FLASHIO    _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
+#define IOCTL_DDB_GPIO_IN    _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
+#define IOCTL_DDB_GPIO_OUT   _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
+#define IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id)
+#define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
+#define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
+#define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
+#define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
+#define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
+#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
 
 #define DDB_NAME "ddbridge"
 
 static u32 ddb_num;
-static struct ddb *ddbs[32];
-static struct class *ddb_class;
 static int ddb_major;
+static DEFINE_MUTEX(ddb_mutex);
+
+static int ddb_release(struct inode *inode, struct file *file)
+{
+	struct ddb *dev = file->private_data;
+	
+	dev->ddb_dev_users--;
+	return 0;
+}
 
 static int ddb_open(struct inode *inode, struct file *file)
 {
 	struct ddb *dev = ddbs[iminor(inode)];
 
+	if (dev->ddb_dev_users)
+		return -EBUSY;
+	dev->ddb_dev_users++;
 	file->private_data = dev;
 	return 0;
 }
@@ -1470,6 +2245,103 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			return -EFAULT;
 		break;
 	}
+	case IOCTL_DDB_GPIO_OUT:
+	{
+		struct ddb_gpio gpio;
+		if (copy_from_user(&gpio, parg, sizeof(gpio))) 
+			return -EFAULT;
+		ddbwritel(dev, gpio.mask, GPIO_DIRECTION);
+		ddbwritel(dev, gpio.data, GPIO_OUTPUT);
+		break;
+	}
+	case IOCTL_DDB_ID:
+	{
+		struct ddb_id ddbid;
+		
+		ddbid.vendor = dev->id->vendor;
+		ddbid.device = dev->id->device;
+		ddbid.subvendor = dev->id->subvendor;
+		ddbid.subdevice = dev->id->subdevice;
+		ddbid.hw = ddbreadl(dev, 0);
+		ddbid.regmap = ddbreadl(dev, 4);
+		if (copy_to_user(parg, &ddbid, sizeof(ddbid))) 
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_READ_REG:
+	{
+		struct ddb_reg reg;
+		
+		if (copy_from_user(&reg, parg, sizeof(reg))) 
+			return -EFAULT;
+		if (reg.reg >= dev->regs_len)
+			return -EINVAL;
+		reg.val = ddbreadl(dev, reg.reg);
+		if (copy_to_user(parg, &reg, sizeof(reg))) 
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_REG:
+	{
+		struct ddb_reg reg;
+		
+		if (copy_from_user(&reg, parg, sizeof(reg))) 
+			return -EFAULT;
+		if (reg.reg >= dev->regs_len)
+			return -EINVAL;
+		ddbwritel(dev, reg.val, reg.reg);
+		break;
+	}
+	case IOCTL_DDB_READ_MDIO:
+	{
+		struct ddb_mdio mdio;
+		
+		if (copy_from_user(&mdio, parg, sizeof(mdio))) 
+			return -EFAULT;
+		mdio.val = mdio_read(dev, mdio.adr, mdio.reg);
+		if (copy_to_user(parg, &mdio, sizeof(mdio))) 
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_MDIO:
+	{
+		struct ddb_mdio mdio;
+		
+		if (copy_from_user(&mdio, parg, sizeof(mdio))) 
+			return -EFAULT;
+		mdio_write(dev, mdio.adr, mdio.reg, mdio.val);
+		break;
+	}
+	case IOCTL_DDB_READ_MEM:
+	{
+		struct ddb_mem mem;
+		u8 *buf = &dev->iobuf[0];
+
+		if (copy_from_user(&mem, parg, sizeof(mem)))
+			return -EFAULT;
+		if ((mem.len + mem.off > dev->regs_len) ||
+		    mem.len > 1024)
+			return -EINVAL;
+		ddbcpyfrom(dev, buf, mem.off, mem.len);
+		if (copy_to_user(mem.buf, buf, mem.len))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_MEM:
+	{
+		struct ddb_mem mem;
+		u8 *buf = &dev->iobuf[0];
+		
+		if (copy_from_user(&mem, parg, sizeof(mem)))
+			return -EFAULT;
+		if ((mem.len + mem.off > dev->regs_len) ||
+		    mem.len > 1024)
+			return -EINVAL;
+		if (copy_from_user(buf, mem.buf, mem.len))
+			return -EFAULT;
+		ddbcpyto(dev, mem.off, buf, mem.len);
+		break;
+	}
 	default:
 		return -ENOTTY;
 	}
@@ -1479,61 +2351,425 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static const struct file_operations ddb_fops = {
 	.unlocked_ioctl = ddb_ioctl,
 	.open           = ddb_open,
+	.release        = ddb_release,
 };
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+static char *ddb_devnode(struct device *device, mode_t *mode)
+#else
 static char *ddb_devnode(struct device *device, umode_t *mode)
+#endif
 {
 	struct ddb *dev = dev_get_drvdata(device);
 
 	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
 }
 
+#define __ATTR_MRO(_name, _show) {				\
+	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
+	.show	= _show,					\
+}
+
+#define __ATTR_MWO(_name, _store) {				\
+	.attr	= { .name = __stringify(_name), .mode = 0222 },	\
+	.store	= _store,					\
+}
+
+static ssize_t ports_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->info->port_num);
+}
+
+static ssize_t ts_irq_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->ts_irq);
+}
+
+static ssize_t i2c_irq_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->i2c_irq);
+}
+
+static char *class_name[] = {
+	"NONE", "CI", "TUNER", "LOOP"
+};
+
+static char *type_name[] = {
+	"NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", "DVBCT_ST", "INTERNAL", "CXD2099", 
+};
+
+static ssize_t fan_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	u32 val;
+
+	val = ddbreadl(dev, GPIO_OUTPUT) & 1;
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t fan_store(struct device *device, struct device_attribute *d,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	unsigned val;
+
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	ddbwritel(dev, 1, GPIO_DIRECTION);
+	ddbwritel(dev, val & 1, GPIO_OUTPUT);
+	return count;
+}
+
+static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	struct i2c_adapter *adap;
+	int temp, temp2;
+	u8 tmp[2];
+
+	if (dev->info->type == DDB_MOD) {
+		ddbwritel(dev, 1, TEMPMON_CONTROL);
+		msleep(5);
+		temp = ddbreadl(dev, TEMPMON_SENSOR1);
+		temp2 = ddbreadl(dev, TEMPMON_SENSOR2);
+		temp = (temp * 1000) >> 8;
+		temp2 = (temp2 * 1000) >> 8;
+		return sprintf(buf, "%d %d\n", temp, temp2);
+	}
+	if (!dev->info->temp_num)
+		return sprintf(buf, "no sensor\n");
+	adap = &dev->i2c[dev->info->temp_bus].adap;
+	if (ddb_i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0)
+		return sprintf(buf, "read_error\n");
+	temp = (tmp[0] << 3) | (tmp[1] >> 5);
+	temp *= 125;
+	if (dev->info->temp_num == 2) {
+		if (ddb_i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0)
+			return sprintf(buf, "read_error\n");
+		temp2 = (tmp[0] << 3) | (tmp[1] >> 5);
+		temp2 *= 125;
+		return sprintf(buf, "%d %d\n", temp, temp2);
+	}
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t mod_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+
+	return sprintf(buf, "%s:%s\n",
+		       class_name[dev->port[num].class],
+		       type_name[dev->port[num].type]);
+}
+
+static ssize_t led_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+
+	return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0);
+}
+
+static void ddb_set_led(struct ddb *dev, int num, int val)
+{
+	if (!dev->info->led_num)
+		return;
+	switch (dev->port[num].class) {
+	case DDB_PORT_TUNER:
+		switch (dev->port[num].type) {
+		case DDB_TUNER_DVBS_ST:
+			ddb_i2c_write_reg16(&dev->i2c[num].adap,
+					0x69, 0xf14c, val ? 2 : 0);
+			break;
+		case DDB_TUNER_DVBCT_ST:
+			ddb_i2c_write_reg16(&dev->i2c[num].adap, 
+					0x1f, 0xf00e, 0);
+			ddb_i2c_write_reg16(&dev->i2c[num].adap, 
+					0x1f, 0xf00f, val ? 1 : 0);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static ssize_t led_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+	unsigned val;
+
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	if (val)
+		dev->leds |= (1 << num);
+	else
+		dev->leds &= ~(1 << num);
+	ddb_set_led(dev, num, val);
+	return count;
+}
+
+static ssize_t snr_show(struct device *device, struct device_attribute *attr, char *buf) 
+{
+	struct ddb *dev = dev_get_drvdata(device); 
+	char snr[32];
+	int num = attr->attr.name[3] - 0x30;
+	
+	/* serial number at 0x100-0x11f */
+	if (ddb_i2c_read_regs16(&dev->i2c[num].adap, 0x50, 0x100, snr, 32) < 0)
+		if (ddb_i2c_read_regs16(&dev->i2c[num].adap, 0x57, 0x100, snr, 32) < 0)
+			return sprintf(buf, "NO SNR\n");
+	snr[31]=0; /* in case it is not terminated on EEPROM */
+	return sprintf(buf, "%s\n", snr); 
+}
+
+static ssize_t snr_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device); 
+	int num = attr->attr.name[3] - 0x30;
+	u8 snr[34] = { 0x01, 0x00 };
+	
+	if (count > 31)
+		return -EINVAL;
+	memcpy(snr + 2, buf, count);
+	ddb_i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
+	ddb_i2c_write(&dev->i2c[num].adap, 0x50, snr, 34);
+	return count;
+}
+
+static ssize_t bsnr_show(struct device *device, struct device_attribute *attr, char *buf) 
+{
+	struct ddb *dev = dev_get_drvdata(device); 
+	char snr[16];
+
+	ddbridge_flashread(dev, snr, 0x10, 15);
+	snr[15]=0; /* in case it is not terminated on EEPROM */
+	return sprintf(buf, "%s\n", snr); 
+}
+
+static ssize_t redirect_show(struct device *device, struct device_attribute *attr, char *buf) 
+{
+	return 0;
+}
+
+static ssize_t redirect_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	unsigned int i, p;
+	int res;
+	
+	if (sscanf(buf, "%x %x\n", &i, &p) != 2)
+		return -EINVAL;
+	res = ddb_redirect(i, p);
+	if (res < 0)
+		return res;
+	printk(KERN_INFO "redirect: %02x, %02x\n", i, p);
+	return count;
+}
+
+static ssize_t gap_show(struct device *device, struct device_attribute *attr, char *buf) 
+{
+	struct ddb *dev = dev_get_drvdata(device); 
+	int num = attr->attr.name[3] - 0x30;
+	
+	return sprintf(buf, "%d\n", dev->port[num].gap);
+
+}
+static ssize_t gap_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device); 
+	int num = attr->attr.name[3] - 0x30;
+	unsigned int val;
+	
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	if (val > 20)
+		return -EINVAL;
+	dev->port[num].gap = val;
+	return count;
+}
+
+static ssize_t version_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	
+	return sprintf(buf, "%08x %08x\n", ddbreadl(dev, 0), ddbreadl(dev, 4));
+}
+
+static ssize_t hwid_show(struct device *device,
+			 struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "0x%08X\n", dev->hwid);
+}
+
+static ssize_t regmap_show(struct device *device, 
+			   struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	
+	return sprintf(buf, "0x%08X\n", dev->regmapid);
+}
+
+static struct device_attribute ddb_attrs[] = {
+	__ATTR_RO(version),
+	__ATTR_RO(ports),
+	__ATTR_RO(ts_irq),
+	__ATTR_RO(i2c_irq),
+	__ATTR(gap0, 0666, gap_show, gap_store),
+	__ATTR(gap1, 0666, gap_show, gap_store),
+	__ATTR(gap2, 0666, gap_show, gap_store),
+	__ATTR(gap3, 0666, gap_show, gap_store),
+	__ATTR_RO(hwid),
+	__ATTR_RO(regmap),
+	__ATTR(redirect, 0666, redirect_show, redirect_store),
+	__ATTR_MRO(snr,  bsnr_show),
+	__ATTR_NULL,
+};
+
+static struct device_attribute ddb_attrs_temp[] = {
+	__ATTR_RO(temp),
+};
+
+static struct device_attribute ddb_attrs_mod[] = {
+	__ATTR_MRO(mod0, mod_show),
+	__ATTR_MRO(mod1, mod_show),
+	__ATTR_MRO(mod2, mod_show),
+	__ATTR_MRO(mod3, mod_show),
+};
+
+static struct device_attribute ddb_attrs_fan[] = {
+	__ATTR(fan, 0666, fan_show, fan_store),
+};
+
+static struct device_attribute ddb_attrs_snr[] = {
+	__ATTR(snr0, 0666, snr_show, snr_store),
+	__ATTR(snr1, 0666, snr_show, snr_store),
+	__ATTR(snr2, 0666, snr_show, snr_store),
+	__ATTR(snr3, 0666, snr_show, snr_store),
+};
+
+static struct device_attribute ddb_attrs_led[] = {
+	__ATTR(led0, 0666, led_show, led_store),
+	__ATTR(led1, 0666, led_show, led_store),
+	__ATTR(led2, 0666, led_show, led_store),
+	__ATTR(led3, 0666, led_show, led_store),
+};
+
+static struct class ddb_class = {
+	.name		= "ddbridge",
+	.owner          = THIS_MODULE,
+	.dev_attrs	= ddb_attrs,
+	.devnode        = ddb_devnode,
+};
+
 static int ddb_class_create(void)
 {
 	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
 	if (ddb_major < 0)
 		return ddb_major;
-
-	ddb_class = class_create(THIS_MODULE, DDB_NAME);
-	if (IS_ERR(ddb_class)) {
-		unregister_chrdev(ddb_major, DDB_NAME);
-		return PTR_ERR(ddb_class);
-	}
-	ddb_class->devnode = ddb_devnode;
+	if (class_register(&ddb_class) < 0)
+		return -1;
 	return 0;
 }
 
 static void ddb_class_destroy(void)
 {
-	class_destroy(ddb_class);
+	class_unregister(&ddb_class);
 	unregister_chrdev(ddb_major, DDB_NAME);
 }
 
+static void ddb_device_attrs_del(struct ddb *dev)
+{
+	int i;
+
+	for (i = 0; i < dev->info->temp_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_temp[0]);
+	for (i = 0; i < dev->info->port_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]);
+	for (i = 0; i < dev->info->fan_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_fan[0]);
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		if (dev->info->led_num)
+			device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]);
+		device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]);
+	}
+}
+
+static int ddb_device_attrs_add(struct ddb *dev)
+{
+	int i, res = 0;
+	
+	for (i = 0; i < dev->info->temp_num; i++)
+		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_temp[0])))
+			goto fail;
+	for (i = 0; i < dev->info->port_num; i++)
+		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])))
+			goto fail;
+	for (i = 0; i < dev->info->fan_num; i++)
+		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_fan[0])))
+			goto fail;
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])))
+			goto fail;
+		if (dev->info->led_num)
+			if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_led[i])))
+				goto fail;
+	}
+fail:
+	return res;
+}
+
 static int ddb_device_create(struct ddb *dev)
 {
-	dev->nr = ddb_num++;
-	dev->ddb_dev = device_create(ddb_class, NULL,
+	int res = 0;
+
+	if (ddb_num == DDB_MAX_ADAPTER)
+		return -ENOMEM;
+	mutex_lock(&ddb_mutex);
+	dev->nr = ddb_num;
+	ddbs[dev->nr] = dev;
+	dev->ddb_dev = device_create(&ddb_class, dev->dev,
 				     MKDEV(ddb_major, dev->nr),
 				     dev, "ddbridge%d", dev->nr);
-	ddbs[dev->nr] = dev;
-	if (IS_ERR(dev->ddb_dev))
-		return -1;
-	return 0;
+	if (IS_ERR(dev->ddb_dev)) {
+		res = PTR_ERR(dev->ddb_dev);
+		printk(KERN_INFO "Could not create ddbridge%d\n", dev->nr); 
+		goto fail;
+	}
+	res = ddb_device_attrs_add(dev);
+	if (res) {
+		ddb_device_attrs_del(dev);
+		device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
+		ddbs[dev->nr] = 0;
+		dev->ddb_dev = ERR_PTR(-ENODEV);
+	} else
+		ddb_num++;
+fail:
+	mutex_unlock(&ddb_mutex);
+	return res;
 }
 
 static void ddb_device_destroy(struct ddb *dev)
 {
-	ddb_num--;
 	if (IS_ERR(dev->ddb_dev))
 		return;
-	device_destroy(ddb_class, MKDEV(ddb_major, 0));
+	ddb_device_attrs_del(dev);
+	device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
 }
 
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
 static void ddb_unmap(struct ddb *dev)
 {
 	if (dev->regs)
@@ -1541,20 +2777,20 @@ static void ddb_unmap(struct ddb *dev)
 	vfree(dev);
 }
 
-
-static void ddb_remove(struct pci_dev *pdev)
+static void __devexit ddb_remove(struct pci_dev *pdev)
 {
-	struct ddb *dev = pci_get_drvdata(pdev);
+	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
 
 	ddb_ports_detach(dev);
 	ddb_i2c_release(dev);
 
-	ddbwritel(0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, MSI1_ENABLE);
+	if (dev->msi == 2)
+		free_irq(dev->pdev->irq + 1, dev);
 	free_irq(dev->pdev->irq, dev);
-#ifdef CONFIG_PCI_MSI
 	if (dev->msi)
 		pci_disable_msi(dev->pdev);
-#endif
 	ddb_ports_release(dev);
 	ddb_buffers_free(dev);
 	ddb_device_destroy(dev);
@@ -1564,8 +2800,13 @@ static void ddb_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#define __devinit 
+#define __devinitdata 
+#endif 
 
-static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit ddb_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *id)
 {
 	struct ddb *dev;
 	int stat = 0;
@@ -1574,44 +2815,91 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (pci_enable_device(pdev) < 0)
 		return -ENODEV;
 
-	dev = vmalloc(sizeof(struct ddb));
+	dev = vzalloc(sizeof(struct ddb));
 	if (dev == NULL)
 		return -ENOMEM;
-	memset(dev, 0, sizeof(struct ddb));
 
+	dev->has_dma = 1;
 	dev->pdev = pdev;
+	dev->dev = &pdev->dev;
 	pci_set_drvdata(pdev, dev);
+	dev->id = id;
 	dev->info = (struct ddb_info *) id->driver_data;
 	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
 
+	dev->regs_len = pci_resource_len(dev->pdev, 0);
 	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
 			    pci_resource_len(dev->pdev, 0));
 	if (!dev->regs) {
+		printk("DDBridge: not enough memory for register map\n");
 		stat = -ENOMEM;
 		goto fail;
 	}
-	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
+	if (ddbreadl(dev, 0) == 0xffffffff) {
+		printk("DDBridge: cannot read registers\n");
+		stat = -ENODEV;
+		goto fail;
+	}
 
-#ifdef CONFIG_PCI_MSI
-	if (pci_msi_enabled())
-		stat = pci_enable_msi(dev->pdev);
-	if (stat) {
-		printk(KERN_INFO ": MSI not available.\n");
+	dev->hwid = ddbreadl(dev, 0);
+	dev->regmapid = ddbreadl(dev, 4);
+	
+	printk(KERN_INFO "HW %08x REGMAP %08x\n",
+	       dev->hwid, dev->regmapid);
+	
+	ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI1_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI2_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI3_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI4_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI5_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI6_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI7_ENABLE);
+
+	if (pci_msi_enabled()) {
+		stat = pci_enable_msi_block(dev->pdev, 2);
+		if (stat == 0) {
+			dev->msi = 1;
+			printk("DDBrige using 2 MSI interrupts\n");
+		}
+		if (stat == 1) 
+			stat = pci_enable_msi(dev->pdev);
+		if (stat < 0) {
+			printk(KERN_INFO ": MSI not available.\n");
+		} else {
+			irq_flag = 0;
+			dev->msi++;
+		}
+	}
+	if (dev->msi == 2) {
+		stat = request_irq(dev->pdev->irq, irq_handler0,
+				   irq_flag, "ddbridge", (void *) dev);
+		if (stat < 0)
+			goto fail0;
+		stat = request_irq(dev->pdev->irq + 1, irq_handler1,
+				   irq_flag, "ddbridge", (void *) dev);
+		if (stat < 0) {
+			free_irq(dev->pdev->irq, dev);
+			goto fail0;
+		} 
 	} else {
-		irq_flag = 0;
-		dev->msi = 1;
+		stat = request_irq(dev->pdev->irq, irq_handler, 
+				   irq_flag, "ddbridge", (void *) dev);
+		if (stat < 0)
+			goto fail0;
+	}
+	ddbwritel(dev, 0, DMA_BASE_READ);
+	if (dev->info->type != DDB_MOD)
+		ddbwritel(dev, 0, DMA_BASE_WRITE);
+	
+	// ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);
+	if (dev->msi == 2) {
+		ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
+		ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
+	} else {
+		ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
+		ddbwritel(dev, 0x00000000, MSI1_ENABLE);
 	}
-#endif
-	stat = request_irq(dev->pdev->irq, irq_handler,
-			   irq_flag, "DDBridge", (void *) dev);
-	if (stat < 0)
-		goto fail1;
-	ddbwritel(0, DMA_BASE_WRITE);
-	ddbwritel(0, DMA_BASE_READ);
-	ddbwritel(0xffffffff, INTERRUPT_ACK);
-	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
-	ddbwritel(0, MSI1_ENABLE);
-
 	if (ddb_i2c_init(dev) < 0)
 		goto fail1;
 	ddb_ports_init(dev);
@@ -1621,7 +2909,17 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	}
 	if (ddb_ports_attach(dev) < 0)
 		goto fail3;
+
+	/* ignore if this fails */
 	ddb_device_create(dev);
+
+	if (dev->info->fan_num)	{
+		ddbwritel(dev, 1, GPIO_DIRECTION);
+		ddbwritel(dev, 1, GPIO_OUTPUT);
+	}
+	if (dev->info->type == DDB_MOD)
+		ddbridge_mod_init(dev);
+
 	return 0;
 
 fail3:
@@ -1631,11 +2929,18 @@ fail3:
 fail2:
 	printk(KERN_ERR "fail2\n");
 	ddb_buffers_free(dev);
+	ddb_i2c_release(dev);
 fail1:
 	printk(KERN_ERR "fail1\n");
+	ddbwritel(dev, 0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, MSI1_ENABLE);
+	free_irq(dev->pdev->irq, dev);
+	if (dev->msi == 2) 
+		free_irq(dev->pdev->irq + 1, dev);
+fail0:
+	printk(KERN_ERR "fail0\n");
 	if (dev->msi)
 		pci_disable_msi(dev->pdev);
-	free_irq(dev->pdev->irq, dev);
 fail:
 	printk(KERN_ERR "fail\n");
 	ddb_unmap(dev);
@@ -1644,55 +2949,130 @@ fail:
 	return -1;
 }
 
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
 static struct ddb_info ddb_none = {
 	.type     = DDB_NONE,
-	.name     = "Digital Devices PCIe bridge",
+	.name     = "unknown Digital Devices PCIe card, install newer driver",
 };
 
 static struct ddb_info ddb_octopus = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Octopus DVB adapter",
 	.port_num = 4,
+	.i2c_num  = 4,
+};
+
+static struct ddb_info ddb_octopusv3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus V3 DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
 };
 
 static struct ddb_info ddb_octopus_le = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Octopus LE DVB adapter",
 	.port_num = 2,
+	.i2c_num  = 2,
+};
+
+static struct ddb_info ddb_octopus_oem = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus OEM",
+	.port_num = 4,
+	.i2c_num  = 4,
+	.led_num  = 1,
+	.fan_num  = 1,
+	.temp_num = 1,
+	.temp_bus = 0,
+};
+
+static struct ddb_info ddb_octopus_mini = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus Mini",
+	.port_num = 4,
+	.i2c_num  = 4,
 };
 
 static struct ddb_info ddb_v6 = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Cine S2 V6 DVB adapter",
 	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_v6_5 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
+};
+
+static struct ddb_info ddb_satixS2v3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
+	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_ci = {
+	.type     = DDB_OCTOPUS_CI,
+	.name     = "Digital Devices Octopus CI",
+	.port_num = 4,
+	.i2c_num  = 2,
+};
+
+static struct ddb_info ddb_cis = {
+	.type     = DDB_OCTOPUS_CI,
+	.name     = "Digital Devices Octopus CI single",
+	.port_num = 3,
+	.i2c_num  = 2,
+};
+
+static struct ddb_info ddb_dvbct = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
+	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_mod = {
+	.type     = DDB_MOD,
+	.name     = "Digital Devices DVB-C modulator",
+	.port_num = 10,
+	.temp_num = 1,
 };
 
 #define DDVID 0xdd01 /* Digital Devices Vendor ID */
 
-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
 	.vendor      = _vend,    .device    = _dev, \
 	.subvendor   = _subvend, .subdevice = _subdev, \
 	.driver_data = (unsigned long)&_driverdata }
 
-static const struct pci_device_id ddb_id_tbl[] = {
+static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
 	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
+	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
+	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
+	DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
 	/* in case sub-ids got deleted in flash */
 	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
 	{0}
 };
 MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
 
-
 static struct pci_driver ddb_pci_driver = {
-	.name        = "DDBridge",
+	.name        = "ddbridge",
 	.id_table    = ddb_id_tbl,
 	.probe       = ddb_probe,
 	.remove      = ddb_remove,
@@ -1700,23 +3080,30 @@ static struct pci_driver ddb_pci_driver = {
 
 static __init int module_init_ddbridge(void)
 {
-	int ret;
-
-	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
-	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
+	int stat = -1;
 
-	ret = ddb_class_create();
-	if (ret < 0)
-		return ret;
-	ret = pci_register_driver(&ddb_pci_driver);
-	if (ret < 0)
-		ddb_class_destroy();
-	return ret;
+	printk(KERN_INFO "Digital Devices PCIE bridge driver 0.9.9, "
+	       "Copyright (C) 2010-13 Digital Devices GmbH\n");
+	if (ddb_class_create() < 0)
+		return -1;
+	ddb_wq = create_workqueue("ddbridge");
+	if (ddb_wq == NULL)
+		goto exit1;
+	stat = pci_register_driver(&ddb_pci_driver);
+	if (stat < 0)
+		goto exit2;
+	return stat;
+exit2:
+	destroy_workqueue(ddb_wq);
+exit1:
+	ddb_class_destroy();
+	return stat;
 }
 
 static __exit void module_exit_ddbridge(void)
 {
 	pci_unregister_driver(&ddb_pci_driver);
+	destroy_workqueue(ddb_wq);
 	ddb_class_destroy();
 }
 
@@ -1724,6 +3111,6 @@ module_init(module_init_ddbridge);
 module_exit(module_exit_ddbridge);
 
 MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
-MODULE_AUTHOR("Ralph Metzler");
+MODULE_AUTHOR("Ralph Metzler, Metzler Brothers Systementwicklung");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
+MODULE_VERSION("0.9.10");
-- 
1.8.4.2

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

* [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (9 preceding siblings ...)
  2013-11-03  0:44 ` [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10 Maik Broemme
@ 2013-11-03  0:45 ` Maik Broemme
  2013-11-03 10:50   ` Mauro Carvalho Chehab
  2013-11-03  0:46 ` [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge Maik Broemme
  2013-11-03 10:58 ` [PATCH 00/12] DDBridge 0.9.10 driver updates Mauro Carvalho Chehab
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:45 UTC (permalink / raw)
  To: Linux Media Mailing List

Updated ddbridge header for 0.9.10 changes.

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/ddbridge.h | 408 ++++++++++++++++++++++++++++------
 1 file changed, 343 insertions(+), 65 deletions(-)

diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
index 8b1b41d..f35a5b4 100644
--- a/drivers/media/pci/ddbridge/ddbridge.h
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -1,38 +1,69 @@
 /*
- * ddbridge.h: Digital Devices PCIe bridge driver
+ *  ddbridge.h: Digital Devices PCIe bridge driver
  *
- * Copyright (C) 2010-2011 Digital Devices GmbH
+ *  Copyright (C) 2010-2013 Digital Devices GmbH
+ *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
  *
- * 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 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.
  *
- * 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
+ *  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
  */
 
 #ifndef _DDBRIDGE_H_
 #define _DDBRIDGE_H_
 
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#define __devexit
+#define __devinit
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/timer.h>
+#include <linux/i2c.h>
+#include <linux/swab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/completion.h>
+
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <asm/dma.h>
-#include <linux/dvb/frontend.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
 #include <linux/dvb/ca.h>
 #include <linux/socket.h>
+#include <linux/device.h>
+#include <linux/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
@@ -44,51 +75,83 @@
 #include "cxd2099.h"
 
 #define DDB_MAX_I2C     4
-#define DDB_MAX_PORT    4
+#define DDB_MAX_PORT   10
 #define DDB_MAX_INPUT   8
-#define DDB_MAX_OUTPUT  4
+#define DDB_MAX_OUTPUT 10
+
+struct ddb_regset {
+	uint32_t base;
+	uint32_t num;
+	uint32_t size;
+};
+
+struct ddb_regmap {
+	struct ddb_regset i2c;
+	struct ddb_regset i2c_buf;
+	struct ddb_regset dma;
+	struct ddb_regset dma_buf;
+	struct ddb_regset input;
+	struct ddb_regset output;
+	struct ddb_regset channel;
+	struct ddb_regset ci;
+	struct ddb_regset pid_filter;
+};
 
 struct ddb_info {
 	int   type;
 #define DDB_NONE         0
 #define DDB_OCTOPUS      1
+#define DDB_OCTOPUS_CI   2
+#define DDB_MOD          3
+#define DDB_OCTONET      4
 	char *name;
 	int   port_num;
-	u32   port_type[DDB_MAX_PORT];
+	int   i2c_num;
+	int   led_num;
+	int   fan_num;
+	int   temp_num;
+	int   temp_bus;
+	struct ddb_regmap regmap;
 };
 
-/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
+/* DMA_SIZE MUST be smaller than 256k and 
+   MUST be divisible by 188 and 128 !!! */
+
+#define DMA_MAX_BUFS 32      /* hardware table limit */
 
-#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
 #define INPUT_DMA_BUFS 8
 #define INPUT_DMA_SIZE (128*47*21)
+#define INPUT_DMA_IRQ_DIV 1
 
-#define OUTPUT_DMA_MAX_BUFS 32
 #define OUTPUT_DMA_BUFS 8
 #define OUTPUT_DMA_SIZE (128*47*21)
+#define OUTPUT_DMA_IRQ_DIV 1
 
 struct ddb;
 struct ddb_port;
 
-struct ddb_input {
-	struct ddb_port       *port;
+struct ddb_dma {
+	void                  *io;
 	u32                    nr;
-	int                    attached;
-
-	dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[INPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
-
-	struct tasklet_struct  tasklet;
+	dma_addr_t             pbuf[DMA_MAX_BUFS];
+	u8                    *vbuf[DMA_MAX_BUFS];
+	u32                    num;
+	u32                    size;
+	u32                    div;
+	u32                    bufreg;
+	struct work_struct     work;
 	spinlock_t             lock;
 	wait_queue_head_t      wq;
 	int                    running;
 	u32                    stat;
+	u32                    ctrl;
 	u32                    cbuf;
 	u32                    coff;
+};
 
-	struct dvb_adapter     adap;
+struct ddb_dvb {
+	struct dvb_adapter    *adap;
+	int                    adap_registered;
 	struct dvb_device     *dev;
 	struct dvb_frontend   *fe;
 	struct dvb_frontend   *fe2;
@@ -99,37 +162,35 @@ struct ddb_input {
 	struct dmx_frontend    mem_frontend;
 	int                    users;
 	int (*gate_ctrl)(struct dvb_frontend *, int);
+	int                    attached;
 };
 
-struct ddb_output {
+struct ddb_ci {
+	struct dvb_ca_en50221  en;
 	struct ddb_port       *port;
 	u32                    nr;
-	dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
-	struct tasklet_struct  tasklet;
-	spinlock_t             lock;
-	wait_queue_head_t      wq;
-	int                    running;
-	u32                    stat;
-	u32                    cbuf;
-	u32                    coff;
+	struct mutex           lock;
+};
 
-	struct dvb_adapter     adap;
-	struct dvb_device     *dev;
+struct ddb_io {
+	struct ddb_port       *port;
+	u32                    nr;
+	struct ddb_dma        *dma;
+	struct ddb_io         *redo;
+	struct ddb_io         *redi;
 };
 
+#define ddb_output ddb_io
+#define ddb_input ddb_io
+
 struct ddb_i2c {
 	struct ddb            *dev;
 	u32                    nr;
 	struct i2c_adapter     adap;
-	struct i2c_adapter     adap2;
 	u32                    regs;
 	u32                    rbuf;
 	u32                    wbuf;
-	int                    done;
-	wait_queue_head_t      wq;
+	struct completion      completion;
 };
 
 struct ddb_port {
@@ -141,45 +202,262 @@ struct ddb_port {
 #define DDB_PORT_NONE           0
 #define DDB_PORT_CI             1
 #define DDB_PORT_TUNER          2
+#define DDB_PORT_LOOP           3
+#define DDB_PORT_MOD            4
 	u32                    type;
 #define DDB_TUNER_NONE          0
 #define DDB_TUNER_DVBS_ST       1
 #define DDB_TUNER_DVBS_ST_AA    2
-#define DDB_TUNER_DVBCT_TR     16
-#define DDB_TUNER_DVBCT_ST     17
+#define DDB_TUNER_DVBCT_TR      3
+#define DDB_TUNER_DVBCT_ST      4
+#define DDB_CI_INTERNAL         5
+#define DDB_CI_EXTERNAL_SONY    6
+#define DDB_TUNER_XO2           16
+#define DDB_TUNER_DVBS          16
+#define DDB_TUNER_DVBCT2_SONY   17
+#define DDB_TUNER_ISDBT_SONY    18
+#define DDB_TUNER_DVBC2T2_SONY  19
+#define DDB_TUNER_ATSC_ST       20
+#define DDB_TUNER_DVBC2T2_ST    21
+
 	u32                    adr;
 
 	struct ddb_input      *input[2];
 	struct ddb_output     *output;
 	struct dvb_ca_en50221 *en;
+	struct ddb_dvb         dvb[2];
+	u32                    gap;
+	u32                    obr;
+};
+
+struct mod_base {
+	u32                    frequency;
+
+	u32                    flat_start;
+	u32                    flat_end;
+};
+
+struct mod_state {
+	u32                    modulation;
+
+	u32                    do_handle;
+
+	u32                    rate_inc;
+	u32                    Control;
+	u32                    State;
+	u32                    StateCounter;
+	s32                    LastPCRAdjust;
+	s32                    PCRAdjustSum;
+	s32                    InPacketsSum;
+	s32                    OutPacketsSum;
+	s64                    PCRIncrement;
+	s64                    PCRDecrement;
+	s32                    PCRRunningCorr;
+	u32                    OutOverflowPacketCount;
+	u32                    InOverflowPacketCount;
+	u32                    LastOutPacketCount;
+	u32                    LastInPacketCount;
+	u64                    LastOutPackets;
+	u64                    LastInPackets;
+	u32                    MinInputPackets;
+};
+
+#define CM_STARTUP_DELAY 2
+#define CM_AVERAGE  20
+#define CM_GAIN     10
+
+#define HW_LSB_SHIFT    12
+#define HW_LSB_MASK     0x1000
+
+#define CM_IDLE    0
+#define CM_STARTUP 1
+#define CM_ADJUST  2
+
+#define TS_CAPTURE_LEN  (21*188)
+
+/* net streaming hardware block */
+#define DDB_NS_MAX 15
+
+struct ddb_ns {
+	struct ddb_input      *input; 
+	int                    nr;
+	int                    fe;
+	u32                    rtcp_udplen;
+	u32                    rtcp_len;
+	u32                    ts_offset;
+	u32                    udplen;
+	u8                     p[512];
 };
 
 struct ddb {
 	struct pci_dev        *pdev;
+	struct platform_device *pfdev;
+	struct device         *dev;
+	const struct pci_device_id *id;
+	struct ddb_info       *info;
+	int                    msi;
+	struct workqueue_struct *wq;
+	u32                    has_dma;
+	u32                    has_ns;
+
+	struct ddb_regmap      regmap;
 	unsigned char         *regs;
+	u32                    regs_len;
 	struct ddb_port        port[DDB_MAX_PORT];
 	struct ddb_i2c         i2c[DDB_MAX_I2C];
 	struct ddb_input       input[DDB_MAX_INPUT];
 	struct ddb_output      output[DDB_MAX_OUTPUT];
+	struct dvb_adapter     adap[DDB_MAX_INPUT];
+	struct ddb_dma         dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT];
+
+	void                   (*handler[32])(unsigned long);
+	unsigned long          handler_data[32];
 
 	struct device         *ddb_dev;
-	int                    nr;
+	u32                    ddb_dev_users;
+	u32                    nr;
 	u8                     iobuf[1028];
 
-	struct ddb_info       *info;
-	int                    msi;
+	u8                     leds;
+	u32                    ts_irq;
+	u32                    i2c_irq;
+
+	u32                    hwid;
+	u32                    regmapid;
+	u32                    mac;
+	u32                    devid;
+
+	int                    ns_num;
+	struct ddb_ns          ns[DDB_NS_MAX];
+	struct mutex           mutex;
+
+	struct dvb_device     *nsd_dev;
+	u8                     tsbuf[TS_CAPTURE_LEN];
+
+	struct mod_base        mod_base;
+	struct mod_state       mod[10];
+};
+
+static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
+{
+	writeb(val, (char *) (dev->regs+(adr)));
+}
+
+static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr)
+{
+	writel(val, (char *) (dev->regs+(adr)));
+}
+
+static inline void ddbwritew(struct ddb *dev, u16 val, u32 adr)
+{
+	writew(val, (char *) (dev->regs+(adr)));
+}
+
+static inline u32 ddbreadl(struct ddb *dev, u32 adr)
+{
+	return readl((char *) (dev->regs+(adr)));
+}
+
+static inline u32 ddbreadb(struct ddb *dev, u32 adr)
+{
+	return readb((char *) (dev->regs+(adr)));
+}
+
+#define ddbcpyto(_dev, _adr, _src, _count) \
+	memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count))
+
+#define ddbcpyfrom(_dev, _dst, _adr, _count) \
+	memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count))
+
+#define ddbmemset(_dev, _adr, _val, _count) \
+	memset_io((char *) (_dev->regs + (_adr)), (_val), (_count))
+
+#define dd_uint8    u8
+#define dd_uint16   u16
+#define dd_int16    s16
+#define dd_uint32   u32
+#define dd_int32    s32
+#define dd_uint64   u64
+#define dd_int64    s64
+
+#define DDMOD_FLASH_START  0x1000
+
+struct DDMOD_FLASH_DS {
+	dd_uint32   Symbolrate;             /* kSymbols/s */
+	dd_uint32   DACFrequency;           /* kHz        */
+	dd_uint16   FrequencyResolution;    /* kHz        */
+	dd_uint16   IQTableLength;
+	dd_uint16   FrequencyFactor;
+	dd_int16    PhaseCorr;              /* TBD        */
+	dd_uint32   Control2;
+	dd_uint16   PostScaleI;   
+	dd_uint16   PostScaleQ;
+	dd_uint16   PreScale;
+	dd_int16    EQTap[11];
+	dd_uint16   FlatStart;   
+	dd_uint16   FlatEnd;
+	dd_uint32   FlashOffsetPrecalculatedIQTables;       /* 0 = none */
+	dd_uint8    Reserved[28];
+
+};
+
+struct DDMOD_FLASH {
+	dd_uint32   Magic;
+	dd_uint16   Version;
+	dd_uint16   DataSets;
+	
+	dd_uint16   VCORefFrequency;    /* MHz */
+	dd_uint16   VCO1Frequency;      /* MHz */
+	dd_uint16   VCO2Frequency;      /* MHz */
+	
+	dd_uint16   DACAux1;    /* TBD */
+	dd_uint16   DACAux2;    /* TBD */
+	
+	dd_uint8    Reserved1[238];
+	
+	struct DDMOD_FLASH_DS DataSet[1];
+};
+
+#define DDMOD_FLASH_MAGIC   0x5F564d5F
+
+struct dvb_mod_params {
+	__u32 base_frequency;
+	__u32 attenuator;
 };
 
-/****************************************************************************/
+struct dvb_mod_channel_params {
+	enum fe_modulation modulation;
+	__u32 rate_increment;
+};
+
+#define DVB_MOD_SET		_IOW('o', 208, struct dvb_mod_params)
+#define DVB_MOD_CHANNEL_SET	_IOW('o', 209, struct dvb_mod_channel_params)
+
+/* DDBridge flash functions (ddbridge-core.c) */
+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len);
 
-#define ddbwritel(_val, _adr)        writel((_val), \
-				     (char *) (dev->regs+(_adr)))
-#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
-#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)	\
-				     (dev->regs+(_adr)), (_src), (_count))
-#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
-				       (dev->regs+(_adr)), (_count))
+/* DDBridge DVB-C modulator functions (ddbridge-mod.c) */
+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
+int ddbridge_mod_init(struct ddb *dev);
+void ddbridge_mod_output_stop(struct ddb_output *output);
+void ddbridge_mod_output_start(struct ddb_output *output);
+void ddbridge_mod_rate_handler(unsigned long data);
 
-/****************************************************************************/
+/* DDBrigde I2C functions (ddbridge-i2c.c) */
+int ddb_i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len);
+int ddb_i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val);
+int ddb_i2c_read_regs(struct i2c_adapter *adapter,
+ 		 u8 adr, u8 reg, u8 *val, u8 len);
+int ddb_i2c_read_regs16(struct i2c_adapter *adapter, 
+ 		   u8 adr, u16 reg, u8 *val, u8 len);
+int ddb_i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val);
+int ddb_i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+ 		  u16 reg, u8 *val);
+int ddb_i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
+ 		   u16 reg, u8 val);
+int ddb_i2c_write_reg(struct i2c_adapter *adap, u8 adr,
+ 		  u8 reg, u8 val);
+void ddb_i2c_release(struct ddb *dev);
+int ddb_i2c_init(struct ddb *dev);
 
 #endif
-- 
1.8.4.2

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

* [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (10 preceding siblings ...)
  2013-11-03  0:45 ` [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes Maik Broemme
@ 2013-11-03  0:46 ` Maik Broemme
  2013-11-03 10:51   ` Mauro Carvalho Chehab
  2013-11-03 10:58 ` [PATCH 00/12] DDBridge 0.9.10 driver updates Mauro Carvalho Chehab
  12 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03  0:46 UTC (permalink / raw)
  To: Linux Media Mailing List

Fixed Kconfig and Makefile to build latest version off ddbridge. It
adds support for the following devices:

  - Octopus DVB adapter
  - Octopus V3 DVB adapter
  - Octopus LE DVB adapter
  - Octopus OEM
  - Octopus Mini
  - Cine S2 V6 DVB adapter
  - Cine S2 V6.5 DVB adapter
  - Octopus CI
  - Octopus CI single
  - DVBCT V6.1 DVB adapter
  - DVB-C modulator
  - SaTiX-S2 V3 DVB adapter

Signed-off-by: Maik Broemme <mbroemme@parallels.com>
---
 drivers/media/pci/ddbridge/Kconfig  | 21 +++++++++++++++------
 drivers/media/pci/ddbridge/Makefile |  2 +-
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig
index 44e5dc1..a30848f 100644
--- a/drivers/media/pci/ddbridge/Kconfig
+++ b/drivers/media/pci/ddbridge/Kconfig
@@ -6,13 +6,22 @@ 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_STV0367DD if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  Support for cards with the Digital Devices PCI express bridge:
-	  - Octopus PCIe Bridge
-	  - Octopus mini PCIe Bridge
-	  - Octopus LE
-	  - DuoFlex S2 Octopus
-	  - DuoFlex CT Octopus
-	  - cineS2(v6)
+	  - Octopus DVB adapter
+	  - Octopus V3 DVB adapter
+	  - Octopus LE DVB adapter
+	  - Octopus OEM
+	  - Octopus Mini
+	  - Cine S2 V6 DVB adapter
+	  - Cine S2 V6.5 DVB adapter
+	  - Octopus CI
+	  - Octopus CI single
+	  - DVBCT V6.1 DVB adapter
+	  - DVB-C modulator
+	  - SaTiX-S2 V3 DVB adapter
 
 	  Say Y if you own such a card and want to use it.
diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile
index 7446c8b..c274b81 100644
--- a/drivers/media/pci/ddbridge/Makefile
+++ b/drivers/media/pci/ddbridge/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the ddbridge device driver
 #
 
-ddbridge-objs := ddbridge-core.o
+ddbridge-objs := ddbridge-core.o ddbridge-i2c.o ddbridge-mod.o
 
 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 
-- 
1.8.4.2

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

* Re: [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends
  2013-11-03  0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
@ 2013-11-03  9:23   ` Mauro Carvalho Chehab
  2013-11-03 10:47     ` Ralph Metzler
  0 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03  9:23 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:24:25 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added support for DVB-C2 to DVB frontends. It will be required
> by cxd2843 and tda18212dd (Digital Devices) frontends.
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  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 */

Please update also the documentation, at Documentation/DocBook/media/dvb.

Doesn't DVB-C2 provide any newer property? If so, please add it there as
well, and at frontend.h.

Regards,
Maur
-- 

Cheers,
Mauro

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

* Re: [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
  2013-11-03  0:25 ` [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner Maik Broemme
@ 2013-11-03  9:27   ` Mauro Carvalho Chehab
  2013-11-03 12:17     ` Maik Broemme
  0 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03  9:27 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:25:23 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added (DD) to NXP TDA18271C2 silicon tuner as this tuner was
> specifically added for Digital Devices ddbridge driver.
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/dvb-frontends/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> index bddbab4..6f99eb8 100644
> --- a/drivers/media/dvb-frontends/Kconfig
> +++ b/drivers/media/dvb-frontends/Kconfig
> @@ -48,11 +48,11 @@ config DVB_DRXK
>  	  Say Y when you want to support this frontend.
>  
>  config DVB_TDA18271C2DD
> -	tristate "NXP TDA18271C2 silicon tuner"
> +	tristate "NXP TDA18271C2 silicon tuner (DD)"
>  	depends on DVB_CORE && I2C
>  	default m if !MEDIA_SUBDRV_AUTOSELECT
>  	help
> -	  NXP TDA18271 silicon tuner.
> +	  NXP TDA18271 silicon tuner (Digital Devices driver).
>  
>  	  Say Y when you want to support this tuner.
>  

The better is to use the other tda18271 driver. This one was added as a
temporary alternative, as the more complete one were lacking some
features, and were not working with DRX-K. Well, those got fixed already,
and we now want to get rid of this duplicated driver.

Regards,
Mauro
-- 

Cheers,
Mauro

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

* Re: [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
  2013-11-03  0:28 ` [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator Maik Broemme
@ 2013-11-03  9:29   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03  9:29 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:28:50 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added support for the STV 0367 DVB-C/T demodulator used by recent
> Digital Devices hardware. This will allow update of ddbridge driver
> to support newer devices like DVBCT V6.1 DVB adapter.

We have already a driver for stv0367. Please re-use it, adding there the
missing features (if any).

Regards,
Mauro

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/dvb-frontends/Kconfig          |    9 +
>  drivers/media/dvb-frontends/Makefile         |    1 +
>  drivers/media/dvb-frontends/stv0367dd.c      | 2329 +++++++++++++++++
>  drivers/media/dvb-frontends/stv0367dd.h      |   48 +
>  drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 ++++++++++++++++++++++++++
>  5 files changed, 5829 insertions(+)
>  create mode 100644 drivers/media/dvb-frontends/stv0367dd.c
>  create mode 100644 drivers/media/dvb-frontends/stv0367dd.h
>  create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h
> 
> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> index 6f99eb8..7cac015 100644
> --- a/drivers/media/dvb-frontends/Kconfig
> +++ b/drivers/media/dvb-frontends/Kconfig
> @@ -56,6 +56,15 @@ config DVB_TDA18271C2DD
>  
>  	  Say Y when you want to support this tuner.
>  
> +config DVB_STV0367DD
> +        tristate "STV 0367 (DD)"
> +        depends on DVB_CORE && I2C
> +        default m if DVB_FE_CUSTOMISE
> +        help
> +          STV 0367 DVB-C/T demodulator (Digital Devices 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 f9cb43d..de100f1 100644
> --- a/drivers/media/dvb-frontends/Makefile
> +++ b/drivers/media/dvb-frontends/Makefile
> @@ -97,6 +97,7 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
>  obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
>  obj-$(CONFIG_DVB_DRXK) += drxk.o
>  obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
> +obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
>  obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
>  obj-$(CONFIG_DVB_A8293) += a8293.o
>  obj-$(CONFIG_DVB_TDA10071) += tda10071.o
> diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c
> new file mode 100644
> index 0000000..37c8e2d
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/stv0367dd.c
> @@ -0,0 +1,2329 @@
> +/*
> + *  stv0367dd.c: STV0367 DVB-C/T demodulator driver
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#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 <asm/div64.h>
> +
> +#include "dvb_frontend.h"
> +#include "stv0367dd.h"
> +#include "stv0367dd_regs.h"
> +
> +enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C };
> +enum {  QAM_MOD_QAM4 = 0,
> +	QAM_MOD_QAM16,
> +	QAM_MOD_QAM32,
> +	QAM_MOD_QAM64,
> +	QAM_MOD_QAM128,
> +	QAM_MOD_QAM256,
> +	QAM_MOD_QAM512,
> +	QAM_MOD_QAM1024
> +};
> +
> +enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED };
> +
> +enum {
> +	QAM_FEC_A = 1,					/* J83 Annex A */
> +	QAM_FEC_B = (1<<1),				/* J83 Annex B */
> +	QAM_FEC_C = (1<<2)				/* J83 Annex C */
> +};
> +
> +enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted };
> +
> +struct stv_state {
> +#ifdef USE_API3
> +	struct dvb_frontend c_frontend;
> +	struct dvb_frontend t_frontend;
> +#else
> +	struct dvb_frontend frontend;
> +#endif
> +	fe_modulation_t modulation;
> +	u32 symbol_rate;
> +	u32 bandwidth;
> +	struct device *dev;
> +
> +	struct i2c_adapter *i2c;
> +	u8     adr;
> +	void  *priv;
> +
> +	struct mutex mutex;
> +	struct mutex ctlock;
> +
> +	u32 master_clock;
> +	u32 adc_clock;
> +	u8 ID;
> +	u8 I2CRPT;
> +	u32 omode;
> +	u8  qam_inversion;
> +
> +	s32 IF;
> +
> +	s32    m_FECTimeOut;
> +	s32    m_DemodTimeOut;
> +	s32    m_SignalTimeOut;
> +	s32    m_DemodLockTime;
> +	s32    m_FFTTimeOut;
> +	s32    m_TSTimeOut;
> +
> +	bool    m_bFirstTimeLock;
> +
> +	u8    m_Save_QAM_AGC_CTL;
> +
> +	enum EDemodState demod_state;
> +
> +	u8    m_OFDM_FFTMode;          // 0 = 2k, 1 = 8k, 2 = 4k
> +	u8    m_OFDM_Modulation;   //
> +	u8    m_OFDM_FEC;          //
> +	u8    m_OFDM_Guard;
> +
> +	u32   ucblocks;
> +	u32   ber;
> +};
> +
> +struct init_table {
> +	u16  adr;
> +	u8   data;
> +};
> +
> +struct init_table base_init[] = {
> +	{ R367_IOCFG0,     0x80 },
> +	{ R367_DAC0R,      0x00 },
> +	{ R367_IOCFG1,     0x00 },
> +	{ R367_DAC1R,      0x00 },
> +	{ R367_IOCFG2,     0x00 },
> +	{ R367_SDFR,       0x00 },
> +	{ R367_AUX_CLK,    0x00 },
> +	{ R367_FREESYS1,   0x00 },
> +	{ R367_FREESYS2,   0x00 },
> +	{ R367_FREESYS3,   0x00 },
> +	{ R367_GPIO_CFG,   0x55 },
> +	{ R367_GPIO_CMD,   0x01 },
> +	{ R367_TSTRES,     0x00 },
> +	{ R367_ANACTRL,    0x00 },
> +	{ R367_TSTBUS,     0x00 },
> +	{ R367_RF_AGC2,    0x20 },
> +	{ R367_ANADIGCTRL, 0x0b },
> +	{ R367_PLLMDIV,    0x01 },
> +	{ R367_PLLNDIV,    0x08 },
> +	{ R367_PLLSETUP,   0x18 },
> +	{ R367_DUAL_AD12,  0x04 },
> +	{ R367_TSTBIST,    0x00 },
> +	{ 0x0000,          0x00 }
> +};
> +
> +struct init_table qam_init[] = {
> +	{ R367_QAM_CTRL_1,                  0x06 },// Orginal 0x04
> +	{ R367_QAM_CTRL_2,                  0x03 },
> +	{ R367_QAM_IT_STATUS1,              0x2b },
> +	{ R367_QAM_IT_STATUS2,              0x08 },
> +	{ R367_QAM_IT_EN1,                  0x00 },
> +	{ R367_QAM_IT_EN2,                  0x00 },
> +	{ R367_QAM_CTRL_STATUS,             0x04 },
> +	{ R367_QAM_TEST_CTL,                0x00 },
> +	{ R367_QAM_AGC_CTL,                 0x73 },
> +	{ R367_QAM_AGC_IF_CFG,              0x50 },
> +	{ R367_QAM_AGC_RF_CFG,              0x02 },// RF Freeze
> +	{ R367_QAM_AGC_PWM_CFG,             0x03 },
> +	{ R367_QAM_AGC_PWR_REF_L,           0x5a },
> +	{ R367_QAM_AGC_PWR_REF_H,           0x00 },
> +	{ R367_QAM_AGC_RF_TH_L,             0xff },
> +	{ R367_QAM_AGC_RF_TH_H,             0x07 },
> +	{ R367_QAM_AGC_IF_LTH_L,            0x00 },
> +	{ R367_QAM_AGC_IF_LTH_H,            0x08 },
> +	{ R367_QAM_AGC_IF_HTH_L,            0xff },
> +	{ R367_QAM_AGC_IF_HTH_H,            0x07 },
> +	{ R367_QAM_AGC_PWR_RD_L,            0xa0 },
> +	{ R367_QAM_AGC_PWR_RD_M,            0xe9 },
> +	{ R367_QAM_AGC_PWR_RD_H,            0x03 },
> +	{ R367_QAM_AGC_PWM_IFCMD_L,         0xe4 },
> +	{ R367_QAM_AGC_PWM_IFCMD_H,         0x00 },
> +	{ R367_QAM_AGC_PWM_RFCMD_L,         0xff },
> +	{ R367_QAM_AGC_PWM_RFCMD_H,         0x07 },
> +	{ R367_QAM_IQDEM_CFG,               0x01 },
> +	{ R367_QAM_MIX_NCO_LL,              0x22 },
> +	{ R367_QAM_MIX_NCO_HL,              0x96 },
> +	{ R367_QAM_MIX_NCO_HH,              0x55 },
> +	{ R367_QAM_SRC_NCO_LL,              0xff },
> +	{ R367_QAM_SRC_NCO_LH,              0x0c },
> +	{ R367_QAM_SRC_NCO_HL,              0xf5 },
> +	{ R367_QAM_SRC_NCO_HH,              0x20 },
> +	{ R367_QAM_IQDEM_GAIN_SRC_L,        0x06 },
> +	{ R367_QAM_IQDEM_GAIN_SRC_H,        0x01 },
> +	{ R367_QAM_IQDEM_DCRM_CFG_LL,       0xfe },
> +	{ R367_QAM_IQDEM_DCRM_CFG_LH,       0xff },
> +	{ R367_QAM_IQDEM_DCRM_CFG_HL,       0x0f },
> +	{ R367_QAM_IQDEM_DCRM_CFG_HH,       0x00 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF0,        0x34 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF1,        0xae },
> +	{ R367_QAM_IQDEM_ADJ_COEFF2,        0x46 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF3,        0x77 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF4,        0x96 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF5,        0x69 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF6,        0xc7 },
> +	{ R367_QAM_IQDEM_ADJ_COEFF7,        0x01 },
> +	{ R367_QAM_IQDEM_ADJ_EN,            0x04 },
> +	{ R367_QAM_IQDEM_ADJ_AGC_REF,       0x94 },
> +	{ R367_QAM_ALLPASSFILT1,            0xc9 },
> +	{ R367_QAM_ALLPASSFILT2,            0x2d },
> +	{ R367_QAM_ALLPASSFILT3,            0xa3 },
> +	{ R367_QAM_ALLPASSFILT4,            0xfb },
> +	{ R367_QAM_ALLPASSFILT5,            0xf6 },
> +	{ R367_QAM_ALLPASSFILT6,            0x45 },
> +	{ R367_QAM_ALLPASSFILT7,            0x6f },
> +	{ R367_QAM_ALLPASSFILT8,            0x7e },
> +	{ R367_QAM_ALLPASSFILT9,            0x05 },
> +	{ R367_QAM_ALLPASSFILT10,           0x0a },
> +	{ R367_QAM_ALLPASSFILT11,           0x51 },
> +	{ R367_QAM_TRL_AGC_CFG,             0x20 },
> +	{ R367_QAM_TRL_LPF_CFG,             0x28 },
> +	{ R367_QAM_TRL_LPF_ACQ_GAIN,        0x44 },
> +	{ R367_QAM_TRL_LPF_TRK_GAIN,        0x22 },
> +	{ R367_QAM_TRL_LPF_OUT_GAIN,        0x03 },
> +	{ R367_QAM_TRL_LOCKDET_LTH,         0x04 },
> +	{ R367_QAM_TRL_LOCKDET_HTH,         0x11 },
> +	{ R367_QAM_TRL_LOCKDET_TRGVAL,      0x20 },
> +	{ R367_QAM_IQ_QAM,			0x01 },
> +	{ R367_QAM_FSM_STATE,               0xa0 },
> +	{ R367_QAM_FSM_CTL,                 0x08 },
> +	{ R367_QAM_FSM_STS,                 0x0c },
> +	{ R367_QAM_FSM_SNR0_HTH,            0x00 },
> +	{ R367_QAM_FSM_SNR1_HTH,            0x00 },
> +	{ R367_QAM_FSM_SNR2_HTH,            0x00 },
> +	{ R367_QAM_FSM_SNR0_LTH,            0x00 },
> +	{ R367_QAM_FSM_SNR1_LTH,            0x00 },
> +	{ R367_QAM_FSM_EQA1_HTH,            0x00 },
> +	{ R367_QAM_FSM_TEMPO,               0x32 },
> +	{ R367_QAM_FSM_CONFIG,              0x03 },
> +	{ R367_QAM_EQU_I_TESTTAP_L,         0x11 },
> +	{ R367_QAM_EQU_I_TESTTAP_M,         0x00 },
> +	{ R367_QAM_EQU_I_TESTTAP_H,         0x00 },
> +	{ R367_QAM_EQU_TESTAP_CFG,          0x00 },
> +	{ R367_QAM_EQU_Q_TESTTAP_L,         0xff },
> +	{ R367_QAM_EQU_Q_TESTTAP_M,         0x00 },
> +	{ R367_QAM_EQU_Q_TESTTAP_H,         0x00 },
> +	{ R367_QAM_EQU_TAP_CTRL,            0x00 },
> +	{ R367_QAM_EQU_CTR_CRL_CONTROL_L,   0x11 },
> +	{ R367_QAM_EQU_CTR_CRL_CONTROL_H,   0x05 },
> +	{ R367_QAM_EQU_CTR_HIPOW_L,         0x00 },
> +	{ R367_QAM_EQU_CTR_HIPOW_H,         0x00 },
> +	{ R367_QAM_EQU_I_EQU_LO,            0xef },
> +	{ R367_QAM_EQU_I_EQU_HI,            0x00 },
> +	{ R367_QAM_EQU_Q_EQU_LO,            0xee },
> +	{ R367_QAM_EQU_Q_EQU_HI,            0x00 },
> +	{ R367_QAM_EQU_MAPPER,              0xc5 },
> +	{ R367_QAM_EQU_SWEEP_RATE,          0x80 },
> +	{ R367_QAM_EQU_SNR_LO,              0x64 },
> +	{ R367_QAM_EQU_SNR_HI,              0x03 },
> +	{ R367_QAM_EQU_GAMMA_LO,            0x00 },
> +	{ R367_QAM_EQU_GAMMA_HI,            0x00 },
> +	{ R367_QAM_EQU_ERR_GAIN,            0x36 },
> +	{ R367_QAM_EQU_RADIUS,              0xaa },
> +	{ R367_QAM_EQU_FFE_MAINTAP,         0x00 },
> +	{ R367_QAM_EQU_FFE_LEAKAGE,         0x63 },
> +	{ R367_QAM_EQU_FFE_MAINTAP_POS,     0xdf },
> +	{ R367_QAM_EQU_GAIN_WIDE,           0x88 },
> +	{ R367_QAM_EQU_GAIN_NARROW,         0x41 },
> +	{ R367_QAM_EQU_CTR_LPF_GAIN,        0xd1 },
> +	{ R367_QAM_EQU_CRL_LPF_GAIN,        0xa7 },
> +	{ R367_QAM_EQU_GLOBAL_GAIN,         0x06 },
> +	{ R367_QAM_EQU_CRL_LD_SEN,          0x85 },
> +	{ R367_QAM_EQU_CRL_LD_VAL,          0xe2 },
> +	{ R367_QAM_EQU_CRL_TFR,             0x20 },
> +	{ R367_QAM_EQU_CRL_BISTH_LO,        0x00 },
> +	{ R367_QAM_EQU_CRL_BISTH_HI,        0x00 },
> +	{ R367_QAM_EQU_SWEEP_RANGE_LO,      0x00 },
> +	{ R367_QAM_EQU_SWEEP_RANGE_HI,      0x00 },
> +	{ R367_QAM_EQU_CRL_LIMITER,         0x40 },
> +	{ R367_QAM_EQU_MODULUS_MAP,         0x90 },
> +	{ R367_QAM_EQU_PNT_GAIN,            0xa7 },
> +	{ R367_QAM_FEC_AC_CTR_0,            0x16 },
> +	{ R367_QAM_FEC_AC_CTR_1,            0x0b },
> +	{ R367_QAM_FEC_AC_CTR_2,            0x88 },
> +	{ R367_QAM_FEC_AC_CTR_3,            0x02 },
> +	{ R367_QAM_FEC_STATUS,              0x12 },
> +	{ R367_QAM_RS_COUNTER_0,            0x7d },
> +	{ R367_QAM_RS_COUNTER_1,            0xd0 },
> +	{ R367_QAM_RS_COUNTER_2,            0x19 },
> +	{ R367_QAM_RS_COUNTER_3,            0x0b },
> +	{ R367_QAM_RS_COUNTER_4,            0xa3 },
> +	{ R367_QAM_RS_COUNTER_5,            0x00 },
> +	{ R367_QAM_BERT_0,                  0x01 },
> +	{ R367_QAM_BERT_1,                  0x25 },
> +	{ R367_QAM_BERT_2,                  0x41 },
> +	{ R367_QAM_BERT_3,                  0x39 },
> +	{ R367_QAM_OUTFORMAT_0,             0xc2 },
> +	{ R367_QAM_OUTFORMAT_1,             0x22 },
> +	{ R367_QAM_SMOOTHER_2,              0x28 },
> +	{ R367_QAM_TSMF_CTRL_0,             0x01 },
> +	{ R367_QAM_TSMF_CTRL_1,             0xc6 },
> +	{ R367_QAM_TSMF_CTRL_3,             0x43 },
> +	{ R367_QAM_TS_ON_ID_0,              0x00 },
> +	{ R367_QAM_TS_ON_ID_1,              0x00 },
> +	{ R367_QAM_TS_ON_ID_2,              0x00 },
> +	{ R367_QAM_TS_ON_ID_3,              0x00 },
> +	{ R367_QAM_RE_STATUS_0,             0x00 },
> +	{ R367_QAM_RE_STATUS_1,             0x00 },
> +	{ R367_QAM_RE_STATUS_2,             0x00 },
> +	{ R367_QAM_RE_STATUS_3,             0x00 },
> +	{ R367_QAM_TS_STATUS_0,             0x00 },
> +	{ R367_QAM_TS_STATUS_1,             0x00 },
> +	{ R367_QAM_TS_STATUS_2,             0xa0 },
> +	{ R367_QAM_TS_STATUS_3,             0x00 },
> +	{ R367_QAM_T_O_ID_0,                0x00 },
> +	{ R367_QAM_T_O_ID_1,                0x00 },
> +	{ R367_QAM_T_O_ID_2,                0x00 },
> +	{ R367_QAM_T_O_ID_3,                0x00 },
> +	{ 0x0000, 0x00 } // EOT
> +};
> +
> +struct init_table ofdm_init[] = {
> +	//{R367_OFDM_ID                   ,0x60},
> +	//{R367_OFDM_I2CRPT 				,0x22},
> +	//{R367_OFDM_TOPCTRL				,0x02},
> +	//{R367_OFDM_IOCFG0				,0x40},
> +	//{R367_OFDM_DAC0R				,0x00},
> +	//{R367_OFDM_IOCFG1				,0x00},
> +	//{R367_OFDM_DAC1R				,0x00},
> +	//{R367_OFDM_IOCFG2				,0x62},
> +	//{R367_OFDM_SDFR 				,0x00},
> +	//{R367_OFDM_STATUS				,0xf8},
> +	//{R367_OFDM_AUX_CLK				,0x0a},
> +	//{R367_OFDM_FREESYS1			,0x00},
> +	//{R367_OFDM_FREESYS2			,0x00},
> +	//{R367_OFDM_FREESYS3			,0x00},
> +	//{R367_OFDM_GPIO_CFG			,0x55},
> +	//{R367_OFDM_GPIO_CMD			,0x00},
> +	{R367_OFDM_AGC2MAX				,0xff},
> +	{R367_OFDM_AGC2MIN				,0x00},
> +	{R367_OFDM_AGC1MAX				,0xff},
> +	{R367_OFDM_AGC1MIN				,0x00},
> +	{R367_OFDM_AGCR					,0xbc},
> +	{R367_OFDM_AGC2TH				,0x00},
> +	//{R367_OFDM_AGC12C				,0x01}, //Note: This defines AGC pins, also needed for QAM
> +	{R367_OFDM_AGCCTRL1			,0x85},
> +	{R367_OFDM_AGCCTRL2			,0x1f},
> +	{R367_OFDM_AGC1VAL1			,0x00},
> +	{R367_OFDM_AGC1VAL2			,0x00},
> +	{R367_OFDM_AGC2VAL1			,0x6f},
> +	{R367_OFDM_AGC2VAL2			,0x05},
> +	{R367_OFDM_AGC2PGA				,0x00},
> +	{R367_OFDM_OVF_RATE1			,0x00},
> +	{R367_OFDM_OVF_RATE2			,0x00},
> +	{R367_OFDM_GAIN_SRC1			,0x2b},
> +	{R367_OFDM_GAIN_SRC2			,0x04},
> +	{R367_OFDM_INC_DEROT1			,0x55},
> +	{R367_OFDM_INC_DEROT2			,0x55},
> +	{R367_OFDM_PPM_CPAMP_DIR		,0x2c},
> +	{R367_OFDM_PPM_CPAMP_INV		,0x00},
> +	{R367_OFDM_FREESTFE_1			,0x00},
> +	{R367_OFDM_FREESTFE_2			,0x1c},
> +	{R367_OFDM_DCOFFSET			,0x00},
> +	{R367_OFDM_EN_PROCESS			,0x05},
> +	{R367_OFDM_SDI_SMOOTHER		,0x80},
> +	{R367_OFDM_FE_LOOP_OPEN		,0x1c},
> +	{R367_OFDM_FREQOFF1			,0x00},
> +	{R367_OFDM_FREQOFF2			,0x00},
> +	{R367_OFDM_FREQOFF3			,0x00},
> +	{R367_OFDM_TIMOFF1				,0x00},
> +	{R367_OFDM_TIMOFF2				,0x00},
> +	{R367_OFDM_EPQ					,0x02},
> +	{R367_OFDM_EPQAUTO				,0x01},
> +	{R367_OFDM_SYR_UPDATE			,0xf5},
> +	{R367_OFDM_CHPFREE						,0x00},
> +	{R367_OFDM_PPM_STATE_MAC		      ,0x23},
> +	{R367_OFDM_INR_THRESHOLD		      ,0xff},
> +	{R367_OFDM_EPQ_TPS_ID_CELL	      ,0xf9},
> +	{R367_OFDM_EPQ_CFG				      ,0x00},
> +	{R367_OFDM_EPQ_STATUS			      ,0x01},
> +	{R367_OFDM_AUTORELOCK			      ,0x81},
> +	{R367_OFDM_BER_THR_VMSB		      ,0x00},
> +	{R367_OFDM_BER_THR_MSB		      ,0x00},
> +	{R367_OFDM_BER_THR_LSB		      ,0x00},
> +	{R367_OFDM_CCD					      ,0x83},
> +	{R367_OFDM_SPECTR_CFG			      ,0x00},
> +	{R367_OFDM_CHC_DUMMY			      ,0x18},
> +	{R367_OFDM_INC_CTL				      ,0x88},
> +	{R367_OFDM_INCTHRES_COR1		      ,0xb4},
> +	{R367_OFDM_INCTHRES_COR2		      ,0x96},
> +	{R367_OFDM_INCTHRES_DET1		      ,0x0e},
> +	{R367_OFDM_INCTHRES_DET2		      ,0x11},
> +	{R367_OFDM_IIR_CELLNB				   ,0x8d},
> +	{R367_OFDM_IIRCX_COEFF1_MSB	      ,0x00},
> +	{R367_OFDM_IIRCX_COEFF1_LSB	      ,0x00},
> +	{R367_OFDM_IIRCX_COEFF2_MSB	      ,0x09},
> +	{R367_OFDM_IIRCX_COEFF2_LSB	      ,0x18},
> +	{R367_OFDM_IIRCX_COEFF3_MSB	      ,0x14},
> +	{R367_OFDM_IIRCX_COEFF3_LSB	      ,0x9c},
> +	{R367_OFDM_IIRCX_COEFF4_MSB	      ,0x00},
> +	{R367_OFDM_IIRCX_COEFF4_LSB	      ,0x00},
> +	{R367_OFDM_IIRCX_COEFF5_MSB	      ,0x36},
> +	{R367_OFDM_IIRCX_COEFF5_LSB			,0x42},
> +	{R367_OFDM_FEPATH_CFG			      ,0x00},
> +	{R367_OFDM_PMC1_FUNC			      ,0x65},
> +	{R367_OFDM_PMC1_FOR			      ,0x00},
> +	{R367_OFDM_PMC2_FUNC			      ,0x00},
> +	{R367_OFDM_STATUS_ERR_DA		      ,0xe0},
> +	{R367_OFDM_DIG_AGC_R			      ,0xfe},
> +	{R367_OFDM_COMAGC_TARMSB		      ,0x0b},
> +	{R367_OFDM_COM_AGC_TAR_ENMODE     ,0x41},
> +	{R367_OFDM_COM_AGC_CFG			   ,0x3e},
> +	{R367_OFDM_COM_AGC_GAIN1				,0x39},
> +	{R367_OFDM_AUT_AGC_TARGETMSB	   ,0x0b},
> +	{R367_OFDM_LOCK_DET_MSB			   ,0x01},
> +	{R367_OFDM_AGCTAR_LOCK_LSBS		   ,0x40},
> +	{R367_OFDM_AUT_GAIN_EN		      ,0xf4},
> +	{R367_OFDM_AUT_CFG				      ,0xf0},
> +	{R367_OFDM_LOCKN				      ,0x23},
> +	{R367_OFDM_INT_X_3				      ,0x00},
> +	{R367_OFDM_INT_X_2				      ,0x03},
> +	{R367_OFDM_INT_X_1				      ,0x8d},
> +	{R367_OFDM_INT_X_0				      ,0xa0},
> +	{R367_OFDM_MIN_ERRX_MSB		      ,0x00},
> +	{R367_OFDM_COR_CTL				      ,0x00},
> +	{R367_OFDM_COR_STAT			      ,0xf6},
> +	{R367_OFDM_COR_INTEN			      ,0x00},
> +	{R367_OFDM_COR_INTSTAT		      ,0x3f},
> +	{R367_OFDM_COR_MODEGUARD		      ,0x03},
> +	{R367_OFDM_AGC_CTL				      ,0x08},
> +	{R367_OFDM_AGC_MANUAL1		      ,0x00},
> +	{R367_OFDM_AGC_MANUAL2		      ,0x00},
> +	{R367_OFDM_AGC_TARG			      ,0x16},
> +	{R367_OFDM_AGC_GAIN1			      ,0x53},
> +	{R367_OFDM_AGC_GAIN2			      ,0x1d},
> +	{R367_OFDM_RESERVED_1			      ,0x00},
> +	{R367_OFDM_RESERVED_2			      ,0x00},
> +	{R367_OFDM_RESERVED_3			      ,0x00},
> +	{R367_OFDM_CAS_CTL				      ,0x44},
> +	{R367_OFDM_CAS_FREQ			      ,0xb3},
> +	{R367_OFDM_CAS_DAGCGAIN		      ,0x12},
> +	{R367_OFDM_SYR_CTL				      ,0x04},
> +	{R367_OFDM_SYR_STAT			      ,0x10},
> +	{R367_OFDM_SYR_NCO1			      ,0x00},
> +	{R367_OFDM_SYR_NCO2			      ,0x00},
> +	{R367_OFDM_SYR_OFFSET1		      ,0x00},
> +	{R367_OFDM_SYR_OFFSET2		      ,0x00},
> +	{R367_OFDM_FFT_CTL				      ,0x00},
> +	{R367_OFDM_SCR_CTL				      ,0x70},
> +	{R367_OFDM_PPM_CTL1			      ,0xf8},
> +	{R367_OFDM_TRL_CTL				      ,0xac},
> +	{R367_OFDM_TRL_NOMRATE1		      ,0x1e},
> +	{R367_OFDM_TRL_NOMRATE2		      ,0x58},
> +	{R367_OFDM_TRL_TIME1			      ,0x1d},
> +	{R367_OFDM_TRL_TIME2			      ,0xfc},
> +	{R367_OFDM_CRL_CTL				      ,0x24},
> +	{R367_OFDM_CRL_FREQ1			      ,0xad},
> +	{R367_OFDM_CRL_FREQ2			      ,0x9d},
> +	{R367_OFDM_CRL_FREQ3			      ,0xff},
> +	{R367_OFDM_CHC_CTL		       ,0x01},
> +	{R367_OFDM_CHC_SNR				      ,0xf0},
> +	{R367_OFDM_BDI_CTL				      ,0x00},
> +	{R367_OFDM_DMP_CTL				      ,0x00},
> +	{R367_OFDM_TPS_RCVD1			      ,0x30},
> +	{R367_OFDM_TPS_RCVD2			      ,0x02},
> +	{R367_OFDM_TPS_RCVD3			      ,0x01},
> +	{R367_OFDM_TPS_RCVD4			      ,0x00},
> +	{R367_OFDM_TPS_ID_CELL1		      ,0x00},
> +	{R367_OFDM_TPS_ID_CELL2		      ,0x00},
> +	{R367_OFDM_TPS_RCVD5_SET1	      ,0x02},
> +	{R367_OFDM_TPS_SET2			      ,0x02},
> +	{R367_OFDM_TPS_SET3			      ,0x01},
> +	{R367_OFDM_TPS_CTL				      ,0x00},
> +	{R367_OFDM_CTL_FFTOSNUM		      ,0x34},
> +	{R367_OFDM_TESTSELECT			      ,0x09},
> +	{R367_OFDM_MSC_REV 			      ,0x0a},
> +	{R367_OFDM_PIR_CTL 			      ,0x00},
> +	{R367_OFDM_SNR_CARRIER1 		      ,0xa1},
> +	{R367_OFDM_SNR_CARRIER2		      ,0x9a},
> +	{R367_OFDM_PPM_CPAMP			      ,0x2c},
> +	{R367_OFDM_TSM_AP0				      ,0x00},
> +	{R367_OFDM_TSM_AP1				      ,0x00},
> +	{R367_OFDM_TSM_AP2 			      ,0x00},
> +	{R367_OFDM_TSM_AP3				      ,0x00},
> +	{R367_OFDM_TSM_AP4				      ,0x00},
> +	{R367_OFDM_TSM_AP5				      ,0x00},
> +	{R367_OFDM_TSM_AP6				      ,0x00},
> +	{R367_OFDM_TSM_AP7				      ,0x00},
> +	//{R367_OFDM_TSTRES				 ,0x00},
> +	//{R367_OFDM_ANACTRL				 ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/
> +	//{R367_OFDM_TSTBUS				      ,0x00},
> +	//{R367_OFDM_TSTRATE				      ,0x00},
> +	{R367_OFDM_CONSTMODE			      ,0x01},
> +	{R367_OFDM_CONSTCARR1			      ,0x00},
> +	{R367_OFDM_CONSTCARR2			      ,0x00},
> +	{R367_OFDM_ICONSTEL			      ,0x0a},
> +	{R367_OFDM_QCONSTEL			      ,0x15},
> +	{R367_OFDM_TSTBISTRES0		      ,0x00},
> +	{R367_OFDM_TSTBISTRES1		      ,0x00},
> +	{R367_OFDM_TSTBISTRES2		      ,0x28},
> +	{R367_OFDM_TSTBISTRES3		      ,0x00},
> +	//{R367_OFDM_RF_AGC1				      ,0xff},
> +	//{R367_OFDM_RF_AGC2				      ,0x83},
> +	//{R367_OFDM_ANADIGCTRL			      ,0x19},
> +	//{R367_OFDM_PLLMDIV				      ,0x0c},
> +	//{R367_OFDM_PLLNDIV				      ,0x55},
> +	//{R367_OFDM_PLLSETUP			      ,0x18},
> +	//{R367_OFDM_DUAL_AD12			      ,0x00},
> +	//{R367_OFDM_TSTBIST				      ,0x00},
> +	//{R367_OFDM_PAD_COMP_CTRL		      ,0x00},
> +	//{R367_OFDM_PAD_COMP_WR		      ,0x00},
> +	//{R367_OFDM_PAD_COMP_RD		      ,0xe0},
> +	{R367_OFDM_SYR_TARGET_FFTADJT_MSB	,0x00},
> +	{R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00},
> +	{R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00},
> +	{R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00},
> +	{R367_OFDM_SYR_FLAG			 ,0x00},
> +	{R367_OFDM_CRL_TARGET1		 ,0x00},
> +	{R367_OFDM_CRL_TARGET2		 ,0x00},
> +	{R367_OFDM_CRL_TARGET3		 ,0x00},
> +	{R367_OFDM_CRL_TARGET4		 ,0x00},
> +	{R367_OFDM_CRL_FLAG			 ,0x00},
> +	{R367_OFDM_TRL_TARGET1		 ,0x00},
> +	{R367_OFDM_TRL_TARGET2		 ,0x00},
> +	{R367_OFDM_TRL_CHC				 ,0x00},
> +	{R367_OFDM_CHC_SNR_TARG		 ,0x00},
> +	{R367_OFDM_TOP_TRACK			      ,0x00},
> +	{R367_OFDM_TRACKER_FREE1		 ,0x00},
> +	{R367_OFDM_ERROR_CRL1			 ,0x00},
> +	{R367_OFDM_ERROR_CRL2			 ,0x00},
> +	{R367_OFDM_ERROR_CRL3			 ,0x00},
> +	{R367_OFDM_ERROR_CRL4			 ,0x00},
> +	{R367_OFDM_DEC_NCO1			 ,0x2c},
> +	{R367_OFDM_DEC_NCO2			 ,0x0f},
> +	{R367_OFDM_DEC_NCO3			 ,0x20},
> +	{R367_OFDM_SNR					 ,0xf1},
> +	{R367_OFDM_SYR_FFTADJ1		      ,0x00},
> +	{R367_OFDM_SYR_FFTADJ2		 ,0x00},
> +	{R367_OFDM_SYR_CHCADJ1		 ,0x00},
> +	{R367_OFDM_SYR_CHCADJ2		 ,0x00},
> +	{R367_OFDM_SYR_OFF				 ,0x00},
> +	{R367_OFDM_PPM_OFFSET1		      ,0x00},
> +	{R367_OFDM_PPM_OFFSET2		 ,0x03},
> +	{R367_OFDM_TRACKER_FREE2		 ,0x00},
> +	{R367_OFDM_DEBG_LT10			 ,0x00},
> +	{R367_OFDM_DEBG_LT11			 ,0x00},
> +	{R367_OFDM_DEBG_LT12			      ,0x00},
> +	{R367_OFDM_DEBG_LT13			 ,0x00},
> +	{R367_OFDM_DEBG_LT14			 ,0x00},
> +	{R367_OFDM_DEBG_LT15			 ,0x00},
> +	{R367_OFDM_DEBG_LT16			 ,0x00},
> +	{R367_OFDM_DEBG_LT17			 ,0x00},
> +	{R367_OFDM_DEBG_LT18			 ,0x00},
> +	{R367_OFDM_DEBG_LT19			 ,0x00},
> +	{R367_OFDM_DEBG_LT1A			 ,0x00},
> +	{R367_OFDM_DEBG_LT1B			 ,0x00},
> +	{R367_OFDM_DEBG_LT1C 			 ,0x00},
> +	{R367_OFDM_DEBG_LT1D 			 ,0x00},
> +	{R367_OFDM_DEBG_LT1E			 ,0x00},
> +	{R367_OFDM_DEBG_LT1F			 ,0x00},
> +	{R367_OFDM_RCCFGH				 ,0x00},
> +	{R367_OFDM_RCCFGM						,0x00},
> +	{R367_OFDM_RCCFGL						,0x00},
> +	{R367_OFDM_RCINSDELH					,0x00},
> +	{R367_OFDM_RCINSDELM			 ,0x00},
> +	{R367_OFDM_RCINSDELL			 ,0x00},
> +	{R367_OFDM_RCSTATUS			 ,0x00},
> +	{R367_OFDM_RCSPEED 			 ,0x6f},
> +	{R367_OFDM_RCDEBUGM			 ,0xe7},
> +	{R367_OFDM_RCDEBUGL			 ,0x9b},
> +	{R367_OFDM_RCOBSCFG			 ,0x00},
> +	{R367_OFDM_RCOBSM 				 ,0x00},
> +	{R367_OFDM_RCOBSL 				 ,0x00},
> +	{R367_OFDM_RCFECSPY			 ,0x00},
> +	{R367_OFDM_RCFSPYCFG 			 ,0x00},
> +	{R367_OFDM_RCFSPYDATA			 ,0x00},
> +	{R367_OFDM_RCFSPYOUT 			 ,0x00},
> +	{R367_OFDM_RCFSTATUS 			 ,0x00},
> +	{R367_OFDM_RCFGOODPACK		 ,0x00},
> +	{R367_OFDM_RCFPACKCNT 		 ,0x00},
> +	{R367_OFDM_RCFSPYMISC 		 ,0x00},
> +	{R367_OFDM_RCFBERCPT4 		 ,0x00},
> +	{R367_OFDM_RCFBERCPT3 		 ,0x00},
> +	{R367_OFDM_RCFBERCPT2 		 ,0x00},
> +	{R367_OFDM_RCFBERCPT1 		 ,0x00},
> +	{R367_OFDM_RCFBERCPT0 		 ,0x00},
> +	{R367_OFDM_RCFBERERR2 		 ,0x00},
> +	{R367_OFDM_RCFBERERR1 		 ,0x00},
> +	{R367_OFDM_RCFBERERR0 		 ,0x00},
> +	{R367_OFDM_RCFSTATESM 		 ,0x00},
> +	{R367_OFDM_RCFSTATESL 		 ,0x00},
> +	{R367_OFDM_RCFSPYBER  		 ,0x00},
> +	{R367_OFDM_RCFSPYDISTM		 ,0x00},
> +	{R367_OFDM_RCFSPYDISTL		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS7 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS6 		      ,0x00},
> +	{R367_OFDM_RCFSPYOBS5 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS4 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS3 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS2 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS1 		 ,0x00},
> +	{R367_OFDM_RCFSPYOBS0			 ,0x00},
> +	//{R367_OFDM_TSGENERAL 			 ,0x00},
> +	//{R367_OFDM_RC1SPEED  			 ,0x6f},
> +	//{R367_OFDM_TSGSTATUS			 ,0x18},
> +	{R367_OFDM_FECM					 ,0x01},
> +	{R367_OFDM_VTH12				 ,0xff},
> +	{R367_OFDM_VTH23				 ,0xa1},
> +	{R367_OFDM_VTH34				 ,0x64},
> +	{R367_OFDM_VTH56				 ,0x40},
> +	{R367_OFDM_VTH67				 ,0x00},
> +	{R367_OFDM_VTH78				 ,0x2c},
> +	{R367_OFDM_VITCURPUN			 ,0x12},
> +	{R367_OFDM_VERROR				 ,0x01},
> +	{R367_OFDM_PRVIT				 ,0x3f},
> +	{R367_OFDM_VAVSRVIT			 ,0x00},
> +	{R367_OFDM_VSTATUSVIT			 ,0xbd},
> +	{R367_OFDM_VTHINUSE 			 ,0xa1},
> +	{R367_OFDM_KDIV12				 ,0x20},
> +	{R367_OFDM_KDIV23				 ,0x40},
> +	{R367_OFDM_KDIV34				 ,0x20},
> +	{R367_OFDM_KDIV56				 ,0x30},
> +	{R367_OFDM_KDIV67				 ,0x00},
> +	{R367_OFDM_KDIV78				 ,0x30},
> +	{R367_OFDM_SIGPOWER 			 ,0x54},
> +	{R367_OFDM_DEMAPVIT 			 ,0x40},
> +	{R367_OFDM_VITSCALE 			 ,0x00},
> +	{R367_OFDM_FFEC1PRG 			 ,0x00},
> +	{R367_OFDM_FVITCURPUN 		 ,0x12},
> +	{R367_OFDM_FVERROR 			 ,0x01},
> +	{R367_OFDM_FVSTATUSVIT		 ,0xbd},
> +	{R367_OFDM_DEBUG_LT1			 ,0x00},
> +	{R367_OFDM_DEBUG_LT2			 ,0x00},
> +	{R367_OFDM_DEBUG_LT3			 ,0x00},
> +	{R367_OFDM_TSTSFMET  			 ,0x00},
> +	{R367_OFDM_SELOUT				 ,0x00},
> +	{R367_OFDM_TSYNC				 ,0x00},
> +	{R367_OFDM_TSTERR				 ,0x00},
> +	{R367_OFDM_TSFSYNC   			 ,0x00},
> +	{R367_OFDM_TSTSFERR  			 ,0x00},
> +	{R367_OFDM_TSTTSSF1  			 ,0x01},
> +	{R367_OFDM_TSTTSSF2  			 ,0x1f},
> +	{R367_OFDM_TSTTSSF3  			 ,0x00},
> +	{R367_OFDM_TSTTS1   			 ,0x00},
> +	{R367_OFDM_TSTTS2   			      ,0x1f},
> +	{R367_OFDM_TSTTS3   			 ,0x01},
> +	{R367_OFDM_TSTTS4   			 ,0x00},
> +	{R367_OFDM_TSTTSRC  			 ,0x00},
> +	{R367_OFDM_TSTTSRS  			 ,0x00},
> +	{R367_OFDM_TSSTATEM			 ,0xb0},
> +	{R367_OFDM_TSSTATEL			 ,0x40},
> +	{R367_OFDM_TSCFGH  			 ,0x80},
> +	{R367_OFDM_TSCFGM  			 ,0x00},
> +	{R367_OFDM_TSCFGL  			 ,0x20},
> +	{R367_OFDM_TSSYNC  			 ,0x00},
> +	{R367_OFDM_TSINSDELH			 ,0x00},
> +	{R367_OFDM_TSINSDELM 			 ,0x00},
> +	{R367_OFDM_TSINSDELL			 ,0x00},
> +	{R367_OFDM_TSDIVN				 ,0x03},
> +	{R367_OFDM_TSDIVPM				 ,0x00},
> +	{R367_OFDM_TSDIVPL				 ,0x00},
> +	{R367_OFDM_TSDIVQM 			 ,0x00},
> +	{R367_OFDM_TSDIVQL				 ,0x00},
> +	{R367_OFDM_TSDILSTKM			 ,0x00},
> +	{R367_OFDM_TSDILSTKL			 ,0x00},
> +	{R367_OFDM_TSSPEED				 ,0x6f},
> +	{R367_OFDM_TSSTATUS			 ,0x81},
> +	{R367_OFDM_TSSTATUS2			 ,0x6a},
> +	{R367_OFDM_TSBITRATEM			 ,0x0f},
> +	{R367_OFDM_TSBITRATEL			 ,0xc6},
> +	{R367_OFDM_TSPACKLENM			 ,0x00},
> +	{R367_OFDM_TSPACKLENL			 ,0xfc},
> +	{R367_OFDM_TSBLOCLENM			 ,0x0a},
> +	{R367_OFDM_TSBLOCLENL			 ,0x80},
> +	{R367_OFDM_TSDLYH 				 ,0x90},
> +	{R367_OFDM_TSDLYM				 ,0x68},
> +	{R367_OFDM_TSDLYL				 ,0x01},
> +	{R367_OFDM_TSNPDAV				 ,0x00},
> +	{R367_OFDM_TSBUFSTATH 		 ,0x00},
> +	{R367_OFDM_TSBUFSTATM 		 ,0x00},
> +	{R367_OFDM_TSBUFSTATL			 ,0x00},
> +	{R367_OFDM_TSDEBUGM			 ,0xcf},
> +	{R367_OFDM_TSDEBUGL			 ,0x1e},
> +	{R367_OFDM_TSDLYSETH 			 ,0x00},
> +	{R367_OFDM_TSDLYSETM			 ,0x68},
> +	{R367_OFDM_TSDLYSETL			 ,0x00},
> +	{R367_OFDM_TSOBSCFG			 ,0x00},
> +	{R367_OFDM_TSOBSM 				 ,0x47},
> +	{R367_OFDM_TSOBSL				 ,0x1f},
> +	{R367_OFDM_ERRCTRL1			 ,0x95},
> +	{R367_OFDM_ERRCNT1H 			 ,0x80},
> +	{R367_OFDM_ERRCNT1M 			 ,0x00},
> +	{R367_OFDM_ERRCNT1L 			 ,0x00},
> +	{R367_OFDM_ERRCTRL2			 ,0x95},
> +	{R367_OFDM_ERRCNT2H			 ,0x00},
> +	{R367_OFDM_ERRCNT2M			 ,0x00},
> +	{R367_OFDM_ERRCNT2L			 ,0x00},
> +	{R367_OFDM_FECSPY 				 ,0x88},
> +	{R367_OFDM_FSPYCFG				 ,0x2c},
> +	{R367_OFDM_FSPYDATA			 ,0x3a},
> +	{R367_OFDM_FSPYOUT				 ,0x06},
> +	{R367_OFDM_FSTATUS				 ,0x61},
> +	{R367_OFDM_FGOODPACK			 ,0xff},
> +	{R367_OFDM_FPACKCNT			 ,0xff},
> +	{R367_OFDM_FSPYMISC 			 ,0x66},
> +	{R367_OFDM_FBERCPT4 			 ,0x00},
> +	{R367_OFDM_FBERCPT3			 ,0x00},
> +	{R367_OFDM_FBERCPT2			 ,0x36},
> +	{R367_OFDM_FBERCPT1			 ,0x36},
> +	{R367_OFDM_FBERCPT0 			 ,0x14},
> +	{R367_OFDM_FBERERR2			 ,0x00},
> +	{R367_OFDM_FBERERR1			 ,0x03},
> +	{R367_OFDM_FBERERR0			 ,0x28},
> +	{R367_OFDM_FSTATESM			 ,0x00},
> +	{R367_OFDM_FSTATESL			 ,0x02},
> +	{R367_OFDM_FSPYBER 			 ,0x00},
> +	{R367_OFDM_FSPYDISTM			 ,0x01},
> +	{R367_OFDM_FSPYDISTL			 ,0x9f},
> +	{R367_OFDM_FSPYOBS7 			 ,0xc9},
> +	{R367_OFDM_FSPYOBS6 			 ,0x99},
> +	{R367_OFDM_FSPYOBS5			 ,0x08},
> +	{R367_OFDM_FSPYOBS4			 ,0xec},
> +	{R367_OFDM_FSPYOBS3			 ,0x01},
> +	{R367_OFDM_FSPYOBS2			 ,0x0f},
> +	{R367_OFDM_FSPYOBS1			 ,0xf5},
> +	{R367_OFDM_FSPYOBS0			 ,0x08},
> +	{R367_OFDM_SFDEMAP 			 ,0x40},
> +	{R367_OFDM_SFERROR 			 ,0x00},
> +	{R367_OFDM_SFAVSR  			 ,0x30},
> +	{R367_OFDM_SFECSTATUS			 ,0xcc},
> +	{R367_OFDM_SFKDIV12			 ,0x20},
> +	{R367_OFDM_SFKDIV23			 ,0x40},
> +	{R367_OFDM_SFKDIV34			 ,0x20},
> +	{R367_OFDM_SFKDIV56			 ,0x20},
> +	{R367_OFDM_SFKDIV67			 ,0x00},
> +	{R367_OFDM_SFKDIV78			 ,0x20},
> +	{R367_OFDM_SFDILSTKM			 ,0x00},
> +	{R367_OFDM_SFDILSTKL 			 ,0x00},
> +	{R367_OFDM_SFSTATUS			 ,0xb5},
> +	{R367_OFDM_SFDLYH				 ,0x90},
> +	{R367_OFDM_SFDLYM				 ,0x60},
> +	{R367_OFDM_SFDLYL				 ,0x01},
> +	{R367_OFDM_SFDLYSETH			 ,0xc0},
> +	{R367_OFDM_SFDLYSETM			 ,0x60},
> +	{R367_OFDM_SFDLYSETL			 ,0x00},
> +	{R367_OFDM_SFOBSCFG 			 ,0x00},
> +	{R367_OFDM_SFOBSM 				 ,0x47},
> +	{R367_OFDM_SFOBSL				 ,0x05},
> +	{R367_OFDM_SFECINFO 			 ,0x40},
> +	{R367_OFDM_SFERRCTRL 			 ,0x74},
> +	{R367_OFDM_SFERRCNTH			 ,0x80},
> +	{R367_OFDM_SFERRCNTM 			 ,0x00},
> +	{R367_OFDM_SFERRCNTL			 ,0x00},
> +	{R367_OFDM_SYMBRATEM			 ,0x2f},
> +	{R367_OFDM_SYMBRATEL			      ,0x50},
> +	{R367_OFDM_SYMBSTATUS			 ,0x7f},
> +	{R367_OFDM_SYMBCFG 			 ,0x00},
> +	{R367_OFDM_SYMBFIFOM 			 ,0xf4},
> +	{R367_OFDM_SYMBFIFOL 			 ,0x0d},
> +	{R367_OFDM_SYMBOFFSM 			 ,0xf0},
> +	{R367_OFDM_SYMBOFFSL 			 ,0x2d},
> +	//{R367_OFDM_DEBUG_LT4			 ,0x00},
> +	//{R367_OFDM_DEBUG_LT5			 ,0x00},
> +	//{R367_OFDM_DEBUG_LT6			 ,0x00},
> +	//{R367_OFDM_DEBUG_LT7			 ,0x00},
> +	//{R367_OFDM_DEBUG_LT8			 ,0x00},
> +	//{R367_OFDM_DEBUG_LT9			 ,0x00},
> +	{ 0x0000, 0x00 } // EOT
> +};
> +
> +static inline u32 MulDiv32(u32 a, u32 b, u32 c)
> +{
> +	u64 tmp64;
> +
> +	tmp64 = (u64)a * (u64)b;
> +	do_div(tmp64, c);
> +
> +	return (u32) tmp64;
> +}
> +
> +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) {
> +		printk("stv0367: i2c_write error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +#if 0
> +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) {
> +		printk("stv0367: i2c_read error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +#endif
> +
> +static int writereg(struct stv_state *state, u16 reg, u8 dat)
> +{
> +	u8 mm[3] = { (reg >> 8), reg & 0xff, dat };
> +
> +	return i2c_write(state->i2c, state->adr, mm, 3);
> +}
> +
> +static int readreg(struct stv_state *state, u16 reg, u8 *val)
> +{
> +	u8 msg[2] = {reg >> 8, reg & 0xff};
> +	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
> +				   .buf  = msg, .len   = 2},
> +				  {.addr = state->adr, .flags = I2C_M_RD,
> +				   .buf  = val, .len   = 1}};
> +	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +static int readregs(struct stv_state *state, u16 reg, u8 *val, int count)
> +{
> +	u8 msg[2] = {reg >> 8, reg & 0xff};
> +	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
> +				   .buf  = msg, .len   = 2},
> +				  {.addr = state->adr, .flags = I2C_M_RD,
> +				   .buf  = val, .len   = count}};
> +	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +static int write_init_table(struct stv_state *state, struct init_table *tab)
> +{
> +	while (1) {
> +		if (!tab->adr)
> +			break;
> +		if (writereg(state, tab->adr, tab->data) < 0)
> +			return -1;
> +		tab++;
> +	}
> +	return 0;
> +}
> +
> +static int qam_set_modulation(struct stv_state *state)
> +{
> +	int stat = 0;
> +
> +	switch(state->modulation) {
> +	case QAM_16:
> +		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 );
> +		writereg(state, R367_QAM_AGC_PWR_REF_L,0x64);       /* Set analog AGC reference */
> +		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
> +		writereg(state, R367_QAM_FSM_STATE,0x90);
> +		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
> +		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
> +		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
> +		writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a);
> +		break;
> +	case QAM_32:
> +		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 );
> +		writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e);       /* Set analog AGC reference */
> +		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
> +		writereg(state, R367_QAM_FSM_STATE,0xb0);
> +		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7);
> +		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d);
> +		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
> +		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
> +		break;
> +	case QAM_64:
> +		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 );
> +		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);       /* Set analog AGC reference */
> +		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82);   /* Set digital AGC reference */
> +		if(state->symbol_rate>4500000)
> +		{
> +			writereg(state, R367_QAM_FSM_STATE,0xb0);
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5);
> +		}
> +		else if(state->symbol_rate>2500000) // 25000000
> +		{
> +			writereg(state, R367_QAM_FSM_STATE,0xa0);
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
> +		}
> +		else
> +		{
> +			writereg(state, R367_QAM_FSM_STATE,0xa0);
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
> +		}
> +		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
> +		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
> +		writereg(state, R367_QAM_EQU_PNT_GAIN,0x99);
> +		break;
> +	case QAM_128:
> +		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 );
> +		writereg(state, R367_QAM_AGC_PWR_REF_L,0x76);       /* Set analog AGC reference */
> +		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);	/* Set digital AGC reference */
> +		writereg(state, R367_QAM_FSM_STATE,0x90);
> +		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1);
> +		if(state->symbol_rate>4500000) // 45000000
> +		{
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
> +		}
> +		else if(state->symbol_rate>2500000) // 25000000
> +		{
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
> +		}
> +		else
> +		{
> +			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97);
> +		}
> +		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e);
> +		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
> +		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
> +		break;
> +	case QAM_256:
> +		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 );
> +		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);     /* Set analog AGC reference */
> +		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */
> +		writereg(state, R367_QAM_FSM_STATE,0xa0);
> +		if(state->symbol_rate>4500000) // 45000000
> +		{
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +		}
> +		else if(state->symbol_rate>2500000) // 25000000
> +		{
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
> +		}
> +		else
> +		{
> +			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
> +		}
> +		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
> +		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85);
> +		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
> +		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
> +		break;
> +	default:
> +		stat = -EINVAL;
> +		break;
> +	}
> +	return stat;
> +}
> +
> +
> +static int QAM_SetSymbolRate(struct stv_state *state)
> +{
> +	int status = 0;
> +	u32 sr = state->symbol_rate;
> +	u32 Corr = 0;
> +	u32 Temp, Temp1, AdpClk;
> +
> +	switch(state->modulation) {
> +	default:
> +	case QAM_16:   Corr = 1032; break;
> +	case QAM_32:   Corr =  954; break;
> +	case QAM_64:   Corr =  983; break;
> +	case QAM_128:  Corr =  957; break;
> +	case QAM_256:  Corr =  948; break;
> +	}
> +
> +	// Transfer ration
> +	Temp = (256*sr) / state->adc_clock;
> +	writereg(state, R367_QAM_EQU_CRL_TFR,(Temp));
> +
> +	/* Symbol rate and SRC gain calculation */
> +	AdpClk = (state->master_clock) / 2000; /* TRL works at half the system clock */
> +
> +	Temp = state->symbol_rate;
> +	Temp1 = sr;
> +
> +	if(sr < 2097152)				/* 2097152 = 2^21 */
> +	{
> +		Temp  = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8;
> +		Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000;
> +	}
> +	else if(sr < 4194304)			/* 4194304 = 2**22 */
> +	{
> +		Temp  = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16;
> +		Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000;
> +	}
> +	else if(sr < 8388608)			/* 8388608 = 2**23 */
> +	{
> +		Temp  = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32;
> +		Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000;
> +	}
> +	else
> +	{
> +		Temp  = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64;
> +		Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000;
> +	}
> +
> +	///* Filters' coefficients are calculated and written into registers only if the filters are enabled */
> +	//if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init!
> +	//{
> +	//    FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate);
> +	//}
> +	///* AllPass filter is never used on this IC */
> +	//ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init!
> +
> +	writereg(state, R367_QAM_SRC_NCO_LL,(Temp));
> +	writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8));
> +	writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16));
> +	writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24));
> +
> +	writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1));
> +	writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8));
> +	return status;
> +}
> +
> +
> +static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency)
> +{
> +	int status = 0;
> +	u32 Sampled_IF;
> +
> +	do {
> +		//if (DerotFrequency < 1000000)
> +		//    DerotFrequency = state->adc_clock/4; /* ZIF operation */
> +		if (DerotFrequency > state->adc_clock)
> +			DerotFrequency = DerotFrequency - state->adc_clock;	// User Alias
> +
> +		Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256;
> +		if(Sampled_IF > 8388607)
> +			Sampled_IF = 8388607;
> +
> +		writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF));
> +		writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8));
> +		writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16));
> +	} while(0);
> +
> +	return status;
> +}
> +
> +
> +
> +static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
> +{
> +	int status = 0;
> +	u32 AGCTimeOut = 25;
> +	u32 TRLTimeOut = 100000000 / state->symbol_rate;
> +	u32 CRLSymbols = 0;
> +	u32 EQLTimeOut = 100;
> +	u32 SearchRange = state->symbol_rate / 25;
> +	u32 CRLTimeOut;
> +	u8 Temp;
> +
> +	if( state->demod_state != QAMSet ) {
> +		writereg(state, R367_DEBUG_LT4,0x00);
> +		writereg(state, R367_DEBUG_LT5,0x01);
> +		writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1
> +		writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2
> +		writereg(state, R367_DEBUG_LT8,0x00);
> +		writereg(state, R367_DEBUG_LT9,0x00);
> +
> +		// Tuner Setup
> +		writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */
> +		writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */
> +
> +		// Clock setup
> +		writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */
> +		writereg(state, R367_TOPCTRL,0x10); // Set QAM
> +
> +		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
> +		writereg(state, R367_PLLNDIV,232);
> +		writereg(state, R367_PLLSETUP,0x18);  /* ADC clock is equal to system clock */
> +
> +		msleep(50);
> +		writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */
> +
> +		state->master_clock = 58000000;
> +		state->adc_clock = 58000000;
> +
> +		state->demod_state = QAMSet;
> +	}
> +
> +	state->m_bFirstTimeLock = true;
> +	state->m_DemodLockTime  = -1;
> +
> +	qam_set_modulation(state);
> +	QAM_SetSymbolRate(state);
> +
> +	// Will make problems on low symbol rates ( < 2500000 )
> +
> +	switch(state->modulation) {
> +	default:
> +	case QAM_16:   CRLSymbols = 150000; break;
> +	case QAM_32:   CRLSymbols = 250000; break;
> +	case QAM_64:   CRLSymbols = 200000; break;
> +	case QAM_128:  CRLSymbols = 250000; break;
> +	case QAM_256:  CRLSymbols = 250000; break;
> +	}
> +
> +	CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000);
> +	CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate;
> +	if( CRLTimeOut < 50 ) CRLTimeOut = 50;
> +
> +	state->m_FECTimeOut = 20;
> +	state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
> +	state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut;
> +
> +	// QAM_AGC_ACCUMRSTSEL = 0;
> +	readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL);
> +	writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F);
> +
> +	// QAM_MODULUSMAP_EN = 0
> +	readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp);
> +	writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40);
> +
> +	// QAM_SWEEP_EN = 0
> +	readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp);
> +	writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08);
> +
> +	QAM_SetDerotFrequency(state, IntermediateFrequency);
> +
> +	// Release TRL
> +	writereg(state, R367_QAM_CTRL_1,0x00);
> +
> +	state->IF = IntermediateFrequency;
> +	state->demod_state = QAMStarted;
> +
> +	return status;
> +}
> +
> +static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
> +{
> +	int status = 0;
> +	u8 GAIN_SRC1;
> +	u32 Derot;
> +	u8 SYR_CTL;
> +	u8 tmp1;
> +	u8 tmp2;
> +
> +	if ( state->demod_state != OFDMSet ) {
> +		// QAM Disable
> +		writereg(state, R367_DEBUG_LT4, 0x00);
> +		writereg(state, R367_DEBUG_LT5, 0x00);
> +		writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1
> +		writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2
> +		writereg(state, R367_DEBUG_LT8, 0x00);
> +		writereg(state, R367_DEBUG_LT9, 0x00);
> +
> +		// Tuner Setup
> +		writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */
> +		writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
> +
> +		// Clock setup
> +		writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
> +		writereg(state, R367_TOPCTRL, 0x00); // Set OFDM
> +
> +		writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */
> +		writereg(state, R367_PLLNDIV, 8);
> +		writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
> +
> +		msleep(50);
> +		writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
> +
> +		state->master_clock = 54000000;
> +		state->adc_clock    = 54000000;
> +
> +		state->demod_state = OFDMSet;
> +	}
> +
> +	state->m_bFirstTimeLock = true;
> +	state->m_DemodLockTime  = -1;
> +
> +	// Set inversion in GAIN_SRC1 (fixed from init)
> +	//  is in GAIN_SRC1, see below
> +
> +	GAIN_SRC1 = 0xA0;
> +	// Bandwidth
> +
> +	// Fixed values for 54 MHz
> +	switch(state->bandwidth) {
> +	case 0:
> +	case 8000000:
> +		// Normrate = 44384;
> +		writereg(state, R367_OFDM_TRL_CTL,0x14);
> +		writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0);
> +		writereg(state, R367_OFDM_TRL_NOMRATE2,0x56);
> +		// Gain SRC = 2774
> +		writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1);
> +		writereg(state, R367_OFDM_GAIN_SRC2,0xD6);
> +		break;
> +	case 7000000:
> +		// Normrate = 38836;
> +		writereg(state, R367_OFDM_TRL_CTL,0x14);
> +		writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA);
> +		writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B);
> +		// Gain SRC = 2427
> +		writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1);
> +		writereg(state, R367_OFDM_GAIN_SRC2,0x7B);
> +		break;
> +	case 6000000:
> +		// Normrate = 33288;
> +		writereg(state, R367_OFDM_TRL_CTL,0x14);
> +		writereg(state, R367_OFDM_TRL_NOMRATE1,0x04);
> +		writereg(state, R367_OFDM_TRL_NOMRATE2,0x41);
> +		// Gain SRC = 2080
> +		writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1);
> +		writereg(state, R367_OFDM_GAIN_SRC2,0x20);
> +		break;
> +	default:
> +		return -EINVAL;
> +		break;
> +	}
> +
> +	Derot = ((IntermediateFrequency / 1000) * 65536) / (state->master_clock / 1000);
> +
> +	writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8));
> +	writereg(state, R367_OFDM_INC_DEROT2,(Derot));
> +
> +	readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL);
> +	SYR_CTL  &= ~0x78;
> +	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // EchoPos = 0
> +
> +
> +	writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3
> +	SYR_CTL &= 0x01;
> +	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // SYR_TR_DIS = 0
> +
> +	msleep(5);
> +
> +	writereg(state, R367_OFDM_COR_CTL,0x20);    // Start core
> +
> +	// -- Begin M.V.
> +	// Reset FEC and Read Solomon
> +	readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
> +	readreg(state, R367_TSGENERAL,&tmp2);
> +	writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08);
> +	writereg(state, R367_TSGENERAL,tmp2 | 0x01);
> +	// -- End M.V.
> +
> +	state->m_SignalTimeOut = 200;
> +	state->IF = IntermediateFrequency;
> +	state->demod_state = OFDMStarted;
> +	state->m_DemodTimeOut = 0;
> +	state->m_FECTimeOut = 0;
> +	state->m_TSTimeOut = 0;
> +
> +	return status;
> +}
> +
> +#if 0
> +static int Stop(struct stv_state *state)
> +{
> +	int status = 0;
> +
> +	switch(state->demod_state)
> +	{
> +	case QAMStarted:
> +		status = writereg(state, R367_QAM_CTRL_1,0x06);
> +		state->demod_state = QAMSet;
> +		break;
> +	case OFDMStarted:
> +		status = writereg(state, R367_OFDM_COR_CTL,0x00);
> +		state->demod_state = OFDMSet;
> +		break;
> +	default:
> +		break;
> +	}
> +	return status;
> +}
> +#endif
> +
> +static s32 Log10x100(u32 x)
> +{
> +	static u32 LookupTable[100] = {
> +		101157945, 103514217, 105925373, 108392691, 110917482,
> +		113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5
> +		127350308, 130316678, 133352143, 136458314, 139636836,
> +		142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
> +		160324539, 164058977, 167880402, 171790839, 175792361,
> +		179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
> +		201836636, 206538016, 211348904, 216271852, 221309471,
> +		226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
> +		254097271, 260015956, 266072506, 272270131, 278612117,
> +		285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
> +		319889511, 327340695, 334965439, 342767787, 350751874,
> +		358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
> +		402717034, 412097519, 421696503, 431519077, 441570447,
> +		451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
> +		506990708, 518800039, 530884444, 543250331, 555904257,
> +		568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
> +		638263486, 653130553, 668343918, 683911647, 699841996,
> +		716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
> +		803526122, 822242650, 841395142, 860993752, 881048873,
> +		901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
> +	};
> +	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;
> +}
> +
> +static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
> +{
> +	u32 RegValAvg = 0;
> +	u8 RegVal[2];
> +	int status = 0, i;
> +
> +	*pSignalToNoise = 0;
> +	for (i = 0; i < 10; i += 1 ) {
> +		readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2);
> +		RegValAvg += RegVal[0] + 256 * RegVal[1];
> +	}
> +	if (RegValAvg != 0) {
> +		s32 Power = 1;
> +		switch(state->modulation) {
> +		case QAM_16:
> +			Power = 20480;
> +			break;
> +		case QAM_32:
> +			Power = 23040;
> +			break;
> +		case QAM_64:
> +			Power = 21504;
> +			break;
> +		case QAM_128:
> +			Power = 23616; 
> +			break;
> +		case QAM_256:
> +			Power = 21760; 
> +			break;
> +		default:
> +			break;
> +		}
> +		*pSignalToNoise = Log10x100((Power * 320) / RegValAvg);
> +	} else {
> +		*pSignalToNoise = 380;
> +	}
> +	return status;
> +}
> +
> +static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
> +{
> +	u8 CHC_SNR = 0;
> +
> +	int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR);
> +	if (status >= 0) {
> +		// Note: very unclear documentation on this.
> +		//   Datasheet states snr = CHC_SNR/4 dB  -> way to high values!
> +		//   Software  snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values
> +		//   Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367
> +		//   361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best
> +		*pSignalToNoise = ( (s32)CHC_SNR * 10) / 8;
> +	}
> +	//printk("SNR %d\n", *pSignalToNoise);
> +	return status;
> +}
> +
> +#if 0
> +static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
> +{
> +	*pQuality = 100;
> +	return 0;
> +};
> +
> +static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
> +{
> +	static s32 QE_SN[] = {
> +		51, // QPSK 1/2
> +		69, // QPSK 2/3
> +		79, // QPSK 3/4
> +		89, // QPSK 5/6
> +		97, // QPSK 7/8
> +		108, // 16-QAM 1/2
> +		131, // 16-QAM 2/3
> +		146, // 16-QAM 3/4
> +		156, // 16-QAM 5/6
> +		160, // 16-QAM 7/8
> +		165, // 64-QAM 1/2
> +		187, // 64-QAM 2/3
> +		202, // 64-QAM 3/4
> +		216, // 64-QAM 5/6
> +		225, // 64-QAM 7/8
> +	};
> +	u8 TPS_Received[2];
> +	int Constellation;
> +	int CodeRate;
> +	s32 SignalToNoiseRel, BERQuality;
> +
> +	*pQuality = 0;
> +	readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received));
> +	Constellation = TPS_Received[0] & 0x03;
> +	CodeRate = TPS_Received[1] & 0x07;
> +
> +	if( Constellation > 2 || CodeRate > 5 )
> +		return -1;
> +	SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate];
> +	BERQuality = 100;
> +
> +	if( SignalToNoiseRel < -70 )
> +		*pQuality = 0;
> +	else if( SignalToNoiseRel < 30 ) {
> +		*pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100;
> +	} else
> +		*pQuality = BERQuality;
> +	return 0;
> +};
> +
> +static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise)
> +{
> +	s32 SignalToNoiseRel = 0;
> +	s32 Quality = 0;
> +	s32 BERQuality = 100;
> +
> +	switch(state->modulation) {
> +	case QAM_16:  SignalToNoiseRel = SignalToNoise - 200 ; break;
> +	case QAM_32:  SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig
> +	case QAM_64:  SignalToNoiseRel = SignalToNoise - 260 ; break;
> +	case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break;
> +	case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break;
> +	}
> +
> +	if( SignalToNoiseRel < -70 ) Quality = 0;
> +	else if( SignalToNoiseRel < 30 )
> +	{
> +		Quality = ((SignalToNoiseRel + 70) * BERQuality)/100;
> +	}
> +	else
> +	Quality = BERQuality;
> +
> +	return Quality;
> +}
> +
> +static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
> +{
> +	*pQuality = 0;
> +	switch(state->demod_state)
> +	{
> +	case QAMStarted:
> +		*pQuality = DVBCQuality(state, SignalToNoise);
> +		break;
> +	case OFDMStarted:
> +		return DVBT_GetQuality(state, SignalToNoise, pQuality);
> +	}
> +	return 0;
> +};
> +#endif
> +
> +static int attach_init(struct stv_state *state)
> +{
> +	int stat = 0;
> +
> +	stat = readreg(state, R367_ID, &state->ID);
> +	if ( stat < 0 || state->ID != 0x60 )
> +		return -ENODEV;
> +	printk("stv0367 found\n");
> +
> +	writereg(state, R367_TOPCTRL, 0x10);
> +	write_init_table(state, base_init);
> +	write_init_table(state, qam_init);
> +
> +	writereg(state, R367_TOPCTRL, 0x00);
> +	write_init_table(state, ofdm_init);
> +
> +	writereg(state, R367_OFDM_GAIN_SRC1, 0x2A);
> +	writereg(state, R367_OFDM_GAIN_SRC2, 0xD6);
> +	writereg(state, R367_OFDM_INC_DEROT1, 0x55);
> +	writereg(state, R367_OFDM_INC_DEROT2, 0x55);
> +	writereg(state, R367_OFDM_TRL_CTL, 0x14);
> +	writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE);
> +	writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56);
> +	writereg(state, R367_OFDM_FEPATH_CFG, 0x0);
> +
> +	// OFDM TS Setup
> +
> +	writereg(state, R367_OFDM_TSCFGH, 0x70);
> +	writereg(state, R367_OFDM_TSCFGM, 0xC0);
> +	writereg(state, R367_OFDM_TSCFGL, 0x20);
> +	writereg(state, R367_OFDM_TSSPEED, 0x40);        // Fixed at 54 MHz
> +	//writereg(state, R367_TSTBUS, 0x80);      // Invert CLK
> +
> +	writereg(state, R367_OFDM_TSCFGH, 0x71);
> +	writereg(state, R367_OFDM_TSCFGH, 0x70);
> +
> +	writereg(state, R367_TOPCTRL, 0x10);
> +
> +	// Also needed for QAM
> +	writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup
> +
> +	writereg(state, R367_OFDM_AGCCTRL1, 0x8A); //
> +
> +	// QAM TS setup, note exact format also depends on descrambler settings
> +	writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial
> +	// writereg(state, R367_QAM_OUTFORMAT_1, 0x00); //
> +
> +	// Clock setup
> +	writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
> +
> +	if( state->master_clock == 58000000 ) {
> +		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
> +		writereg(state, R367_PLLNDIV,232);
> +	} else {
> +		writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */
> +		writereg(state, R367_PLLNDIV,8);
> +	}
> +	writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
> +
> +	// Tuner setup
> +	writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */
> +	writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
> +
> +	writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */
> +	writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */
> +	writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */
> +	writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */
> +
> +	writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
> +
> +	writereg(state, R367_I2CRPT, state->I2CRPT);
> +	state->demod_state    = QAMSet;
> +	return stat;
> +}
> +
> +#ifdef USE_API3
> +static void c_release(struct dvb_frontend* fe)
> +#else
> +static void release(struct dvb_frontend* fe)
> +#endif
> +{
> +	struct stv_state *state=fe->demodulator_priv;
> +	printk("%s\n", __FUNCTION__);
> +	kfree(state);
> +}
> +
> +#ifdef USE_API3
> +static int c_init (struct dvb_frontend *fe)
> +{
> +	struct stv_state *state=fe->demodulator_priv;
> +
> +	if (mutex_trylock(&state->ctlock)==0)
> +		return -EBUSY;
> +	state->omode = OM_DVBC;
> +	return 0;
> +}
> +
> +static int c_sleep(struct dvb_frontend* fe)
> +{
> +	struct stv_state *state=fe->demodulator_priv;
> +
> +	mutex_unlock(&state->ctlock);
> +	return 0;
> +}
> +#endif
> +
> +static int gate_ctrl(struct dvb_frontend *fe, int enable)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +	u8 i2crpt = state->I2CRPT & ~0x80;
> +
> +	if (enable)
> +		i2crpt |= 0x80;
> +	if (writereg(state, R367_I2CRPT, i2crpt) < 0)
> +		return -1;
> +	state->I2CRPT = i2crpt;
> +	return 0;
> +}
> +
> +#if 0
> +static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
> +{
> +	return DVBFE_ALGO_SEARCH_AGAIN;
> +}
> +#endif
> +
> +#if 0
> +int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
> +int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
> +#endif
> +
> +static int ofdm_lock(struct stv_state *state)
> +{
> +	int status = 0;
> +	u8 OFDM_Status;
> +	s32 DemodTimeOut = 10;
> +	s32 FECTimeOut = 0;
> +	s32 TSTimeOut = 0;
> +	u8 CPAMPMin = 255;
> +	u8 CPAMPValue;
> +	u8 SYR_STAT;
> +	u8 FFTMode;
> +	u8 TSStatus;
> +
> +	msleep(state->m_SignalTimeOut);
> +	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
> +
> +	if (!(OFDM_Status & 0x40))
> +		return -1;
> +	//printk("lock 1\n");
> +
> +	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
> +	FFTMode = (SYR_STAT & 0x0C) >> 2;
> +
> +	switch(FFTMode)
> +	{
> +	    case 0: // 2K
> +		DemodTimeOut = 10;
> +		FECTimeOut = 150;
> +		TSTimeOut = 125;
> +		CPAMPMin = 20;
> +		break;
> +	    case 1: // 8K
> +		DemodTimeOut = 55;
> +		FECTimeOut = 600;
> +		TSTimeOut = 500;
> +		CPAMPMin = 80;
> +		break;
> +	    case 2: // 4K
> +		DemodTimeOut = 40;
> +		FECTimeOut = 300;
> +		TSTimeOut = 250;
> +		CPAMPMin = 30;
> +		break;
> +	}
> +	state->m_OFDM_FFTMode = FFTMode;
> +	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
> +	msleep(DemodTimeOut);
> +	{
> +	    // Release FEC and Read Solomon Reset
> +	    u8 tmp1;
> +	    u8 tmp2;
> +	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
> +	    readreg(state, R367_TSGENERAL,&tmp2);
> +	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
> +	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
> +	}
> +	msleep(FECTimeOut);
> +	if( (OFDM_Status & 0x98) != 0x98 )
> +		;//return -1;
> +	//printk("lock 2\n");
> +
> +	{
> +	    u8 Guard = (SYR_STAT & 0x03);
> +	    if(Guard < 2)
> +	    {
> +		u8 tmp;
> +		readreg(state, R367_OFDM_SYR_CTL,&tmp);
> +		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
> +		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
> +		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
> +	    } else {
> +		u8 tmp;
> +		readreg(state, R367_OFDM_SYR_CTL,&tmp);
> +		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
> +		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
> +		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
> +	    }
> +
> +	    // apply Sfec workaround if 8K 64QAM CR!=1/2
> +	    if( FFTMode == 1)
> +	    {
> +		u8 tmp[2];
> +		readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2);
> +		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
> +		{
> +		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
> +		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
> +		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
> +		}
> +		else
> +		{
> +		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
> +		}
> +	    }
> +	}
> +	msleep(TSTimeOut);
> +	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
> +	if( (TSStatus & 0x80) != 0x80 )
> +		return -1;
> +	//printk("lock 3\n");
> +	return status;
> +}
> +
> +
> +#ifdef USE_API3
> +static int set_parameters(struct dvb_frontend *fe,
> +			  struct dvb_frontend_parameters *p)
> +{
> +	int stat;
> +	struct stv_state *state = fe->demodulator_priv;
> +	u32 OF = 0;
> +	u32 IF;
> +
> +	if (fe->ops.tuner_ops.set_params)
> +		fe->ops.tuner_ops.set_params(fe, p);
> +
> +	switch (state->omode) {
> +	case OM_DVBC:
> +	case OM_QAM_ITU_C:
> +		state->modulation = p->u.qam.modulation;
> +		state->symbol_rate = p->u.qam.symbol_rate;
> +		break;
> +	case OM_DVBT:
> +		switch (p->u.ofdm.bandwidth) {
> +		case BANDWIDTH_AUTO:
> +		case BANDWIDTH_8_MHZ:
> +			state->bandwidth = 8000000;
> +			break;
> +		case BANDWIDTH_7_MHZ:
> +			state->bandwidth = 7000000;
> +			break;
> +		case BANDWIDTH_6_MHZ:
> +			state->bandwidth = 6000000;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +#else
> +static int set_parameters(struct dvb_frontend *fe)
> +{
> +	int stat;
> +	struct stv_state *state = fe->demodulator_priv;
> +	u32 OF = 0;
> +	u32 IF;
> +
> +	switch (fe->dtv_property_cache.delivery_system) {
> +	case SYS_DVBC_ANNEX_A:
> +		state->omode = OM_DVBC;
> +		/* symbol rate 0 might cause an oops */
> +		if (fe->dtv_property_cache.symbol_rate == 0) {
> +			printk(KERN_ERR "stv0367dd: Invalid symbol rate\n");
> +			return -EINVAL;
> +		}
> +		break;
> +	case SYS_DVBT:
> +		state->omode = OM_DVBT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (fe->ops.tuner_ops.set_params)
> +		fe->ops.tuner_ops.set_params(fe);
> +	state->modulation = fe->dtv_property_cache.modulation;
> +	state->symbol_rate = fe->dtv_property_cache.symbol_rate;
> +	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
> +#endif
> +	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
> +	//fe->ops.tuner_ops.get_frequency(fe, &IF);
> +
> +	switch(state->omode) {
> +	case OM_DVBT:
> +		stat = OFDM_Start(state, OF, IF);
> +		ofdm_lock(state);
> +		break;
> +	case OM_DVBC:
> +	case OM_QAM_ITU_C:
> +		stat = QAM_Start(state, OF, IF);
> +		break;
> +	default:
> +		stat = -EINVAL;
> +	}
> +	//printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF);
> +	return stat;
> +}
> +
> +#if 0
> +static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
> +{
> +	//struct stv_state *state = fe->demodulator_priv;
> +	//printk("%s\n", __FUNCTION__);
> +	return 0;
> +}
> +
> +static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time)
> +{
> +	int status = STATUS_SUCCESS;
> +	u8 OFDM_Status;
> +	s32 DemodTimeOut = 0;
> +	s32 FECTimeOut = 0;
> +	s32 TSTimeOut = 0;
> +	u8 CPAMPMin = 255;
> +	u8 CPAMPValue;
> +	bool SYRLock;
> +	u8 SYR_STAT;
> +	u8 FFTMode;
> +	u8 TSStatus;
> +
> +	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
> +
> +	SYRLock = (OFDM_Status & 0x40) != 0;
> +
> +	if( Time > m_SignalTimeOut && !SYRLock )
> +	{
> +	    *pLockStatus = NEVER_LOCK;
> +	    break;
> +	}
> +
> +	if( !SYRLock ) break;
> +
> +	*pLockStatus = SIGNAL_PRESENT;
> +
> +	// Check Mode
> +
> +	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
> +	FFTMode = (SYR_STAT & 0x0C) >> 2;
> +
> +	switch(FFTMode)
> +	{
> +	    case 0: // 2K
> +		DemodTimeOut = 10;
> +		FECTimeOut = 150;
> +		TSTimeOut = 125;
> +		CPAMPMin = 20;
> +		break;
> +	    case 1: // 8K
> +		DemodTimeOut = 55;
> +		FECTimeOut = 600;
> +		TSTimeOut = 500;
> +		CPAMPMin = 80;
> +		break;
> +	    case 2: // 4K
> +		DemodTimeOut = 40;
> +		FECTimeOut = 300;
> +		TSTimeOut = 250;
> +		CPAMPMin = 30;
> +		break;
> +	}
> +
> +	m_OFDM_FFTMode = FFTMode;
> +
> +	if( m_DemodTimeOut == 0 && m_bFirstTimeLock )
> +	{
> +	    m_DemodTimeOut = Time + DemodTimeOut;
> +	    //break;
> +	}
> +
> +	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
> +
> +	if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin )
> +	{
> +	    break;
> +	}
> +
> +	if( CPAMPValue < CPAMPMin && m_bFirstTimeLock )
> +	{
> +	    // initiate retry
> +	    *pLockStatus = NEVER_LOCK;
> +	    break;
> +	}
> +
> +	if( CPAMPValue < CPAMPMin ) break;
> +
> +	*pLockStatus = DEMOD_LOCK;
> +
> +	if( m_FECTimeOut == 0 && m_bFirstTimeLock )
> +	{
> +	    // Release FEC and Read Solomon Reset
> +	    u8 tmp1;
> +	    u8 tmp2;
> +	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
> +	    readreg(state, R367_TSGENERAL,&tmp2);
> +	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
> +	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
> +
> +	    m_FECTimeOut = Time + FECTimeOut;
> +	}
> +
> +	// Wait for TSP_LOCK, LK, PRF
> +	if( (OFDM_Status & 0x98) != 0x98 )
> +	{
> +	    if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK;
> +	    break;
> +	}
> +
> +	if( m_bFirstTimeLock && m_TSTimeOut == 0)
> +	{
> +	    u8 Guard = (SYR_STAT & 0x03);
> +	    if(Guard < 2)
> +	    {
> +		u8 tmp;
> +		readreg(state, R367_OFDM_SYR_CTL,&tmp);
> +		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
> +		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
> +		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
> +	    } else {
> +		u8 tmp;
> +		readreg(state, R367_OFDM_SYR_CTL,&tmp);
> +		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
> +		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
> +		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
> +	    }
> +
> +	    // apply Sfec workaround if 8K 64QAM CR!=1/2
> +	    if( FFTMode == 1)
> +	    {
> +		u8 tmp[2];
> +		readreg(state, R367_OFDM_TPS_RCVD2,tmp,2);
> +		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
> +		{
> +		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
> +		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
> +		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
> +		}
> +		else
> +		{
> +		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
> +		}
> +	    }
> +
> +	    m_TSTimeOut = Time + TSTimeOut;
> +	}
> +	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
> +	if( (TSStatus & 0x80) != 0x80 )
> +	{
> +		if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK;
> +	    break;
> +	}
> +	*pLockStatus = MPEG_LOCK;
> +	m_bFirstTimeLock = false;
> +	return status;
> +}
> +
> +#endif
> +
> +static int read_status(struct dvb_frontend *fe, fe_status_t *status)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +	*status=0;
> +
> +	switch(state->demod_state) {
> +	case QAMStarted:
> +	{
> +		u8 FEC_Lock;
> +		u8 QAM_Lock;
> +
> +		readreg(state, R367_QAM_FSM_STS, &QAM_Lock);
> +		QAM_Lock &= 0x0F;
> +		if (QAM_Lock >10)
> +			*status|=0x07;
> +		readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock);
> +		if (FEC_Lock&2)
> +			*status|=0x1f;
> +		if (state->m_bFirstTimeLock) {
> +			state->m_bFirstTimeLock = false;
> +			// QAM_AGC_ACCUMRSTSEL to Tracking;
> +			writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL);
> +		}
> +		break;
> +	}
> +	case OFDMStarted:
> +	{
> +		u8 OFDM_Status;
> +		u8 TSStatus;
> +
> +		readreg(state, R367_OFDM_TSSTATUS, &TSStatus);
> +
> +		readreg(state, R367_OFDM_STATUS, &OFDM_Status);
> +		if (OFDM_Status & 0x40)
> +			*status |= FE_HAS_SIGNAL;
> +
> +		if ((OFDM_Status & 0x98) == 0x98)
> +			*status|=0x0f;
> +
> +		if (TSStatus & 0x80)
> +			*status |= 0x1f;
> +		break;
> +	}
> +	default:
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static int read_ber_ter(struct dvb_frontend *fe, u32 *ber)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +	u32 err;
> +	u8 cnth, cntm, cntl;
> +
> +#if 1
> +	readreg(state, R367_OFDM_SFERRCNTH, &cnth);
> +
> +	if (cnth & 0x80) {
> +		*ber = state->ber; 
> +		return 0;
> +	}
> +
> +	readreg(state, R367_OFDM_SFERRCNTM, &cntm);
> +	readreg(state, R367_OFDM_SFERRCNTL, &cntl);
> +
> +	err = ((cnth & 0x7f) << 16) | (cntm << 8) | cntl;
> +	
> +#if 0
> +	{
> +		u64 err64;
> +		err64 = (u64) err;
> +		err64 *= 1000000000ULL;
> +		err64 >>= 21;
> +		err = err64;
> +	}
> +#endif
> +#else
> +	readreg(state, R367_OFDM_ERRCNT1HM, &cnth);
> +
> +#endif
> +	*ber = state->ber = err;
> +	return 0;
> +}
> +
> +static int read_ber_cab(struct dvb_frontend *fe, u32 *ber)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +	u32 err;
> +	u8 cntm, cntl, ctrl;
> +
> +	readreg(state, R367_QAM_BERT_1, &ctrl);
> +	if (!(ctrl & 0x20)) {
> +		readreg(state, R367_QAM_BERT_2, &cntl);
> +		readreg(state, R367_QAM_BERT_3, &cntm);
> +		err = (cntm << 8) | cntl;
> +		//printk("err %04x\n", err);
> +		state->ber = err;
> +		writereg(state, R367_QAM_BERT_1, 0x27);
> +	}
> +	*ber = (u32) state->ber;
> +	return 0;
> +}
> +
> +static int read_ber(struct dvb_frontend *fe, u32 *ber)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +
> +	if (state->demod_state == QAMStarted)
> +		return read_ber_cab(fe, ber);
> +	if (state->demod_state == OFDMStarted)
> +		return read_ber_ter(fe, ber);
> +	*ber = 0;
> +	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 int read_snr(struct dvb_frontend *fe, u16 *snr)
> +{
> + 	struct stv_state *state = fe->demodulator_priv;
> +	s32 snr2 = 0;
> +
> +	switch(state->demod_state) {
> +	case QAMStarted:
> +		QAM_GetSignalToNoise(state, &snr2);
> +		break;
> +	case OFDMStarted:
> +		OFDM_GetSignalToNoise(state, &snr2);
> +		break;
> +	default:
> +		break;
> +	}
> +	*snr = snr2&0xffff;
> +	return 0;
> +}
> +
> +static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
> +{
> +	struct stv_state *state = fe->demodulator_priv;
> +	u8 errl, errm, errh;
> +	u8 val;
> +
> +	switch(state->demod_state) {
> +	case QAMStarted:
> +		readreg(state, R367_QAM_RS_COUNTER_4, &errl);
> +		readreg(state, R367_QAM_RS_COUNTER_5, &errm);
> +		*ucblocks = (errm << 8) | errl;
> +		break;
> +	case OFDMStarted:
> +		readreg(state, R367_OFDM_SFERRCNTH, &val);
> +		if ((val & 0x80) == 0) {
> +			readreg(state, R367_OFDM_ERRCNT1H, &errh);
> +			readreg(state, R367_OFDM_ERRCNT1M, &errl);
> +			readreg(state, R367_OFDM_ERRCNT1L, &errm);
> +			state->ucblocks = (errh <<16) | (errm << 8) | errl;
> +		}
> +		*ucblocks = state->ucblocks;
> +		break;
> +	default:
> +		*ucblocks = 0;
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static int c_get_tune_settings(struct dvb_frontend *fe,
> +				    struct dvb_frontend_tune_settings *sets)
> +{
> +	sets->min_delay_ms=3000;
> +	sets->max_drift=0;
> +	sets->step_size=0;
> +	return 0;
> +}
> +
> +#ifndef USE_API3
> +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;
> +	}
> +}
> +#endif
> +
> +#ifdef USE_API3
> +static void t_release(struct dvb_frontend* fe)
> +{
> +	//struct stv_state *state=fe->demodulator_priv;
> +	//printk("%s\n", __FUNCTION__);
> +	//kfree(state);
> +}
> +
> +static int t_init (struct dvb_frontend *fe)
> +{
> +	struct stv_state *state=fe->demodulator_priv;
> +	if (mutex_trylock(&state->ctlock)==0)
> +		return -EBUSY;
> +	state->omode = OM_DVBT;
> +	return 0;
> +}
> +
> +static int t_sleep(struct dvb_frontend* fe)
> +{
> +	struct stv_state *state=fe->demodulator_priv;
> +	mutex_unlock(&state->ctlock);
> +	return 0;
> +}
> +#endif
> +
> +#if 0
> +static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
> +{
> +	//struct stv_state *state = fe->demodulator_priv;
> +	//printk("%s\n", __FUNCTION__);
> +	return 0;
> +}
> +
> +static enum dvbfe_algo algo(struct dvb_frontend *fe)
> +{
> +	return DVBFE_ALGO_CUSTOM;
> +}
> +#endif
> +
> +#ifdef USE_API3
> +static struct dvb_frontend_ops c_ops = {
> +	.info = {
> +		.name = "STV0367 DVB-C",
> +		.type = FE_QAM,
> +		.frequency_stepsize = 62500,
> +		.frequency_min = 47000000,
> +		.frequency_max = 862000000,
> +		.symbol_rate_min = 870000,
> +		.symbol_rate_max = 11700000,
> +		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
> +			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
> +	},
> +	.release = c_release,
> +	.init = c_init,
> +	.sleep = c_sleep,
> +	.i2c_gate_ctrl = gate_ctrl,
> +
> +	.get_tune_settings = c_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,
> +
> +#if 1
> +	.set_frontend = set_parameters,
> +#else
> +	.get_frontend_algo = algo,
> +	.search = search,
> +#endif
> +};
> +
> +static struct dvb_frontend_ops t_ops = {
> +	.info = {
> +		.name			= "STV0367 DVB-T",
> +		.type			= FE_OFDM,
> +		.frequency_min		= 47125000,
> +		.frequency_max		= 865000000,
> +		.frequency_stepsize	= 166667,
> +		.frequency_tolerance	= 0,
> +		.caps = 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_QAM_16 | FE_CAN_QAM_64 |
> +		FE_CAN_QAM_AUTO |
> +		FE_CAN_TRANSMISSION_MODE_AUTO |
> +		FE_CAN_GUARD_INTERVAL_AUTO |
> +		FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
> +		FE_CAN_MUTE_TS
> +	},
> +	.release = t_release,
> +	.init = t_init,
> +	.sleep = t_sleep,
> +	.i2c_gate_ctrl = gate_ctrl,
> +
> +	.set_frontend = set_parameters,
> +
> +	.read_status = read_status,
> +	.read_ber = read_ber,
> +	.read_signal_strength = read_signal_strength,
> +	.read_snr = read_snr,
> +	.read_ucblocks = read_ucblocks,
> +};
> +
> +#else
> +
> +static struct dvb_frontend_ops common_ops = {
> +	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT },
> +	.info = {
> +		.name = "STV0367 DVB-C DVB-T",
> +		.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,
> +
> +	.get_tune_settings = get_tune_settings,
> +
> +	.set_frontend = set_parameters,
> +
> +	.read_status = read_status,
> +	.read_ber = read_ber,
> +	.read_signal_strength = read_signal_strength,
> +	.read_snr = read_snr,
> +	.read_ucblocks = read_ucblocks,
> +};
> +#endif
> +
> +
> +static void init_state(struct stv_state *state, struct stv0367_cfg *cfg)
> +{
> +	u32 ulENARPTLEVEL = 5;
> +	u32 ulQAMInversion = 2;
> +	state->omode = OM_NONE;
> +	state->adr = cfg->adr;
> +
> +	mutex_init(&state->mutex);
> +	mutex_init(&state->ctlock);
> +
> +#ifdef USE_API3
> +	memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops));
> +	memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops));
> +	state->c_frontend.demodulator_priv = state;
> +	state->t_frontend.demodulator_priv = state;
> +#else
> +	memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops));
> +	state->frontend.demodulator_priv = state;
> +#endif
> +
> +	state->master_clock = 58000000;
> +	state->adc_clock = 58000000;
> +	state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4);
> +	state->qam_inversion = ((ulQAMInversion & 3) << 6 );
> +	state->demod_state   = Off;
> +}
> +
> +
> +struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg,
> +				    struct dvb_frontend **fe_t)
> +{
> +	struct stv_state *state = NULL;
> +
> +	state = kzalloc(sizeof(struct stv_state), GFP_KERNEL);
> +	if (!state)
> +		return NULL;
> +
> +	state->i2c = i2c;
> +	init_state(state, cfg);
> +
> +	if (attach_init(state)<0)
> +		goto error;
> +#ifdef USE_API3
> +	*fe_t = &state->t_frontend;
> +	return &state->c_frontend;
> +#else
> +	return &state->frontend;
> +#endif
> +
> +error:
> +	printk("stv0367: not found\n");
> +	kfree(state);
> +	return NULL;
> +}
> +
> +
> +MODULE_DESCRIPTION("STV0367DD driver");
> +MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
> +MODULE_LICENSE("GPL");
> +
> +EXPORT_SYMBOL(stv0367_attach);
> +
> +
> +
> diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h
> new file mode 100644
> index 0000000..a13df69
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/stv0367dd.h
> @@ -0,0 +1,48 @@
> +/*
> + *  stv0367dd.h: STV0367 DVB-C/T demodulator driver
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#ifndef _STV0367DD_H_
> +#define _STV0367DD_H_
> +
> +#include <linux/types.h>
> +#include <linux/i2c.h>
> +
> +struct stv0367_cfg {
> +	u8  adr;
> +	u32 xtal;
> +	u32 ts_mode;
> +};
> +
> +#if IS_ENABLED(CONFIG_DVB_STV0367DD)
> +extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
> +					   struct stv0367_cfg *cfg,
> +					   struct dvb_frontend **fe_t);
> +#else
> +static inline struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
> +						  struct stv0367_cfg *cfg,
> +						  struct dvb_frontend **fe_t);
> +{
> +	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
> +	return NULL;
> +}
> +#endif
> +
> +#endif
> diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h
> new file mode 100644
> index 0000000..3881f55
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/stv0367dd_regs.h
> @@ -0,0 +1,3442 @@
> +/*
> + *  stv0367dd_regs.h: DVB-C/DVB-T STMicroelectronics STV0367
> + *                    register defintions
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#ifndef _STV0367DD_REGS_H_
> +#define _STV0367DD_REGS_H_
> +
> +/* ID */
> +#define	R367_ID		0xF000
> +#define	F367_IDENTIFICATIONREG		0xF00000FF
> +
> +/* I2CRPT */
> +#define	R367_I2CRPT		0xF001
> +#define	F367_I2CT_ON		0xF0010080
> +#define	F367_ENARPT_LEVEL		0xF0010070
> +#define	F367_SCLT_DELAY		0xF0010008
> +#define	F367_SCLT_NOD		0xF0010004
> +#define	F367_STOP_ENABLE		0xF0010002
> +#define	F367_SDAT_NOD		0xF0010001
> +
> +/* TOPCTRL */
> +#define	R367_TOPCTRL		0xF002
> +#define	F367_STDBY		0xF0020080
> +#define	F367_STDBY_FEC		0xF0020040
> +#define	F367_STDBY_CORE		0xF0020020
> +#define	F367_QAM_COFDM		0xF0020010
> +#define	F367_TS_DIS		0xF0020008
> +#define	F367_DIR_CLK_216		0xF0020004
> +#define	F367_TUNER_BB		0xF0020002
> +#define	F367_DVBT_H		0xF0020001
> +
> +/* IOCFG0 */
> +#define	R367_IOCFG0		0xF003
> +#define	F367_OP0_SD		0xF0030080
> +#define	F367_OP0_VAL		0xF0030040
> +#define	F367_OP0_OD		0xF0030020
> +#define	F367_OP0_INV		0xF0030010
> +#define	F367_OP0_DACVALUE_HI		0xF003000F
> +
> +/* DAC0R */
> +#define	R367_DAC0R		0xF004
> +#define	F367_OP0_DACVALUE_LO		0xF00400FF
> +
> +/* IOCFG1 */
> +#define	R367_IOCFG1		0xF005
> +#define	F367_IP0		0xF0050040
> +#define	F367_OP1_OD		0xF0050020
> +#define	F367_OP1_INV		0xF0050010
> +#define	F367_OP1_DACVALUE_HI		0xF005000F
> +
> +/* DAC1R */
> +#define	R367_DAC1R		0xF006
> +#define	F367_OP1_DACVALUE_LO		0xF00600FF
> +
> +/* IOCFG2 */
> +#define	R367_IOCFG2		0xF007
> +#define	F367_OP2_LOCK_CONF		0xF00700E0
> +#define	F367_OP2_OD		0xF0070010
> +#define	F367_OP2_VAL		0xF0070008
> +#define	F367_OP1_LOCK_CONF		0xF0070007
> +
> +/* SDFR */
> +#define	R367_SDFR		0xF008
> +#define	F367_OP0_FREQ		0xF00800F0
> +#define	F367_OP1_FREQ		0xF008000F
> +
> +/* STATUS */
> +#define	R367_OFDM_STATUS		0xF009
> +#define	F367_TPS_LOCK		0xF0090080
> +#define	F367_SYR_LOCK		0xF0090040
> +#define	F367_AGC_LOCK		0xF0090020
> +#define	F367_PRF		0xF0090010
> +#define	F367_LK		0xF0090008
> +#define	F367_PR		0xF0090007
> +
> +/* AUX_CLK */
> +#define	R367_AUX_CLK		0xF00A
> +#define	F367_AUXFEC_CTL		0xF00A00C0
> +#define	F367_DIS_CKX4		0xF00A0020
> +#define	F367_CKSEL		0xF00A0018
> +#define	F367_CKDIV_PROG		0xF00A0006
> +#define	F367_AUXCLK_ENA		0xF00A0001
> +
> +/* FREESYS1 */
> +#define	R367_FREESYS1		0xF00B
> +#define	F367_FREE_SYS1		0xF00B00FF
> +
> +/* FREESYS2 */
> +#define	R367_FREESYS2		0xF00C
> +#define	F367_FREE_SYS2		0xF00C00FF
> +
> +/* FREESYS3 */
> +#define	R367_FREESYS3		0xF00D
> +#define	F367_FREE_SYS3		0xF00D00FF
> +
> +/* GPIO_CFG */
> +#define	R367_GPIO_CFG		0xF00E
> +#define	F367_GPIO7_NOD		0xF00E0080
> +#define	F367_GPIO7_CFG		0xF00E0040
> +#define	F367_GPIO6_NOD		0xF00E0020
> +#define	F367_GPIO6_CFG		0xF00E0010
> +#define	F367_GPIO5_NOD		0xF00E0008
> +#define	F367_GPIO5_CFG		0xF00E0004
> +#define	F367_GPIO4_NOD		0xF00E0002
> +#define	F367_GPIO4_CFG		0xF00E0001
> +
> +/* GPIO_CMD */
> +#define	R367_GPIO_CMD		0xF00F
> +#define	F367_GPIO7_VAL		0xF00F0008
> +#define	F367_GPIO6_VAL		0xF00F0004
> +#define	F367_GPIO5_VAL		0xF00F0002
> +#define	F367_GPIO4_VAL		0xF00F0001
> +
> +/* AGC2MAX */
> +#define	R367_OFDM_AGC2MAX		0xF010
> +#define	F367_OFDM_AGC2_MAX		0xF01000FF
> +
> +/* AGC2MIN */
> +#define	R367_OFDM_AGC2MIN		0xF011
> +#define	F367_OFDM_AGC2_MIN		0xF01100FF
> +
> +/* AGC1MAX */
> +#define	R367_OFDM_AGC1MAX		0xF012
> +#define	F367_OFDM_AGC1_MAX		0xF01200FF
> +
> +/* AGC1MIN */
> +#define	R367_OFDM_AGC1MIN		0xF013
> +#define	F367_OFDM_AGC1_MIN		0xF01300FF
> +
> +/* AGCR */
> +#define	R367_OFDM_AGCR		0xF014
> +#define	F367_OFDM_RATIO_A		0xF01400E0
> +#define	F367_OFDM_RATIO_B		0xF0140018
> +#define	F367_OFDM_RATIO_C		0xF0140007
> +
> +/* AGC2TH */
> +#define	R367_OFDM_AGC2TH		0xF015
> +#define	F367_OFDM_AGC2_THRES		0xF01500FF
> +
> +/* AGC12C */
> +#define	R367_OFDM_AGC12C		0xF016
> +#define	F367_OFDM_AGC1_IV		0xF0160080
> +#define	F367_OFDM_AGC1_OD		0xF0160040
> +#define	F367_OFDM_AGC1_LOAD		0xF0160020
> +#define	F367_OFDM_AGC2_IV		0xF0160010
> +#define	F367_OFDM_AGC2_OD		0xF0160008
> +#define	F367_OFDM_AGC2_LOAD		0xF0160004
> +#define	F367_OFDM_AGC12_MODE		0xF0160003
> +
> +/* AGCCTRL1 */
> +#define	R367_OFDM_AGCCTRL1		0xF017
> +#define	F367_OFDM_DAGC_ON		0xF0170080
> +#define	F367_OFDM_INVERT_AGC12		0xF0170040
> +#define	F367_OFDM_AGC1_MODE		0xF0170008
> +#define	F367_OFDM_AGC2_MODE		0xF0170007
> +
> +/* AGCCTRL2 */
> +#define	R367_OFDM_AGCCTRL2		0xF018
> +#define	F367_OFDM_FRZ2_CTRL		0xF0180060
> +#define	F367_OFDM_FRZ1_CTRL		0xF0180018
> +#define	F367_OFDM_TIME_CST		0xF0180007
> +
> +/* AGC1VAL1 */
> +#define	R367_OFDM_AGC1VAL1		0xF019
> +#define	F367_OFDM_AGC1_VAL_LO		0xF01900FF
> +
> +/* AGC1VAL2 */
> +#define	R367_OFDM_AGC1VAL2		0xF01A
> +#define	F367_OFDM_AGC1_VAL_HI		0xF01A000F
> +
> +/* AGC2VAL1 */
> +#define	R367_OFDM_AGC2VAL1		0xF01B
> +#define	F367_OFDM_AGC2_VAL_LO		0xF01B00FF
> +
> +/* AGC2VAL2 */
> +#define	R367_OFDM_AGC2VAL2		0xF01C
> +#define	F367_OFDM_AGC2_VAL_HI		0xF01C000F
> +
> +/* AGC2PGA */
> +#define	R367_OFDM_AGC2PGA		0xF01D
> +#define	F367_OFDM_AGC2_PGA		0xF01D00FF
> +
> +/* OVF_RATE1 */
> +#define	R367_OFDM_OVF_RATE1		0xF01E
> +#define	F367_OFDM_OVF_RATE_HI		0xF01E000F
> +
> +/* OVF_RATE2 */
> +#define	R367_OFDM_OVF_RATE2		0xF01F
> +#define	F367_OFDM_OVF_RATE_LO		0xF01F00FF
> +
> +/* GAIN_SRC1 */
> +#define	R367_OFDM_GAIN_SRC1		0xF020
> +#define	F367_OFDM_INV_SPECTR		0xF0200080
> +#define	F367_OFDM_IQ_INVERT		0xF0200040
> +#define	F367_OFDM_INR_BYPASS		0xF0200020
> +#define	F367_OFDM_STATUS_INV_SPECRUM		0xF0200010
> +#define	F367_OFDM_GAIN_SRC_HI		0xF020000F
> +
> +/* GAIN_SRC2 */
> +#define	R367_OFDM_GAIN_SRC2		0xF021
> +#define	F367_OFDM_GAIN_SRC_LO		0xF02100FF
> +
> +/* INC_DEROT1 */
> +#define	R367_OFDM_INC_DEROT1		0xF022
> +#define	F367_OFDM_INC_DEROT_HI		0xF02200FF
> +
> +/* INC_DEROT2 */
> +#define	R367_OFDM_INC_DEROT2		0xF023
> +#define	F367_OFDM_INC_DEROT_LO		0xF02300FF
> +
> +/* PPM_CPAMP_DIR */
> +#define	R367_OFDM_PPM_CPAMP_DIR		0xF024
> +#define	F367_OFDM_PPM_CPAMP_DIRECT		0xF02400FF
> +
> +/* PPM_CPAMP_INV */
> +#define	R367_OFDM_PPM_CPAMP_INV		0xF025
> +#define	F367_OFDM_PPM_CPAMP_INVER		0xF02500FF
> +
> +/* FREESTFE_1 */
> +#define	R367_OFDM_FREESTFE_1		0xF026
> +#define	F367_OFDM_SYMBOL_NUMBER_INC		0xF02600C0
> +#define	F367_OFDM_SEL_LSB		0xF0260004
> +#define	F367_OFDM_AVERAGE_ON		0xF0260002
> +#define	F367_OFDM_DC_ADJ		0xF0260001
> +
> +/* FREESTFE_2 */
> +#define	R367_OFDM_FREESTFE_2		0xF027
> +#define	F367_OFDM_SEL_SRCOUT		0xF02700C0
> +#define	F367_OFDM_SEL_SYRTHR		0xF027001F
> +
> +/* DCOFFSET */
> +#define	R367_OFDM_DCOFFSET		0xF028
> +#define	F367_OFDM_SELECT_I_Q		0xF0280080
> +#define	F367_OFDM_DC_OFFSET		0xF028007F
> +
> +/* EN_PROCESS */
> +#define	R367_OFDM_EN_PROCESS		0xF029
> +#define	F367_OFDM_FREE		0xF02900F0
> +#define	F367_OFDM_ENAB_MANUAL		0xF0290001
> +
> +/* SDI_SMOOTHER */
> +#define	R367_OFDM_SDI_SMOOTHER		0xF02A
> +#define	F367_OFDM_DIS_SMOOTH		0xF02A0080
> +#define	F367_OFDM_SDI_INC_SMOOTHER		0xF02A007F
> +
> +/* FE_LOOP_OPEN */
> +#define	R367_OFDM_FE_LOOP_OPEN		0xF02B
> +#define	F367_OFDM_TRL_LOOP_OP		0xF02B0002
> +#define	F367_OFDM_CRL_LOOP_OP		0xF02B0001
> +
> +/* FREQOFF1 */
> +#define	R367_OFDM_FREQOFF1		0xF02C
> +#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI		0xF02C00FF
> +
> +/* FREQOFF2 */
> +#define	R367_OFDM_FREQOFF2		0xF02D
> +#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI		0xF02D00FF
> +
> +/* FREQOFF3 */
> +#define	R367_OFDM_FREQOFF3		0xF02E
> +#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO		0xF02E00FF
> +
> +/* TIMOFF1 */
> +#define	R367_OFDM_TIMOFF1		0xF02F
> +#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI		0xF02F00FF
> +
> +/* TIMOFF2 */
> +#define	R367_OFDM_TIMOFF2		0xF030
> +#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO		0xF03000FF
> +
> +/* EPQ */
> +#define	R367_OFDM_EPQ		0xF031
> +#define	F367_OFDM_EPQ1		0xF03100FF
> +
> +/* EPQAUTO */
> +#define	R367_OFDM_EPQAUTO		0xF032
> +#define	F367_OFDM_EPQ2		0xF03200FF
> +
> +/* SYR_UPDATE */
> +#define	R367_OFDM_SYR_UPDATE		0xF033
> +#define	F367_OFDM_SYR_PROTV		0xF0330080
> +#define	F367_OFDM_SYR_PROTV_GAIN		0xF0330060
> +#define	F367_OFDM_SYR_FILTER		0xF0330010
> +#define	F367_OFDM_SYR_TRACK_THRES		0xF033000C
> +
> +/* CHPFREE */
> +#define	R367_OFDM_CHPFREE		0xF034
> +#define	F367_OFDM_CHP_FREE		0xF03400FF
> +
> +/* PPM_STATE_MAC */
> +#define	R367_OFDM_PPM_STATE_MAC		0xF035
> +#define	F367_OFDM_PPM_STATE_MACHINE_DECODER		0xF035003F
> +
> +/* INR_THRESHOLD */
> +#define	R367_OFDM_INR_THRESHOLD		0xF036
> +#define	F367_OFDM_INR_THRESH		0xF03600FF
> +
> +/* EPQ_TPS_ID_CELL */
> +#define	R367_OFDM_EPQ_TPS_ID_CELL		0xF037
> +#define	F367_OFDM_ENABLE_LGTH_TO_CF		0xF0370080
> +#define	F367_OFDM_DIS_TPS_RSVD		0xF0370040
> +#define	F367_OFDM_DIS_BCH		0xF0370020
> +#define	F367_OFDM_DIS_ID_CEL		0xF0370010
> +#define	F367_OFDM_TPS_ADJUST_SYM		0xF037000F
> +
> +/* EPQ_CFG */
> +#define	R367_OFDM_EPQ_CFG		0xF038
> +#define	F367_OFDM_EPQ_RANGE		0xF0380002
> +#define	F367_OFDM_EPQ_SOFT		0xF0380001
> +
> +/* EPQ_STATUS */
> +#define	R367_OFDM_EPQ_STATUS		0xF039
> +#define	F367_OFDM_SLOPE_INC		0xF03900FC
> +#define	F367_OFDM_TPS_FIELD		0xF0390003
> +
> +/* AUTORELOCK */
> +#define	R367_OFDM_AUTORELOCK		0xF03A
> +#define	F367_OFDM_BYPASS_BER_TEMPO		0xF03A0080
> +#define	F367_OFDM_BER_TEMPO		0xF03A0070
> +#define	F367_OFDM_BYPASS_COFDM_TEMPO		0xF03A0008
> +#define	F367_OFDM_COFDM_TEMPO		0xF03A0007
> +
> +/* BER_THR_VMSB */
> +#define	R367_OFDM_BER_THR_VMSB		0xF03B
> +#define	F367_OFDM_BER_THRESHOLD_HI		0xF03B00FF
> +
> +/* BER_THR_MSB */
> +#define	R367_OFDM_BER_THR_MSB		0xF03C
> +#define	F367_OFDM_BER_THRESHOLD_MID		0xF03C00FF
> +
> +/* BER_THR_LSB */
> +#define	R367_OFDM_BER_THR_LSB		0xF03D
> +#define	F367_OFDM_BER_THRESHOLD_LO		0xF03D00FF
> +
> +/* CCD */
> +#define	R367_OFDM_CCD		0xF03E
> +#define	F367_OFDM_CCD_DETECTED		0xF03E0080
> +#define	F367_OFDM_CCD_RESET		0xF03E0040
> +#define	F367_OFDM_CCD_THRESHOLD		0xF03E000F
> +
> +/* SPECTR_CFG */
> +#define	R367_OFDM_SPECTR_CFG		0xF03F
> +#define	F367_OFDM_SPECT_CFG		0xF03F0003
> +
> +/* CONSTMU_MSB */
> +#define	R367_OFDM_CONSTMU_MSB		0xF040
> +#define	F367_OFDM_CONSTMU_FREEZE		0xF0400080
> +#define	F367_OFDM_CONSTNU_FORCE_EN		0xF0400040
> +#define	F367_OFDM_CONST_MU_MSB		0xF040003F
> +
> +/* CONSTMU_LSB */
> +#define	R367_OFDM_CONSTMU_LSB		0xF041
> +#define	F367_OFDM_CONST_MU_LSB		0xF04100FF
> +
> +/* CONSTMU_MAX_MSB */
> +#define	R367_OFDM_CONSTMU_MAX_MSB		0xF042
> +#define	F367_OFDM_CONST_MU_MAX_MSB		0xF042003F
> +
> +/* CONSTMU_MAX_LSB */
> +#define	R367_OFDM_CONSTMU_MAX_LSB		0xF043
> +#define	F367_OFDM_CONST_MU_MAX_LSB		0xF04300FF
> +
> +/* ALPHANOISE */
> +#define	R367_OFDM_ALPHANOISE		0xF044
> +#define	F367_OFDM_USE_ALLFILTER		0xF0440080
> +#define	F367_OFDM_INTER_ON		0xF0440040
> +#define	F367_OFDM_ALPHA_NOISE		0xF044001F
> +
> +/* MAXGP_MSB */
> +#define	R367_OFDM_MAXGP_MSB		0xF045
> +#define	F367_OFDM_MUFILTER_LENGTH		0xF04500F0
> +#define	F367_OFDM_MAX_GP_MSB		0xF045000F
> +
> +/* MAXGP_LSB */
> +#define	R367_OFDM_MAXGP_LSB		0xF046
> +#define	F367_OFDM_MAX_GP_LSB		0xF04600FF
> +
> +/* ALPHAMSB */
> +#define	R367_OFDM_ALPHAMSB		0xF047
> +#define	F367_OFDM_CHC_DATARATE		0xF04700C0
> +#define	F367_OFDM_ALPHA_MSB		0xF047003F
> +
> +/* ALPHALSB */
> +#define	R367_OFDM_ALPHALSB		0xF048
> +#define	F367_OFDM_ALPHA_LSB		0xF04800FF
> +
> +/* PILOT_ACCU */
> +#define	R367_OFDM_PILOT_ACCU		0xF049
> +#define	F367_OFDM_USE_SCAT4ADDAPT		0xF0490080
> +#define	F367_OFDM_PILOT_ACC		0xF049001F
> +
> +/* PILOTMU_ACCU */
> +#define	R367_OFDM_PILOTMU_ACCU		0xF04A
> +#define	F367_OFDM_DISCARD_BAD_SP		0xF04A0080
> +#define	F367_OFDM_DISCARD_BAD_CP		0xF04A0040
> +#define	F367_OFDM_PILOT_MU_ACCU		0xF04A001F
> +
> +/* FILT_CHANNEL_EST */
> +#define	R367_OFDM_FILT_CHANNEL_EST		0xF04B
> +#define	F367_OFDM_USE_FILT_PILOT		0xF04B0080
> +#define	F367_OFDM_FILT_CHANNEL		0xF04B007F
> +
> +/* ALPHA_NOPISE_FREQ */
> +#define	R367_OFDM_ALPHA_NOPISE_FREQ		0xF04C
> +#define	F367_OFDM_NOISE_FREQ_FILT		0xF04C0040
> +#define	F367_OFDM_ALPHA_NOISE_FREQ		0xF04C003F
> +
> +/* RATIO_PILOT */
> +#define	R367_OFDM_RATIO_PILOT		0xF04D
> +#define	F367_OFDM_RATIO_MEAN_SP		0xF04D00F0
> +#define	F367_OFDM_RATIO_MEAN_CP		0xF04D000F
> +
> +/* CHC_CTL */
> +#define	R367_OFDM_CHC_CTL		0xF04E
> +#define	F367_OFDM_TRACK_EN		0xF04E0080
> +#define	F367_OFDM_NOISE_NORM_EN		0xF04E0040
> +#define	F367_OFDM_FORCE_CHC_RESET		0xF04E0020
> +#define	F367_OFDM_SHORT_TIME		0xF04E0010
> +#define	F367_OFDM_FORCE_STATE_EN		0xF04E0008
> +#define	F367_OFDM_FORCE_STATE		0xF04E0007
> +
> +/* EPQ_ADJUST */
> +#define	R367_OFDM_EPQ_ADJUST		0xF04F
> +#define	F367_OFDM_ADJUST_SCAT_IND		0xF04F00C0
> +#define	F367_OFDM_ONE_SYMBOL		0xF04F0010
> +#define	F367_OFDM_EPQ_DECAY		0xF04F000E
> +#define	F367_OFDM_HOLD_SLOPE		0xF04F0001
> +
> +/* EPQ_THRES */
> +#define	R367_OFDM_EPQ_THRES		0xF050
> +#define	F367_OFDM_EPQ_THR		0xF05000FF
> +
> +/* OMEGA_CTL */
> +#define	R367_OFDM_OMEGA_CTL		0xF051
> +#define	F367_OFDM_OMEGA_RST		0xF0510080
> +#define	F367_OFDM_FREEZE_OMEGA		0xF0510040
> +#define	F367_OFDM_OMEGA_SEL		0xF051003F
> +
> +/* GP_CTL */
> +#define	R367_OFDM_GP_CTL		0xF052
> +#define	F367_OFDM_CHC_STATE		0xF05200E0
> +#define	F367_OFDM_FREEZE_GP		0xF0520010
> +#define	F367_OFDM_GP_SEL		0xF052000F
> +
> +/* MUMSB */
> +#define	R367_OFDM_MUMSB		0xF053
> +#define	F367_OFDM_MU_MSB		0xF053007F
> +
> +/* MULSB */
> +#define	R367_OFDM_MULSB		0xF054
> +#define	F367_OFDM_MU_LSB		0xF05400FF
> +
> +/* GPMSB */
> +#define	R367_OFDM_GPMSB		0xF055
> +#define	F367_OFDM_CSI_THRESHOLD		0xF05500E0
> +#define	F367_OFDM_GP_MSB		0xF055000F
> +
> +/* GPLSB */
> +#define	R367_OFDM_GPLSB		0xF056
> +#define	F367_OFDM_GP_LSB		0xF05600FF
> +
> +/* OMEGAMSB */
> +#define	R367_OFDM_OMEGAMSB		0xF057
> +#define	F367_OFDM_OMEGA_MSB		0xF057007F
> +
> +/* OMEGALSB */
> +#define	R367_OFDM_OMEGALSB		0xF058
> +#define	F367_OFDM_OMEGA_LSB		0xF05800FF
> +
> +/* SCAT_NB */
> +#define	R367_OFDM_SCAT_NB		0xF059
> +#define	F367_OFDM_CHC_TEST		0xF05900F8
> +#define	F367_OFDM_SCAT_NUMB		0xF0590003
> +
> +/* CHC_DUMMY */
> +#define	R367_OFDM_CHC_DUMMY		0xF05A
> +#define	F367_OFDM_CHC_DUM		0xF05A00FF
> +
> +/* INC_CTL */
> +#define	R367_OFDM_INC_CTL		0xF05B
> +#define	F367_OFDM_INC_BYPASS		0xF05B0080
> +#define	F367_OFDM_INC_NDEPTH		0xF05B000C
> +#define	F367_OFDM_INC_MADEPTH		0xF05B0003
> +
> +/* INCTHRES_COR1 */
> +#define	R367_OFDM_INCTHRES_COR1		0xF05C
> +#define	F367_OFDM_INC_THRES_COR1		0xF05C00FF
> +
> +/* INCTHRES_COR2 */
> +#define	R367_OFDM_INCTHRES_COR2		0xF05D
> +#define	F367_OFDM_INC_THRES_COR2		0xF05D00FF
> +
> +/* INCTHRES_DET1 */
> +#define	R367_OFDM_INCTHRES_DET1		0xF05E
> +#define	F367_OFDM_INC_THRES_DET1		0xF05E003F
> +
> +/* INCTHRES_DET2 */
> +#define	R367_OFDM_INCTHRES_DET2		0xF05F
> +#define	F367_OFDM_INC_THRES_DET2		0xF05F003F
> +
> +/* IIR_CELLNB */
> +#define	R367_OFDM_IIR_CELLNB		0xF060
> +#define	F367_OFDM_NRST_IIR		0xF0600080
> +#define	F367_OFDM_IIR_CELL_NB		0xF0600007
> +
> +/* IIRCX_COEFF1_MSB */
> +#define	R367_OFDM_IIRCX_COEFF1_MSB		0xF061
> +#define	F367_OFDM_IIR_CX_COEFF1_MSB		0xF06100FF
> +
> +/* IIRCX_COEFF1_LSB */
> +#define	R367_OFDM_IIRCX_COEFF1_LSB		0xF062
> +#define	F367_OFDM_IIR_CX_COEFF1_LSB		0xF06200FF
> +
> +/* IIRCX_COEFF2_MSB */
> +#define	R367_OFDM_IIRCX_COEFF2_MSB		0xF063
> +#define	F367_OFDM_IIR_CX_COEFF2_MSB		0xF06300FF
> +
> +/* IIRCX_COEFF2_LSB */
> +#define	R367_OFDM_IIRCX_COEFF2_LSB		0xF064
> +#define	F367_OFDM_IIR_CX_COEFF2_LSB		0xF06400FF
> +
> +/* IIRCX_COEFF3_MSB */
> +#define	R367_OFDM_IIRCX_COEFF3_MSB		0xF065
> +#define	F367_OFDM_IIR_CX_COEFF3_MSB		0xF06500FF
> +
> +/* IIRCX_COEFF3_LSB */
> +#define	R367_OFDM_IIRCX_COEFF3_LSB		0xF066
> +#define	F367_OFDM_IIR_CX_COEFF3_LSB		0xF06600FF
> +
> +/* IIRCX_COEFF4_MSB */
> +#define	R367_OFDM_IIRCX_COEFF4_MSB		0xF067
> +#define	F367_OFDM_IIR_CX_COEFF4_MSB		0xF06700FF
> +
> +/* IIRCX_COEFF4_LSB */
> +#define	R367_OFDM_IIRCX_COEFF4_LSB		0xF068
> +#define	F367_OFDM_IIR_CX_COEFF4_LSB		0xF06800FF
> +
> +/* IIRCX_COEFF5_MSB */
> +#define	R367_OFDM_IIRCX_COEFF5_MSB		0xF069
> +#define	F367_OFDM_IIR_CX_COEFF5_MSB		0xF06900FF
> +
> +/* IIRCX_COEFF5_LSB */
> +#define	R367_OFDM_IIRCX_COEFF5_LSB		0xF06A
> +#define	F367_OFDM_IIR_CX_COEFF5_LSB		0xF06A00FF
> +
> +/* FEPATH_CFG */
> +#define	R367_OFDM_FEPATH_CFG		0xF06B
> +#define	F367_OFDM_DEMUX_SWAP		0xF06B0004
> +#define	F367_OFDM_DIGAGC_SWAP		0xF06B0002
> +#define	F367_OFDM_LONGPATH_IF		0xF06B0001
> +
> +/* PMC1_FUNC */
> +#define	R367_OFDM_PMC1_FUNC		0xF06C
> +#define	F367_OFDM_SOFT_RSTN		0xF06C0080
> +#define	F367_OFDM_PMC1_AVERAGE_TIME		0xF06C0078
> +#define	F367_OFDM_PMC1_WAIT_TIME		0xF06C0006
> +#define	F367_OFDM_PMC1_2N_SEL		0xF06C0001
> +
> +/* PMC1_FOR */
> +#define	R367_OFDM_PMC1_FOR		0xF06D
> +#define	F367_OFDM_PMC1_FORCE		0xF06D0080
> +#define	F367_OFDM_PMC1_FORCE_VALUE		0xF06D007C
> +
> +/* PMC2_FUNC */
> +#define	R367_OFDM_PMC2_FUNC		0xF06E
> +#define	F367_OFDM_PMC2_SOFT_STN		0xF06E0080
> +#define	F367_OFDM_PMC2_ACCU_TIME		0xF06E0070
> +#define	F367_OFDM_PMC2_CMDP_MN		0xF06E0008
> +#define	F367_OFDM_PMC2_SWAP		0xF06E0004
> +
> +/* STATUS_ERR_DA */
> +#define	R367_OFDM_STATUS_ERR_DA		0xF06F
> +#define	F367_OFDM_COM_USEGAINTRK		0xF06F0080
> +#define	F367_OFDM_COM_AGCLOCK		0xF06F0040
> +#define	F367_OFDM_AUT_AGCLOCK		0xF06F0020
> +#define	F367_OFDM_MIN_ERR_X_LSB		0xF06F000F
> +
> +/* DIG_AGC_R */
> +#define	R367_OFDM_DIG_AGC_R		0xF070
> +#define	F367_OFDM_COM_SOFT_RSTN		0xF0700080
> +#define	F367_OFDM_COM_AGC_ON		0xF0700040
> +#define	F367_OFDM_COM_EARLY		0xF0700020
> +#define	F367_OFDM_AUT_SOFT_RESETN		0xF0700010
> +#define	F367_OFDM_AUT_AGC_ON		0xF0700008
> +#define	F367_OFDM_AUT_EARLY		0xF0700004
> +#define	F367_OFDM_AUT_ROT_EN		0xF0700002
> +#define	F367_OFDM_LOCK_SOFT_RESETN		0xF0700001
> +
> +/* COMAGC_TARMSB */
> +#define	R367_OFDM_COMAGC_TARMSB		0xF071
> +#define	F367_OFDM_COM_AGC_TARGET_MSB		0xF07100FF
> +
> +/* COM_AGC_TAR_ENMODE */
> +#define	R367_OFDM_COM_AGC_TAR_ENMODE		0xF072
> +#define	F367_OFDM_COM_AGC_TARGET_LSB		0xF07200F0
> +#define	F367_OFDM_COM_ENMODE		0xF072000F
> +
> +/* COM_AGC_CFG */
> +#define	R367_OFDM_COM_AGC_CFG		0xF073
> +#define	F367_OFDM_COM_N		0xF07300F8
> +#define	F367_OFDM_COM_STABMODE		0xF0730006
> +#define	F367_OFDM_ERR_SEL		0xF0730001
> +
> +/* COM_AGC_GAIN1 */
> +#define	R367_OFDM_COM_AGC_GAIN1		0xF074
> +#define	F367_OFDM_COM_GAIN1ACK		0xF07400F0
> +#define	F367_OFDM_COM_GAIN1TRK		0xF074000F
> +
> +/* AUT_AGC_TARGETMSB */
> +#define	R367_OFDM_AUT_AGC_TARGETMSB		0xF075
> +#define	F367_OFDM_AUT_AGC_TARGET_MSB		0xF07500FF
> +
> +/* LOCK_DET_MSB */
> +#define	R367_OFDM_LOCK_DET_MSB		0xF076
> +#define	F367_OFDM_LOCK_DETECT_MSB		0xF07600FF
> +
> +/* AGCTAR_LOCK_LSBS */
> +#define	R367_OFDM_AGCTAR_LOCK_LSBS		0xF077
> +#define	F367_OFDM_AUT_AGC_TARGET_LSB		0xF07700F0
> +#define	F367_OFDM_LOCK_DETECT_LSB		0xF077000F
> +
> +/* AUT_GAIN_EN */
> +#define	R367_OFDM_AUT_GAIN_EN		0xF078
> +#define	F367_OFDM_AUT_ENMODE		0xF07800F0
> +#define	F367_OFDM_AUT_GAIN2		0xF078000F
> +
> +/* AUT_CFG */
> +#define	R367_OFDM_AUT_CFG		0xF079
> +#define	F367_OFDM_AUT_N		0xF07900F8
> +#define	F367_OFDM_INT_CHOICE		0xF0790006
> +#define	F367_OFDM_INT_LOAD		0xF0790001
> +
> +/* LOCKN */
> +#define	R367_OFDM_LOCKN		0xF07A
> +#define	F367_OFDM_LOCK_N		0xF07A00F8
> +#define	F367_OFDM_SEL_IQNTAR		0xF07A0004
> +#define	F367_OFDM_LOCK_DETECT_CHOICE		0xF07A0003
> +
> +/* INT_X_3 */
> +#define	R367_OFDM_INT_X_3		0xF07B
> +#define	F367_OFDM_INT_X3		0xF07B00FF
> +
> +/* INT_X_2 */
> +#define	R367_OFDM_INT_X_2		0xF07C
> +#define	F367_OFDM_INT_X2		0xF07C00FF
> +
> +/* INT_X_1 */
> +#define	R367_OFDM_INT_X_1		0xF07D
> +#define	F367_OFDM_INT_X1		0xF07D00FF
> +
> +/* INT_X_0 */
> +#define	R367_OFDM_INT_X_0		0xF07E
> +#define	F367_OFDM_INT_X0		0xF07E00FF
> +
> +/* MIN_ERRX_MSB */
> +#define	R367_OFDM_MIN_ERRX_MSB		0xF07F
> +#define	F367_OFDM_MIN_ERR_X_MSB		0xF07F00FF
> +
> +/* COR_CTL */
> +#define	R367_OFDM_COR_CTL		0xF080
> +#define	F367_OFDM_CORE_ACTIVE		0xF0800020
> +#define	F367_OFDM_HOLD		0xF0800010
> +#define	F367_OFDM_CORE_STATE_CTL		0xF080000F
> +
> +/* COR_STAT */
> +#define	R367_OFDM_COR_STAT		0xF081
> +#define	F367_OFDM_SCATT_LOCKED		0xF0810080
> +#define	F367_OFDM_TPS_LOCKED		0xF0810040
> +#define	F367_OFDM_SYR_LOCKED_COR		0xF0810020
> +#define	F367_OFDM_AGC_LOCKED_STAT		0xF0810010
> +#define	F367_OFDM_CORE_STATE_STAT		0xF081000F
> +
> +/* COR_INTEN */
> +#define	R367_OFDM_COR_INTEN		0xF082
> +#define	F367_OFDM_INTEN		0xF0820080
> +#define	F367_OFDM_INTEN_SYR		0xF0820020
> +#define	F367_OFDM_INTEN_FFT		0xF0820010
> +#define	F367_OFDM_INTEN_AGC		0xF0820008
> +#define	F367_OFDM_INTEN_TPS1		0xF0820004
> +#define	F367_OFDM_INTEN_TPS2		0xF0820002
> +#define	F367_OFDM_INTEN_TPS3		0xF0820001
> +
> +/* COR_INTSTAT */
> +#define	R367_OFDM_COR_INTSTAT		0xF083
> +#define	F367_OFDM_INTSTAT_SYR		0xF0830020
> +#define	F367_OFDM_INTSTAT_FFT		0xF0830010
> +#define	F367_OFDM_INTSAT_AGC		0xF0830008
> +#define	F367_OFDM_INTSTAT_TPS1		0xF0830004
> +#define	F367_OFDM_INTSTAT_TPS2		0xF0830002
> +#define	F367_OFDM_INTSTAT_TPS3		0xF0830001
> +
> +/* COR_MODEGUARD */
> +#define	R367_OFDM_COR_MODEGUARD		0xF084
> +#define	F367_OFDM_FORCE		0xF0840010
> +#define	F367_OFDM_MODE		0xF084000C
> +#define	F367_OFDM_GUARD		0xF0840003
> +
> +/* AGC_CTL */
> +#define	R367_OFDM_AGC_CTL		0xF085
> +#define	F367_OFDM_AGC_TIMING_FACTOR		0xF08500E0
> +#define	F367_OFDM_AGC_LAST		0xF0850010
> +#define	F367_OFDM_AGC_GAIN		0xF085000C
> +#define	F367_OFDM_AGC_NEG		0xF0850002
> +#define	F367_OFDM_AGC_SET		0xF0850001
> +
> +/* AGC_MANUAL1 */
> +#define	R367_OFDM_AGC_MANUAL1		0xF086
> +#define	F367_OFDM_AGC_VAL_LO		0xF08600FF
> +
> +/* AGC_MANUAL2 */
> +#define	R367_OFDM_AGC_MANUAL2		0xF087
> +#define	F367_OFDM_AGC_VAL_HI		0xF087000F
> +
> +/* AGC_TARG */
> +#define	R367_OFDM_AGC_TARG		0xF088
> +#define	F367_OFDM_AGC_TARGET		0xF08800FF
> +
> +/* AGC_GAIN1 */
> +#define	R367_OFDM_AGC_GAIN1		0xF089
> +#define	F367_OFDM_AGC_GAIN_LO		0xF08900FF
> +
> +/* AGC_GAIN2 */
> +#define	R367_OFDM_AGC_GAIN2		0xF08A
> +#define	F367_OFDM_AGC_LOCKED_GAIN2		0xF08A0010
> +#define	F367_OFDM_AGC_GAIN_HI		0xF08A000F
> +
> +/* RESERVED_1 */
> +#define	R367_OFDM_RESERVED_1		0xF08B
> +#define	F367_OFDM_RESERVED1		0xF08B00FF
> +
> +/* RESERVED_2 */
> +#define	R367_OFDM_RESERVED_2		0xF08C
> +#define	F367_OFDM_RESERVED2		0xF08C00FF
> +
> +/* RESERVED_3 */
> +#define	R367_OFDM_RESERVED_3		0xF08D
> +#define	F367_OFDM_RESERVED3		0xF08D00FF
> +
> +/* CAS_CTL */
> +#define	R367_OFDM_CAS_CTL		0xF08E
> +#define	F367_OFDM_CCS_ENABLE		0xF08E0080
> +#define	F367_OFDM_ACS_DISABLE		0xF08E0040
> +#define	F367_OFDM_DAGC_DIS		0xF08E0020
> +#define	F367_OFDM_DAGC_GAIN		0xF08E0018
> +#define	F367_OFDM_CCSMU		0xF08E0007
> +
> +/* CAS_FREQ */
> +#define	R367_OFDM_CAS_FREQ		0xF08F
> +#define	F367_OFDM_CCS_FREQ		0xF08F00FF
> +
> +/* CAS_DAGCGAIN */
> +#define	R367_OFDM_CAS_DAGCGAIN		0xF090
> +#define	F367_OFDM_CAS_DAGC_GAIN		0xF09000FF
> +
> +/* SYR_CTL */
> +#define	R367_OFDM_SYR_CTL		0xF091
> +#define	F367_OFDM_SICTH_ENABLE		0xF0910080
> +#define	F367_OFDM_LONG_ECHO		0xF0910078
> +#define	F367_OFDM_AUTO_LE_EN		0xF0910004
> +#define	F367_OFDM_SYR_BYPASS		0xF0910002
> +#define	F367_OFDM_SYR_TR_DIS		0xF0910001
> +
> +/* SYR_STAT */
> +#define	R367_OFDM_SYR_STAT		0xF092
> +#define	F367_OFDM_SYR_LOCKED_STAT		0xF0920010
> +#define	F367_OFDM_SYR_MODE		0xF092000C
> +#define	F367_OFDM_SYR_GUARD		0xF0920003
> +
> +/* SYR_NCO1 */
> +#define	R367_OFDM_SYR_NCO1		0xF093
> +#define	F367_OFDM_SYR_NCO_LO		0xF09300FF
> +
> +/* SYR_NCO2 */
> +#define	R367_OFDM_SYR_NCO2		0xF094
> +#define	F367_OFDM_SYR_NCO_HI		0xF094003F
> +
> +/* SYR_OFFSET1 */
> +#define	R367_OFDM_SYR_OFFSET1		0xF095
> +#define	F367_OFDM_SYR_OFFSET_LO		0xF09500FF
> +
> +/* SYR_OFFSET2 */
> +#define	R367_OFDM_SYR_OFFSET2		0xF096
> +#define	F367_OFDM_SYR_OFFSET_HI		0xF096003F
> +
> +/* FFT_CTL */
> +#define	R367_OFDM_FFT_CTL		0xF097
> +#define	F367_OFDM_SHIFT_FFT_TRIG		0xF0970018
> +#define	F367_OFDM_FFT_TRIGGER		0xF0970004
> +#define	F367_OFDM_FFT_MANUAL		0xF0970002
> +#define	F367_OFDM_IFFT_MODE		0xF0970001
> +
> +/* SCR_CTL */
> +#define	R367_OFDM_SCR_CTL		0xF098
> +#define	F367_OFDM_SYRADJDECAY		0xF0980070
> +#define	F367_OFDM_SCR_CPEDIS		0xF0980002
> +#define	F367_OFDM_SCR_DIS		0xF0980001
> +
> +/* PPM_CTL1 */
> +#define	R367_OFDM_PPM_CTL1		0xF099
> +#define	F367_OFDM_PPM_MAXFREQ		0xF0990030
> +#define	F367_OFDM_PPM_MAXTIM		0xF0990008
> +#define	F367_OFDM_PPM_INVSEL		0xF0990004
> +#define	F367_OFDM_PPM_SCATDIS		0xF0990002
> +#define	F367_OFDM_PPM_BYP		0xF0990001
> +
> +/* TRL_CTL */
> +#define	R367_OFDM_TRL_CTL		0xF09A
> +#define	F367_OFDM_TRL_NOMRATE_LSB		0xF09A0080
> +#define	F367_OFDM_TRL_GAIN_FACTOR		0xF09A0078
> +#define	F367_OFDM_TRL_LOOPGAIN		0xF09A0007
> +
> +/* TRL_NOMRATE1 */
> +#define	R367_OFDM_TRL_NOMRATE1		0xF09B
> +#define	F367_OFDM_TRL_NOMRATE_LO		0xF09B00FF
> +
> +/* TRL_NOMRATE2 */
> +#define	R367_OFDM_TRL_NOMRATE2		0xF09C
> +#define	F367_OFDM_TRL_NOMRATE_HI		0xF09C00FF
> +
> +/* TRL_TIME1 */
> +#define	R367_OFDM_TRL_TIME1		0xF09D
> +#define	F367_OFDM_TRL_TOFFSET_LO		0xF09D00FF
> +
> +/* TRL_TIME2 */
> +#define	R367_OFDM_TRL_TIME2		0xF09E
> +#define	F367_OFDM_TRL_TOFFSET_HI		0xF09E00FF
> +
> +/* CRL_CTL */
> +#define	R367_OFDM_CRL_CTL		0xF09F
> +#define	F367_OFDM_CRL_DIS		0xF09F0080
> +#define	F367_OFDM_CRL_GAIN_FACTOR		0xF09F0078
> +#define	F367_OFDM_CRL_LOOPGAIN		0xF09F0007
> +
> +/* CRL_FREQ1 */
> +#define	R367_OFDM_CRL_FREQ1		0xF0A0
> +#define	F367_OFDM_CRL_FOFFSET_LO		0xF0A000FF
> +
> +/* CRL_FREQ2 */
> +#define	R367_OFDM_CRL_FREQ2		0xF0A1
> +#define	F367_OFDM_CRL_FOFFSET_HI		0xF0A100FF
> +
> +/* CRL_FREQ3 */
> +#define	R367_OFDM_CRL_FREQ3		0xF0A2
> +#define	F367_OFDM_CRL_FOFFSET_VHI		0xF0A200FF
> +
> +/* TPS_SFRAME_CTL */
> +#define	R367_OFDM_TPS_SFRAME_CTL		0xF0A3
> +#define	F367_OFDM_TPS_SFRAME_SYNC		0xF0A30001
> +
> +/* CHC_SNR */
> +#define	R367_OFDM_CHC_SNR		0xF0A4
> +#define	F367_OFDM_CHCSNR		0xF0A400FF
> +
> +/* BDI_CTL */
> +#define	R367_OFDM_BDI_CTL		0xF0A5
> +#define	F367_OFDM_BDI_LPSEL		0xF0A50002
> +#define	F367_OFDM_BDI_SERIAL		0xF0A50001
> +
> +/* DMP_CTL */
> +#define	R367_OFDM_DMP_CTL		0xF0A6
> +#define	F367_OFDM_DMP_SCALING_FACTOR		0xF0A6001E
> +#define	F367_OFDM_DMP_SDDIS		0xF0A60001
> +
> +/* TPS_RCVD1 */
> +#define	R367_OFDM_TPS_RCVD1		0xF0A7
> +#define	F367_OFDM_TPS_CHANGE		0xF0A70040
> +#define	F367_OFDM_BCH_OK		0xF0A70020
> +#define	F367_OFDM_TPS_SYNC		0xF0A70010
> +#define	F367_OFDM_TPS_FRAME		0xF0A70003
> +
> +/* TPS_RCVD2 */
> +#define	R367_OFDM_TPS_RCVD2		0xF0A8
> +#define	F367_OFDM_TPS_HIERMODE		0xF0A80070
> +#define	F367_OFDM_TPS_CONST		0xF0A80003
> +
> +/* TPS_RCVD3 */
> +#define	R367_OFDM_TPS_RCVD3		0xF0A9
> +#define	F367_OFDM_TPS_LPCODE		0xF0A90070
> +#define	F367_OFDM_TPS_HPCODE		0xF0A90007
> +
> +/* TPS_RCVD4 */
> +#define	R367_OFDM_TPS_RCVD4		0xF0AA
> +#define	F367_OFDM_TPS_GUARD		0xF0AA0030
> +#define	F367_OFDM_TPS_MODE		0xF0AA0003
> +
> +/* TPS_ID_CELL1 */
> +#define	R367_OFDM_TPS_ID_CELL1		0xF0AB
> +#define	F367_OFDM_TPS_ID_CELL_LO		0xF0AB00FF
> +
> +/* TPS_ID_CELL2 */
> +#define	R367_OFDM_TPS_ID_CELL2		0xF0AC
> +#define	F367_OFDM_TPS_ID_CELL_HI		0xF0AC00FF
> +
> +/* TPS_RCVD5_SET1 */
> +#define	R367_OFDM_TPS_RCVD5_SET1		0xF0AD
> +#define	F367_OFDM_TPS_NA		0xF0AD00FC
> +#define	F367_OFDM_TPS_SETFRAME		0xF0AD0003
> +
> +/* TPS_SET2 */
> +#define	R367_OFDM_TPS_SET2		0xF0AE
> +#define	F367_OFDM_TPS_SETHIERMODE		0xF0AE0070
> +#define	F367_OFDM_TPS_SETCONST		0xF0AE0003
> +
> +/* TPS_SET3 */
> +#define	R367_OFDM_TPS_SET3		0xF0AF
> +#define	F367_OFDM_TPS_SETLPCODE		0xF0AF0070
> +#define	F367_OFDM_TPS_SETHPCODE		0xF0AF0007
> +
> +/* TPS_CTL */
> +#define	R367_OFDM_TPS_CTL		0xF0B0
> +#define	F367_OFDM_TPS_IMM		0xF0B00004
> +#define	F367_OFDM_TPS_BCHDIS		0xF0B00002
> +#define	F367_OFDM_TPS_UPDDIS		0xF0B00001
> +
> +/* CTL_FFTOSNUM */
> +#define	R367_OFDM_CTL_FFTOSNUM		0xF0B1
> +#define	F367_OFDM_SYMBOL_NUMBER		0xF0B1007F
> +
> +/* TESTSELECT */
> +#define	R367_OFDM_TESTSELECT		0xF0B2
> +#define	F367_OFDM_TEST_SELECT		0xF0B2001F
> +
> +/* MSC_REV */
> +#define	R367_OFDM_MSC_REV		0xF0B3
> +#define	F367_OFDM_REV_NUMBER		0xF0B300FF
> +
> +/* PIR_CTL */
> +#define	R367_OFDM_PIR_CTL		0xF0B4
> +#define	F367_OFDM_FREEZE		0xF0B40001
> +
> +/* SNR_CARRIER1 */
> +#define	R367_OFDM_SNR_CARRIER1		0xF0B5
> +#define	F367_OFDM_SNR_CARRIER_LO		0xF0B500FF
> +
> +/* SNR_CARRIER2 */
> +#define	R367_OFDM_SNR_CARRIER2		0xF0B6
> +#define	F367_OFDM_MEAN		0xF0B600C0
> +#define	F367_OFDM_SNR_CARRIER_HI		0xF0B6001F
> +
> +/* PPM_CPAMP */
> +#define	R367_OFDM_PPM_CPAMP		0xF0B7
> +#define	F367_OFDM_PPM_CPC		0xF0B700FF
> +
> +/* TSM_AP0 */
> +#define	R367_OFDM_TSM_AP0		0xF0B8
> +#define	F367_OFDM_ADDRESS_BYTE_0		0xF0B800FF
> +
> +/* TSM_AP1 */
> +#define	R367_OFDM_TSM_AP1		0xF0B9
> +#define	F367_OFDM_ADDRESS_BYTE_1		0xF0B900FF
> +
> +/* TSM_AP2 */
> +#define	R367_OFDM_TSM_AP2		0xF0BA
> +#define	F367_OFDM_DATA_BYTE_0		0xF0BA00FF
> +
> +/* TSM_AP3 */
> +#define	R367_OFDM_TSM_AP3		0xF0BB
> +#define	F367_OFDM_DATA_BYTE_1		0xF0BB00FF
> +
> +/* TSM_AP4 */
> +#define	R367_OFDM_TSM_AP4		0xF0BC
> +#define	F367_OFDM_DATA_BYTE_2		0xF0BC00FF
> +
> +/* TSM_AP5 */
> +#define	R367_OFDM_TSM_AP5		0xF0BD
> +#define	F367_OFDM_DATA_BYTE_3		0xF0BD00FF
> +
> +/* TSM_AP6 */
> +#define	R367_OFDM_TSM_AP6		0xF0BE
> +#define	F367_OFDM_TSM_AP_6		0xF0BE00FF
> +
> +/* TSM_AP7 */
> +#define	R367_OFDM_TSM_AP7		0xF0BF
> +#define	F367_OFDM_MEM_SELECT_BYTE		0xF0BF00FF
> +
> +/* TSTRES */
> +#define	R367_TSTRES		0xF0C0
> +#define	F367_FRES_DISPLAY		0xF0C00080
> +#define	F367_FRES_FIFO_AD		0xF0C00020
> +#define	F367_FRESRS		0xF0C00010
> +#define	F367_FRESACS		0xF0C00008
> +#define	F367_FRESFEC		0xF0C00004
> +#define	F367_FRES_PRIF		0xF0C00002
> +#define	F367_FRESCORE		0xF0C00001
> +
> +/* ANACTRL */
> +#define	R367_ANACTRL		0xF0C1
> +#define	F367_BYPASS_XTAL		0xF0C10040
> +#define	F367_BYPASS_PLLXN		0xF0C1000C
> +#define	F367_DIS_PAD_OSC		0xF0C10002
> +#define	F367_STDBY_PLLXN		0xF0C10001
> +
> +/* TSTBUS */
> +#define	R367_TSTBUS		0xF0C2
> +#define	F367_TS_BYTE_CLK_INV		0xF0C20080
> +#define	F367_CFG_IP		0xF0C20070
> +#define	F367_CFG_TST		0xF0C2000F
> +
> +/* TSTRATE */
> +#define	R367_TSTRATE		0xF0C6
> +#define	F367_FORCEPHA		0xF0C60080
> +#define	F367_FNEWPHA		0xF0C60010
> +#define	F367_FROT90		0xF0C60008
> +#define	F367_FR		0xF0C60007
> +
> +/* CONSTMODE */
> +#define	R367_OFDM_CONSTMODE		0xF0CB
> +#define	F367_OFDM_TST_PRIF		0xF0CB00E0
> +#define	F367_OFDM_CAR_TYPE		0xF0CB0018
> +#define	F367_OFDM_CONST_MODE		0xF0CB0003
> +
> +/* CONSTCARR1 */
> +#define	R367_OFDM_CONSTCARR1		0xF0CC
> +#define	F367_OFDM_CONST_CARR_LO		0xF0CC00FF
> +
> +/* CONSTCARR2 */
> +#define	R367_OFDM_CONSTCARR2		0xF0CD
> +#define	F367_OFDM_CONST_CARR_HI		0xF0CD001F
> +
> +/* ICONSTEL */
> +#define	R367_OFDM_ICONSTEL		0xF0CE
> +#define	F367_OFDM_PICONSTEL		0xF0CE00FF
> +
> +/* QCONSTEL */
> +#define	R367_OFDM_QCONSTEL		0xF0CF
> +#define	F367_OFDM_PQCONSTEL		0xF0CF00FF
> +
> +/* TSTBISTRES0 */
> +#define	R367_OFDM_TSTBISTRES0		0xF0D0
> +#define	F367_OFDM_BEND_PPM		0xF0D00080
> +#define	F367_OFDM_BBAD_PPM		0xF0D00040
> +#define	F367_OFDM_BEND_FFTW		0xF0D00020
> +#define	F367_OFDM_BBAD_FFTW		0xF0D00010
> +#define	F367_OFDM_BEND_FFT_BUF		0xF0D00008
> +#define	F367_OFDM_BBAD_FFT_BUF		0xF0D00004
> +#define	F367_OFDM_BEND_SYR		0xF0D00002
> +#define	F367_OFDM_BBAD_SYR		0xF0D00001
> +
> +/* TSTBISTRES1 */
> +#define	R367_OFDM_TSTBISTRES1		0xF0D1
> +#define	F367_OFDM_BEND_CHC_CP		0xF0D10080
> +#define	F367_OFDM_BBAD_CHC_CP		0xF0D10040
> +#define	F367_OFDM_BEND_CHCI		0xF0D10020
> +#define	F367_OFDM_BBAD_CHCI		0xF0D10010
> +#define	F367_OFDM_BEND_BDI		0xF0D10008
> +#define	F367_OFDM_BBAD_BDI		0xF0D10004
> +#define	F367_OFDM_BEND_SDI		0xF0D10002
> +#define	F367_OFDM_BBAD_SDI		0xF0D10001
> +
> +/* TSTBISTRES2 */
> +#define	R367_OFDM_TSTBISTRES2		0xF0D2
> +#define	F367_OFDM_BEND_CHC_INC		0xF0D20080
> +#define	F367_OFDM_BBAD_CHC_INC		0xF0D20040
> +#define	F367_OFDM_BEND_CHC_SPP		0xF0D20020
> +#define	F367_OFDM_BBAD_CHC_SPP		0xF0D20010
> +#define	F367_OFDM_BEND_CHC_CPP		0xF0D20008
> +#define	F367_OFDM_BBAD_CHC_CPP		0xF0D20004
> +#define	F367_OFDM_BEND_CHC_SP		0xF0D20002
> +#define	F367_OFDM_BBAD_CHC_SP		0xF0D20001
> +
> +/* TSTBISTRES3 */
> +#define	R367_OFDM_TSTBISTRES3		0xF0D3
> +#define	F367_OFDM_BEND_QAM		0xF0D30080
> +#define	F367_OFDM_BBAD_QAM		0xF0D30040
> +#define	F367_OFDM_BEND_SFEC_VIT		0xF0D30020
> +#define	F367_OFDM_BBAD_SFEC_VIT		0xF0D30010
> +#define	F367_OFDM_BEND_SFEC_DLINE		0xF0D30008
> +#define	F367_OFDM_BBAD_SFEC_DLINE		0xF0D30004
> +#define	F367_OFDM_BEND_SFEC_HW		0xF0D30002
> +#define	F367_OFDM_BBAD_SFEC_HW		0xF0D30001
> +
> +/* RF_AGC1 */
> +#define	R367_RF_AGC1		0xF0D4
> +#define	F367_RF_AGC1_LEVEL_HI		0xF0D400FF
> +
> +/* RF_AGC2 */
> +#define	R367_RF_AGC2		0xF0D5
> +#define	F367_REF_ADGP		0xF0D50080
> +#define	F367_STDBY_ADCGP		0xF0D50020
> +#define	F367_CHANNEL_SEL		0xF0D5001C
> +#define	F367_RF_AGC1_LEVEL_LO		0xF0D50003
> +
> +/* ANADIGCTRL */
> +#define	R367_ANADIGCTRL		0xF0D7
> +#define	F367_SEL_CLKDEM		0xF0D70020
> +#define	F367_EN_BUFFER_Q		0xF0D70010
> +#define	F367_EN_BUFFER_I		0xF0D70008
> +#define	F367_ADC_RIS_EGDE		0xF0D70004
> +#define	F367_SGN_ADC		0xF0D70002
> +#define	F367_SEL_AD12_SYNC		0xF0D70001
> +
> +/* PLLMDIV */
> +#define	R367_PLLMDIV		0xF0D8
> +#define	F367_PLL_MDIV		0xF0D800FF
> +
> +/* PLLNDIV */
> +#define	R367_PLLNDIV		0xF0D9
> +#define	F367_PLL_NDIV		0xF0D900FF
> +
> +/* PLLSETUP */
> +#define	R367_PLLSETUP		0xF0DA
> +#define	F367_PLL_PDIV		0xF0DA0070
> +#define	F367_PLL_KDIV		0xF0DA000F
> +
> +/* DUAL_AD12 */
> +#define	R367_DUAL_AD12		0xF0DB
> +#define	F367_FS20M		0xF0DB0020
> +#define	F367_FS50M		0xF0DB0010
> +#define	F367_INMODE0		0xF0DB0008
> +#define	F367_POFFQ		0xF0DB0004
> +#define	F367_POFFI		0xF0DB0002
> +#define	F367_INMODE1		0xF0DB0001
> +
> +/* TSTBIST */
> +#define	R367_TSTBIST		0xF0DC
> +#define	F367_TST_BYP_CLK		0xF0DC0080
> +#define	F367_TST_GCLKENA_STD		0xF0DC0040
> +#define	F367_TST_GCLKENA		0xF0DC0020
> +#define	F367_TST_MEMBIST		0xF0DC001F
> +
> +/* PAD_COMP_CTRL */
> +#define	R367_PAD_COMP_CTRL		0xF0DD
> +#define	F367_COMPTQ		0xF0DD0010
> +#define	F367_COMPEN		0xF0DD0008
> +#define	F367_FREEZE2		0xF0DD0004
> +#define	F367_SLEEP_INHBT		0xF0DD0002
> +#define	F367_CHIP_SLEEP		0xF0DD0001
> +
> +/* PAD_COMP_WR */
> +#define	R367_PAD_COMP_WR		0xF0DE
> +#define	F367_WR_ASRC		0xF0DE007F
> +
> +/* PAD_COMP_RD */
> +#define	R367_PAD_COMP_RD		0xF0DF
> +#define	F367_COMPOK		0xF0DF0080
> +#define	F367_RD_ASRC		0xF0DF007F
> +
> +/* SYR_TARGET_FFTADJT_MSB */
> +#define	R367_OFDM_SYR_TARGET_FFTADJT_MSB		0xF100
> +#define	F367_OFDM_SYR_START		0xF1000080
> +#define	F367_OFDM_SYR_TARGET_FFTADJ_HI		0xF100000F
> +
> +/* SYR_TARGET_FFTADJT_LSB */
> +#define	R367_OFDM_SYR_TARGET_FFTADJT_LSB		0xF101
> +#define	F367_OFDM_SYR_TARGET_FFTADJ_LO		0xF10100FF
> +
> +/* SYR_TARGET_CHCADJT_MSB */
> +#define	R367_OFDM_SYR_TARGET_CHCADJT_MSB		0xF102
> +#define	F367_OFDM_SYR_TARGET_CHCADJ_HI		0xF102000F
> +
> +/* SYR_TARGET_CHCADJT_LSB */
> +#define	R367_OFDM_SYR_TARGET_CHCADJT_LSB		0xF103
> +#define	F367_OFDM_SYR_TARGET_CHCADJ_LO		0xF10300FF
> +
> +/* SYR_FLAG */
> +#define	R367_OFDM_SYR_FLAG		0xF104
> +#define	F367_OFDM_TRIG_FLG1		0xF1040080
> +#define	F367_OFDM_TRIG_FLG0		0xF1040040
> +#define	F367_OFDM_FFT_FLG1		0xF1040008
> +#define	F367_OFDM_FFT_FLG0		0xF1040004
> +#define	F367_OFDM_CHC_FLG1		0xF1040002
> +#define	F367_OFDM_CHC_FLG0		0xF1040001
> +
> +/* CRL_TARGET1 */
> +#define	R367_OFDM_CRL_TARGET1		0xF105
> +#define	F367_OFDM_CRL_START		0xF1050080
> +#define	F367_OFDM_CRL_TARGET_VHI		0xF105000F
> +
> +/* CRL_TARGET2 */
> +#define	R367_OFDM_CRL_TARGET2		0xF106
> +#define	F367_OFDM_CRL_TARGET_HI		0xF10600FF
> +
> +/* CRL_TARGET3 */
> +#define	R367_OFDM_CRL_TARGET3		0xF107
> +#define	F367_OFDM_CRL_TARGET_LO		0xF10700FF
> +
> +/* CRL_TARGET4 */
> +#define	R367_OFDM_CRL_TARGET4		0xF108
> +#define	F367_OFDM_CRL_TARGET_VLO		0xF10800FF
> +
> +/* CRL_FLAG */
> +#define	R367_OFDM_CRL_FLAG		0xF109
> +#define	F367_OFDM_CRL_FLAG1		0xF1090002
> +#define	F367_OFDM_CRL_FLAG0		0xF1090001
> +
> +/* TRL_TARGET1 */
> +#define	R367_OFDM_TRL_TARGET1		0xF10A
> +#define	F367_OFDM_TRL_TARGET_HI		0xF10A00FF
> +
> +/* TRL_TARGET2 */
> +#define	R367_OFDM_TRL_TARGET2		0xF10B
> +#define	F367_OFDM_TRL_TARGET_LO		0xF10B00FF
> +
> +/* TRL_CHC */
> +#define	R367_OFDM_TRL_CHC		0xF10C
> +#define	F367_OFDM_TRL_START		0xF10C0080
> +#define	F367_OFDM_CHC_START		0xF10C0040
> +#define	F367_OFDM_TRL_FLAG1		0xF10C0002
> +#define	F367_OFDM_TRL_FLAG0		0xF10C0001
> +
> +/* CHC_SNR_TARG */
> +#define	R367_OFDM_CHC_SNR_TARG		0xF10D
> +#define	F367_OFDM_CHC_SNR_TARGET		0xF10D00FF
> +
> +/* TOP_TRACK */
> +#define	R367_OFDM_TOP_TRACK		0xF10E
> +#define	F367_OFDM_TOP_START		0xF10E0080
> +#define	F367_OFDM_FIRST_FLAG		0xF10E0070
> +#define	F367_OFDM_TOP_FLAG1		0xF10E0008
> +#define	F367_OFDM_TOP_FLAG0		0xF10E0004
> +#define	F367_OFDM_CHC_FLAG1		0xF10E0002
> +#define	F367_OFDM_CHC_FLAG0		0xF10E0001
> +
> +/* TRACKER_FREE1 */
> +#define	R367_OFDM_TRACKER_FREE1		0xF10F
> +#define	F367_OFDM_TRACKER_FREE_1		0xF10F00FF
> +
> +/* ERROR_CRL1 */
> +#define	R367_OFDM_ERROR_CRL1		0xF110
> +#define	F367_OFDM_ERROR_CRL_VHI		0xF11000FF
> +
> +/* ERROR_CRL2 */
> +#define	R367_OFDM_ERROR_CRL2		0xF111
> +#define	F367_OFDM_ERROR_CRL_HI		0xF11100FF
> +
> +/* ERROR_CRL3 */
> +#define	R367_OFDM_ERROR_CRL3		0xF112
> +#define	F367_OFDM_ERROR_CRL_LOI		0xF11200FF
> +
> +/* ERROR_CRL4 */
> +#define	R367_OFDM_ERROR_CRL4		0xF113
> +#define	F367_OFDM_ERROR_CRL_VLO		0xF11300FF
> +
> +/* DEC_NCO1 */
> +#define	R367_OFDM_DEC_NCO1		0xF114
> +#define	F367_OFDM_DEC_NCO_VHI		0xF11400FF
> +
> +/* DEC_NCO2 */
> +#define	R367_OFDM_DEC_NCO2		0xF115
> +#define	F367_OFDM_DEC_NCO_HI		0xF11500FF
> +
> +/* DEC_NCO3 */
> +#define	R367_OFDM_DEC_NCO3		0xF116
> +#define	F367_OFDM_DEC_NCO_LO		0xF11600FF
> +
> +/* SNR */
> +#define	R367_OFDM_SNR		0xF117
> +#define	F367_OFDM_SNRATIO		0xF11700FF
> +
> +/* SYR_FFTADJ1 */
> +#define	R367_OFDM_SYR_FFTADJ1		0xF118
> +#define	F367_OFDM_SYR_FFTADJ_HI		0xF11800FF
> +
> +/* SYR_FFTADJ2 */
> +#define	R367_OFDM_SYR_FFTADJ2		0xF119
> +#define	F367_OFDM_SYR_FFTADJ_LO		0xF11900FF
> +
> +/* SYR_CHCADJ1 */
> +#define	R367_OFDM_SYR_CHCADJ1		0xF11A
> +#define	F367_OFDM_SYR_CHCADJ_HI		0xF11A00FF
> +
> +/* SYR_CHCADJ2 */
> +#define	R367_OFDM_SYR_CHCADJ2		0xF11B
> +#define	F367_OFDM_SYR_CHCADJ_LO		0xF11B00FF
> +
> +/* SYR_OFF */
> +#define	R367_OFDM_SYR_OFF		0xF11C
> +#define	F367_OFDM_SYR_OFFSET		0xF11C00FF
> +
> +/* PPM_OFFSET1 */
> +#define	R367_OFDM_PPM_OFFSET1		0xF11D
> +#define	F367_OFDM_PPM_OFFSET_HI		0xF11D00FF
> +
> +/* PPM_OFFSET2 */
> +#define	R367_OFDM_PPM_OFFSET2		0xF11E
> +#define	F367_OFDM_PPM_OFFSET_LO		0xF11E00FF
> +
> +/* TRACKER_FREE2 */
> +#define	R367_OFDM_TRACKER_FREE2		0xF11F
> +#define	F367_OFDM_TRACKER_FREE_2		0xF11F00FF
> +
> +/* DEBG_LT10 */
> +#define	R367_OFDM_DEBG_LT10		0xF120
> +#define	F367_OFDM_DEBUG_LT10		0xF12000FF
> +
> +/* DEBG_LT11 */
> +#define	R367_OFDM_DEBG_LT11		0xF121
> +#define	F367_OFDM_DEBUG_LT11		0xF12100FF
> +
> +/* DEBG_LT12 */
> +#define	R367_OFDM_DEBG_LT12		0xF122
> +#define	F367_OFDM_DEBUG_LT12		0xF12200FF
> +
> +/* DEBG_LT13 */
> +#define	R367_OFDM_DEBG_LT13		0xF123
> +#define	F367_OFDM_DEBUG_LT13		0xF12300FF
> +
> +/* DEBG_LT14 */
> +#define	R367_OFDM_DEBG_LT14		0xF124
> +#define	F367_OFDM_DEBUG_LT14		0xF12400FF
> +
> +/* DEBG_LT15 */
> +#define	R367_OFDM_DEBG_LT15		0xF125
> +#define	F367_OFDM_DEBUG_LT15		0xF12500FF
> +
> +/* DEBG_LT16 */
> +#define	R367_OFDM_DEBG_LT16		0xF126
> +#define	F367_OFDM_DEBUG_LT16		0xF12600FF
> +
> +/* DEBG_LT17 */
> +#define	R367_OFDM_DEBG_LT17		0xF127
> +#define	F367_OFDM_DEBUG_LT17		0xF12700FF
> +
> +/* DEBG_LT18 */
> +#define	R367_OFDM_DEBG_LT18		0xF128
> +#define	F367_OFDM_DEBUG_LT18		0xF12800FF
> +
> +/* DEBG_LT19 */
> +#define	R367_OFDM_DEBG_LT19		0xF129
> +#define	F367_OFDM_DEBUG_LT19		0xF12900FF
> +
> +/* DEBG_LT1A */
> +#define	R367_OFDM_DEBG_LT1A		0xF12A
> +#define	F367_OFDM_DEBUG_LT1A		0xF12A00FF
> +
> +/* DEBG_LT1B */
> +#define	R367_OFDM_DEBG_LT1B		0xF12B
> +#define	F367_OFDM_DEBUG_LT1B		0xF12B00FF
> +
> +/* DEBG_LT1C */
> +#define	R367_OFDM_DEBG_LT1C		0xF12C
> +#define	F367_OFDM_DEBUG_LT1C		0xF12C00FF
> +
> +/* DEBG_LT1D */
> +#define	R367_OFDM_DEBG_LT1D		0xF12D
> +#define	F367_OFDM_DEBUG_LT1D		0xF12D00FF
> +
> +/* DEBG_LT1E */
> +#define	R367_OFDM_DEBG_LT1E		0xF12E
> +#define	F367_OFDM_DEBUG_LT1E		0xF12E00FF
> +
> +/* DEBG_LT1F */
> +#define	R367_OFDM_DEBG_LT1F		0xF12F
> +#define	F367_OFDM_DEBUG_LT1F		0xF12F00FF
> +
> +/* RCCFGH */
> +#define	R367_OFDM_RCCFGH		0xF200
> +#define	F367_OFDM_TSRCFIFO_DVBCI		0xF2000080
> +#define	F367_OFDM_TSRCFIFO_SERIAL		0xF2000040
> +#define	F367_OFDM_TSRCFIFO_DISABLE		0xF2000020
> +#define	F367_OFDM_TSFIFO_2TORC		0xF2000010
> +#define	F367_OFDM_TSRCFIFO_HSGNLOUT		0xF2000008
> +#define	F367_OFDM_TSRCFIFO_ERRMODE		0xF2000006
> +#define	F367_OFDM_RCCFGH_0		0xF2000001
> +
> +/* RCCFGM */
> +#define	R367_OFDM_RCCFGM		0xF201
> +#define	F367_OFDM_TSRCFIFO_MANSPEED		0xF20100C0
> +#define	F367_OFDM_TSRCFIFO_PERMDATA		0xF2010020
> +#define	F367_OFDM_TSRCFIFO_NONEWSGNL		0xF2010010
> +#define	F367_OFDM_RCBYTE_OVERSAMPLING		0xF201000E
> +#define	F367_OFDM_TSRCFIFO_INVDATA		0xF2010001
> +
> +/* RCCFGL */
> +#define	R367_OFDM_RCCFGL		0xF202
> +#define	F367_OFDM_TSRCFIFO_BCLKDEL1CK		0xF20200C0
> +#define	F367_OFDM_RCCFGL_5		0xF2020020
> +#define	F367_OFDM_TSRCFIFO_DUTY50		0xF2020010
> +#define	F367_OFDM_TSRCFIFO_NSGNL2DATA		0xF2020008
> +#define	F367_OFDM_TSRCFIFO_DISSERMUX		0xF2020004
> +#define	F367_OFDM_RCCFGL_1		0xF2020002
> +#define	F367_OFDM_TSRCFIFO_STOPCKDIS		0xF2020001
> +
> +/* RCINSDELH */
> +#define	R367_OFDM_RCINSDELH		0xF203
> +#define	F367_OFDM_TSRCDEL_SYNCBYTE		0xF2030080
> +#define	F367_OFDM_TSRCDEL_XXHEADER		0xF2030040
> +#define	F367_OFDM_TSRCDEL_BBHEADER		0xF2030020
> +#define	F367_OFDM_TSRCDEL_DATAFIELD		0xF2030010
> +#define	F367_OFDM_TSRCINSDEL_ISCR		0xF2030008
> +#define	F367_OFDM_TSRCINSDEL_NPD		0xF2030004
> +#define	F367_OFDM_TSRCINSDEL_RSPARITY		0xF2030002
> +#define	F367_OFDM_TSRCINSDEL_CRC8		0xF2030001
> +
> +/* RCINSDELM */
> +#define	R367_OFDM_RCINSDELM		0xF204
> +#define	F367_OFDM_TSRCINS_BBPADDING		0xF2040080
> +#define	F367_OFDM_TSRCINS_BCHFEC		0xF2040040
> +#define	F367_OFDM_TSRCINS_LDPCFEC		0xF2040020
> +#define	F367_OFDM_TSRCINS_EMODCOD		0xF2040010
> +#define	F367_OFDM_TSRCINS_TOKEN		0xF2040008
> +#define	F367_OFDM_TSRCINS_XXXERR		0xF2040004
> +#define	F367_OFDM_TSRCINS_MATYPE		0xF2040002
> +#define	F367_OFDM_TSRCINS_UPL		0xF2040001
> +
> +/* RCINSDELL */
> +#define	R367_OFDM_RCINSDELL		0xF205
> +#define	F367_OFDM_TSRCINS_DFL		0xF2050080
> +#define	F367_OFDM_TSRCINS_SYNCD		0xF2050040
> +#define	F367_OFDM_TSRCINS_BLOCLEN		0xF2050020
> +#define	F367_OFDM_TSRCINS_SIGPCOUNT		0xF2050010
> +#define	F367_OFDM_TSRCINS_FIFO		0xF2050008
> +#define	F367_OFDM_TSRCINS_REALPACK		0xF2050004
> +#define	F367_OFDM_TSRCINS_TSCONFIG		0xF2050002
> +#define	F367_OFDM_TSRCINS_LATENCY		0xF2050001
> +
> +/* RCSTATUS */
> +#define	R367_OFDM_RCSTATUS		0xF206
> +#define	F367_OFDM_TSRCFIFO_LINEOK		0xF2060080
> +#define	F367_OFDM_TSRCFIFO_ERROR		0xF2060040
> +#define	F367_OFDM_TSRCFIFO_DATA7		0xF2060020
> +#define	F367_OFDM_RCSTATUS_4		0xF2060010
> +#define	F367_OFDM_TSRCFIFO_DEMODSEL		0xF2060008
> +#define	F367_OFDM_TSRC1FIFOSPEED_STORE		0xF2060004
> +#define	F367_OFDM_RCSTATUS_1		0xF2060002
> +#define	F367_OFDM_TSRCSERIAL_IMPOSSIBLE		0xF2060001
> +
> +/* RCSPEED */
> +#define	R367_OFDM_RCSPEED		0xF207
> +#define	F367_OFDM_TSRCFIFO_OUTSPEED		0xF20700FF
> +
> +/* RCDEBUGM */
> +#define	R367_OFDM_RCDEBUGM		0xF208
> +#define	F367_OFDM_SD_UNSYNC		0xF2080080
> +#define	F367_OFDM_ULFLOCK_DETECTM		0xF2080040
> +#define	F367_OFDM_SUL_SELECTOS		0xF2080020
> +#define	F367_OFDM_DILUL_NOSCRBLE		0xF2080010
> +#define	F367_OFDM_NUL_SCRB		0xF2080008
> +#define	F367_OFDM_UL_SCRB		0xF2080004
> +#define	F367_OFDM_SCRAULBAD		0xF2080002
> +#define	F367_OFDM_SCRAUL_UNSYNC		0xF2080001
> +
> +/* RCDEBUGL */
> +#define	R367_OFDM_RCDEBUGL		0xF209
> +#define	F367_OFDM_RS_ERR		0xF2090080
> +#define	F367_OFDM_LLFLOCK_DETECTM		0xF2090040
> +#define	F367_OFDM_NOT_SUL_SELECTOS		0xF2090020
> +#define	F367_OFDM_DILLL_NOSCRBLE		0xF2090010
> +#define	F367_OFDM_NLL_SCRB		0xF2090008
> +#define	F367_OFDM_LL_SCRB		0xF2090004
> +#define	F367_OFDM_SCRALLBAD		0xF2090002
> +#define	F367_OFDM_SCRALL_UNSYNC		0xF2090001
> +
> +/* RCOBSCFG */
> +#define	R367_OFDM_RCOBSCFG		0xF20A
> +#define	F367_OFDM_TSRCFIFO_OBSCFG		0xF20A00FF
> +
> +/* RCOBSM */
> +#define	R367_OFDM_RCOBSM		0xF20B
> +#define	F367_OFDM_TSRCFIFO_OBSDATA_HI		0xF20B00FF
> +
> +/* RCOBSL */
> +#define	R367_OFDM_RCOBSL		0xF20C
> +#define	F367_OFDM_TSRCFIFO_OBSDATA_LO		0xF20C00FF
> +
> +/* RCFECSPY */
> +#define	R367_OFDM_RCFECSPY		0xF210
> +#define	F367_OFDM_SPYRC_ENABLE		0xF2100080
> +#define	F367_OFDM_RCNO_SYNCBYTE		0xF2100040
> +#define	F367_OFDM_RCSERIAL_MODE		0xF2100020
> +#define	F367_OFDM_RCUNUSUAL_PACKET		0xF2100010
> +#define	F367_OFDM_BERRCMETER_DATAMODE		0xF210000C
> +#define	F367_OFDM_BERRCMETER_LMODE		0xF2100002
> +#define	F367_OFDM_BERRCMETER_RESET		0xF2100001
> +
> +/* RCFSPYCFG */
> +#define	R367_OFDM_RCFSPYCFG		0xF211
> +#define	F367_OFDM_FECSPYRC_INPUT		0xF21100C0
> +#define	F367_OFDM_RCRST_ON_ERROR		0xF2110020
> +#define	F367_OFDM_RCONE_SHOT		0xF2110010
> +#define	F367_OFDM_RCI2C_MODE		0xF211000C
> +#define	F367_OFDM_SPYRC_HSTERESIS		0xF2110003
> +
> +/* RCFSPYDATA */
> +#define	R367_OFDM_RCFSPYDATA		0xF212
> +#define	F367_OFDM_SPYRC_STUFFING		0xF2120080
> +#define	F367_OFDM_RCNOERR_PKTJITTER		0xF2120040
> +#define	F367_OFDM_SPYRC_CNULLPKT		0xF2120020
> +#define	F367_OFDM_SPYRC_OUTDATA_MODE		0xF212001F
> +
> +/* RCFSPYOUT */
> +#define	R367_OFDM_RCFSPYOUT		0xF213
> +#define	F367_OFDM_FSPYRC_DIRECT		0xF2130080
> +#define	F367_OFDM_RCFSPYOUT_6		0xF2130040
> +#define	F367_OFDM_SPYRC_OUTDATA_BUS		0xF2130038
> +#define	F367_OFDM_RCSTUFF_MODE		0xF2130007
> +
> +/* RCFSTATUS */
> +#define	R367_OFDM_RCFSTATUS		0xF214
> +#define	F367_OFDM_SPYRC_ENDSIM		0xF2140080
> +#define	F367_OFDM_RCVALID_SIM		0xF2140040
> +#define	F367_OFDM_RCFOUND_SIGNAL		0xF2140020
> +#define	F367_OFDM_RCDSS_SYNCBYTE		0xF2140010
> +#define	F367_OFDM_RCRESULT_STATE		0xF214000F
> +
> +/* RCFGOODPACK */
> +#define	R367_OFDM_RCFGOODPACK		0xF215
> +#define	F367_OFDM_RCGOOD_PACKET		0xF21500FF
> +
> +/* RCFPACKCNT */
> +#define	R367_OFDM_RCFPACKCNT		0xF216
> +#define	F367_OFDM_RCPACKET_COUNTER		0xF21600FF
> +
> +/* RCFSPYMISC */
> +#define	R367_OFDM_RCFSPYMISC		0xF217
> +#define	F367_OFDM_RCLABEL_COUNTER		0xF21700FF
> +
> +/* RCFBERCPT4 */
> +#define	R367_OFDM_RCFBERCPT4		0xF218
> +#define	F367_OFDM_FBERRCMETER_CPT_MMMMSB		0xF21800FF
> +
> +/* RCFBERCPT3 */
> +#define	R367_OFDM_RCFBERCPT3		0xF219
> +#define	F367_OFDM_FBERRCMETER_CPT_MMMSB		0xF21900FF
> +
> +/* RCFBERCPT2 */
> +#define	R367_OFDM_RCFBERCPT2		0xF21A
> +#define	F367_OFDM_FBERRCMETER_CPT_MMSB		0xF21A00FF
> +
> +/* RCFBERCPT1 */
> +#define	R367_OFDM_RCFBERCPT1		0xF21B
> +#define	F367_OFDM_FBERRCMETER_CPT_MSB		0xF21B00FF
> +
> +/* RCFBERCPT0 */
> +#define	R367_OFDM_RCFBERCPT0		0xF21C
> +#define	F367_OFDM_FBERRCMETER_CPT_LSB		0xF21C00FF
> +
> +/* RCFBERERR2 */
> +#define	R367_OFDM_RCFBERERR2		0xF21D
> +#define	F367_OFDM_FBERRCMETER_ERR_HI		0xF21D00FF
> +
> +/* RCFBERERR1 */
> +#define	R367_OFDM_RCFBERERR1		0xF21E
> +#define	F367_OFDM_FBERRCMETER_ERR		0xF21E00FF
> +
> +/* RCFBERERR0 */
> +#define	R367_OFDM_RCFBERERR0		0xF21F
> +#define	F367_OFDM_FBERRCMETER_ERR_LO		0xF21F00FF
> +
> +/* RCFSTATESM */
> +#define	R367_OFDM_RCFSTATESM		0xF220
> +#define	F367_OFDM_RCRSTATE_F		0xF2200080
> +#define	F367_OFDM_RCRSTATE_E		0xF2200040
> +#define	F367_OFDM_RCRSTATE_D		0xF2200020
> +#define	F367_OFDM_RCRSTATE_C		0xF2200010
> +#define	F367_OFDM_RCRSTATE_B		0xF2200008
> +#define	F367_OFDM_RCRSTATE_A		0xF2200004
> +#define	F367_OFDM_RCRSTATE_9		0xF2200002
> +#define	F367_OFDM_RCRSTATE_8		0xF2200001
> +
> +/* RCFSTATESL */
> +#define	R367_OFDM_RCFSTATESL		0xF221
> +#define	F367_OFDM_RCRSTATE_7		0xF2210080
> +#define	F367_OFDM_RCRSTATE_6		0xF2210040
> +#define	F367_OFDM_RCRSTATE_5		0xF2210020
> +#define	F367_OFDM_RCRSTATE_4		0xF2210010
> +#define	F367_OFDM_RCRSTATE_3		0xF2210008
> +#define	F367_OFDM_RCRSTATE_2		0xF2210004
> +#define	F367_OFDM_RCRSTATE_1		0xF2210002
> +#define	F367_OFDM_RCRSTATE_0		0xF2210001
> +
> +/* RCFSPYBER */
> +#define	R367_OFDM_RCFSPYBER		0xF222
> +#define	F367_OFDM_RCFSPYBER_7		0xF2220080
> +#define	F367_OFDM_SPYRCOBS_XORREAD		0xF2220040
> +#define	F367_OFDM_FSPYRCBER_OBSMODE		0xF2220020
> +#define	F367_OFDM_FSPYRCBER_SYNCBYT		0xF2220010
> +#define	F367_OFDM_FSPYRCBER_UNSYNC		0xF2220008
> +#define	F367_OFDM_FSPYRCBER_CTIME		0xF2220007
> +
> +/* RCFSPYDISTM */
> +#define	R367_OFDM_RCFSPYDISTM		0xF223
> +#define	F367_OFDM_RCPKTTIME_DISTANCE_HI		0xF22300FF
> +
> +/* RCFSPYDISTL */
> +#define	R367_OFDM_RCFSPYDISTL		0xF224
> +#define	F367_OFDM_RCPKTTIME_DISTANCE_LO		0xF22400FF
> +
> +/* RCFSPYOBS7 */
> +#define	R367_OFDM_RCFSPYOBS7		0xF228
> +#define	F367_OFDM_RCSPYOBS_SPYFAIL		0xF2280080
> +#define	F367_OFDM_RCSPYOBS_SPYFAIL1		0xF2280040
> +#define	F367_OFDM_RCSPYOBS_ERROR		0xF2280020
> +#define	F367_OFDM_RCSPYOBS_STROUT		0xF2280010
> +#define	F367_OFDM_RCSPYOBS_RESULTSTATE1		0xF228000F
> +
> +/* RCFSPYOBS6 */
> +#define	R367_OFDM_RCFSPYOBS6		0xF229
> +#define	F367_OFDM_RCSPYOBS_RESULTSTATE0		0xF22900F0
> +#define	F367_OFDM_RCSPYOBS_RESULTSTATEM1		0xF229000F
> +
> +/* RCFSPYOBS5 */
> +#define	R367_OFDM_RCFSPYOBS5		0xF22A
> +#define	F367_OFDM_RCSPYOBS_BYTEOFPACKET1		0xF22A00FF
> +
> +/* RCFSPYOBS4 */
> +#define	R367_OFDM_RCFSPYOBS4		0xF22B
> +#define	F367_OFDM_RCSPYOBS_BYTEVALUE1		0xF22B00FF
> +
> +/* RCFSPYOBS3 */
> +#define	R367_OFDM_RCFSPYOBS3		0xF22C
> +#define	F367_OFDM_RCSPYOBS_DATA1		0xF22C00FF
> +
> +/* RCFSPYOBS2 */
> +#define	R367_OFDM_RCFSPYOBS2		0xF22D
> +#define	F367_OFDM_RCSPYOBS_DATA0		0xF22D00FF
> +
> +/* RCFSPYOBS1 */
> +#define	R367_OFDM_RCFSPYOBS1		0xF22E
> +#define	F367_OFDM_RCSPYOBS_DATAM1		0xF22E00FF
> +
> +/* RCFSPYOBS0 */
> +#define	R367_OFDM_RCFSPYOBS0		0xF22F
> +#define	F367_OFDM_RCSPYOBS_DATAM2		0xF22F00FF
> +
> +/* TSGENERAL */
> +#define	R367_TSGENERAL		0xF230
> +#define	F367_TSGENERAL_7		0xF2300080
> +#define	F367_TSGENERAL_6		0xF2300040
> +#define	F367_TSFIFO_BCLK1ALL		0xF2300020
> +#define	F367_TSGENERAL_4		0xF2300010
> +#define	F367_MUXSTREAM_OUTMODE		0xF2300008
> +#define	F367_TSFIFO_PERMPARAL		0xF2300006
> +#define	F367_RST_REEDSOLO		0xF2300001
> +
> +/* RC1SPEED */
> +#define	R367_RC1SPEED		0xF231
> +#define	F367_TSRCFIFO1_OUTSPEED		0xF23100FF
> +
> +/* TSGSTATUS */
> +#define	R367_TSGSTATUS		0xF232
> +#define	F367_TSGSTATUS_7		0xF2320080
> +#define	F367_TSGSTATUS_6		0xF2320040
> +#define	F367_RSMEM_FULL		0xF2320020
> +#define	F367_RS_MULTCALC		0xF2320010
> +#define	F367_RSIN_OVERTIME		0xF2320008
> +#define	F367_TSFIFO3_DEMODSEL		0xF2320004
> +#define	F367_TSFIFO2_DEMODSEL		0xF2320002
> +#define	F367_TSFIFO1_DEMODSEL		0xF2320001
> +
> +
> +/* FECM */
> +#define	R367_OFDM_FECM		0xF233
> +#define	F367_OFDM_DSS_DVB		0xF2330080
> +#define	F367_OFDM_DEMOD_BYPASS		0xF2330040
> +#define	F367_OFDM_CMP_SLOWMODE		0xF2330020
> +#define	F367_OFDM_DSS_SRCH		0xF2330010
> +#define	F367_OFDM_FECM_3		0xF2330008
> +#define	F367_OFDM_DIFF_MODEVIT		0xF2330004
> +#define	F367_OFDM_SYNCVIT		0xF2330002
> +#define	F367_OFDM_I2CSYM		0xF2330001
> +
> +/* VTH12 */
> +#define	R367_OFDM_VTH12		0xF234
> +#define	F367_OFDM_VTH_12		0xF23400FF
> +
> +/* VTH23 */
> +#define	R367_OFDM_VTH23		0xF235
> +#define	F367_OFDM_VTH_23		0xF23500FF
> +
> +/* VTH34 */
> +#define	R367_OFDM_VTH34		0xF236
> +#define	F367_OFDM_VTH_34		0xF23600FF
> +
> +/* VTH56 */
> +#define	R367_OFDM_VTH56		0xF237
> +#define	F367_OFDM_VTH_56		0xF23700FF
> +
> +/* VTH67 */
> +#define	R367_OFDM_VTH67		0xF238
> +#define	F367_OFDM_VTH_67		0xF23800FF
> +
> +/* VTH78 */
> +#define	R367_OFDM_VTH78		0xF239
> +#define	F367_OFDM_VTH_78		0xF23900FF
> +
> +/* VITCURPUN */
> +#define	R367_OFDM_VITCURPUN		0xF23A
> +#define	F367_OFDM_VIT_MAPPING		0xF23A00E0
> +#define	F367_OFDM_VIT_CURPUN		0xF23A001F
> +
> +/* VERROR */
> +#define	R367_OFDM_VERROR		0xF23B
> +#define	F367_OFDM_REGERR_VIT		0xF23B00FF
> +
> +/* PRVIT */
> +#define	R367_OFDM_PRVIT		0xF23C
> +#define	F367_OFDM_PRVIT_7		0xF23C0080
> +#define	F367_OFDM_DIS_VTHLOCK		0xF23C0040
> +#define	F367_OFDM_E7_8VIT		0xF23C0020
> +#define	F367_OFDM_E6_7VIT		0xF23C0010
> +#define	F367_OFDM_E5_6VIT		0xF23C0008
> +#define	F367_OFDM_E3_4VIT		0xF23C0004
> +#define	F367_OFDM_E2_3VIT		0xF23C0002
> +#define	F367_OFDM_E1_2VIT		0xF23C0001
> +
> +/* VAVSRVIT */
> +#define	R367_OFDM_VAVSRVIT		0xF23D
> +#define	F367_OFDM_AMVIT		0xF23D0080
> +#define	F367_OFDM_FROZENVIT		0xF23D0040
> +#define	F367_OFDM_SNVIT		0xF23D0030
> +#define	F367_OFDM_TOVVIT		0xF23D000C
> +#define	F367_OFDM_HYPVIT		0xF23D0003
> +
> +/* VSTATUSVIT */
> +#define	R367_OFDM_VSTATUSVIT		0xF23E
> +#define	F367_OFDM_VITERBI_ON		0xF23E0080
> +#define	F367_OFDM_END_LOOPVIT		0xF23E0040
> +#define	F367_OFDM_VITERBI_DEPRF		0xF23E0020
> +#define	F367_OFDM_PRFVIT		0xF23E0010
> +#define	F367_OFDM_LOCKEDVIT		0xF23E0008
> +#define	F367_OFDM_VITERBI_DELOCK		0xF23E0004
> +#define	F367_OFDM_VIT_DEMODSEL		0xF23E0002
> +#define	F367_OFDM_VITERBI_COMPOUT		0xF23E0001
> +
> +/* VTHINUSE */
> +#define	R367_OFDM_VTHINUSE		0xF23F
> +#define	F367_OFDM_VIT_INUSE		0xF23F00FF
> +
> +/* KDIV12 */
> +#define	R367_OFDM_KDIV12		0xF240
> +#define	F367_OFDM_KDIV12_MANUAL		0xF2400080
> +#define	F367_OFDM_K_DIVIDER_12		0xF240007F
> +
> +/* KDIV23 */
> +#define	R367_OFDM_KDIV23		0xF241
> +#define	F367_OFDM_KDIV23_MANUAL		0xF2410080
> +#define	F367_OFDM_K_DIVIDER_23		0xF241007F
> +
> +/* KDIV34 */
> +#define	R367_OFDM_KDIV34		0xF242
> +#define	F367_OFDM_KDIV34_MANUAL		0xF2420080
> +#define	F367_OFDM_K_DIVIDER_34		0xF242007F
> +
> +/* KDIV56 */
> +#define	R367_OFDM_KDIV56		0xF243
> +#define	F367_OFDM_KDIV56_MANUAL		0xF2430080
> +#define	F367_OFDM_K_DIVIDER_56		0xF243007F
> +
> +/* KDIV67 */
> +#define	R367_OFDM_KDIV67		0xF244
> +#define	F367_OFDM_KDIV67_MANUAL		0xF2440080
> +#define	F367_OFDM_K_DIVIDER_67		0xF244007F
> +
> +/* KDIV78 */
> +#define	R367_OFDM_KDIV78		0xF245
> +#define	F367_OFDM_KDIV78_MANUAL		0xF2450080
> +#define	F367_OFDM_K_DIVIDER_78		0xF245007F
> +
> +/* SIGPOWER */
> +#define	R367_OFDM_SIGPOWER		0xF246
> +#define	F367_OFDM_SIGPOWER_MANUAL		0xF2460080
> +#define	F367_OFDM_SIG_POWER		0xF246007F
> +
> +/* DEMAPVIT */
> +#define	R367_OFDM_DEMAPVIT		0xF247
> +#define	F367_OFDM_DEMAPVIT_7		0xF2470080
> +#define	F367_OFDM_K_DIVIDER_VIT		0xF247007F
> +
> +/* VITSCALE */
> +#define	R367_OFDM_VITSCALE		0xF248
> +#define	F367_OFDM_NVTH_NOSRANGE		0xF2480080
> +#define	F367_OFDM_VERROR_MAXMODE		0xF2480040
> +#define	F367_OFDM_KDIV_MODE		0xF2480030
> +#define	F367_OFDM_NSLOWSN_LOCKED		0xF2480008
> +#define	F367_OFDM_DELOCK_PRFLOSS		0xF2480004
> +#define	F367_OFDM_DIS_RSFLOCK		0xF2480002
> +#define	F367_OFDM_VITSCALE_0		0xF2480001
> +
> +/* FFEC1PRG */
> +#define	R367_OFDM_FFEC1PRG		0xF249
> +#define	F367_OFDM_FDSS_DVB		0xF2490080
> +#define	F367_OFDM_FDSS_SRCH		0xF2490040
> +#define	F367_OFDM_FFECPROG_5		0xF2490020
> +#define	F367_OFDM_FFECPROG_4		0xF2490010
> +#define	F367_OFDM_FFECPROG_3		0xF2490008
> +#define	F367_OFDM_FFECPROG_2		0xF2490004
> +#define	F367_OFDM_FTS1_DISABLE		0xF2490002
> +#define	F367_OFDM_FTS2_DISABLE		0xF2490001
> +
> +/* FVITCURPUN */
> +#define	R367_OFDM_FVITCURPUN		0xF24A
> +#define	F367_OFDM_FVIT_MAPPING		0xF24A00E0
> +#define	F367_OFDM_FVIT_CURPUN		0xF24A001F
> +
> +/* FVERROR */
> +#define	R367_OFDM_FVERROR		0xF24B
> +#define	F367_OFDM_FREGERR_VIT		0xF24B00FF
> +
> +/* FVSTATUSVIT */
> +#define	R367_OFDM_FVSTATUSVIT		0xF24C
> +#define	F367_OFDM_FVITERBI_ON		0xF24C0080
> +#define	F367_OFDM_F1END_LOOPVIT		0xF24C0040
> +#define	F367_OFDM_FVITERBI_DEPRF		0xF24C0020
> +#define	F367_OFDM_FPRFVIT		0xF24C0010
> +#define	F367_OFDM_FLOCKEDVIT		0xF24C0008
> +#define	F367_OFDM_FVITERBI_DELOCK		0xF24C0004
> +#define	F367_OFDM_FVIT_DEMODSEL		0xF24C0002
> +#define	F367_OFDM_FVITERBI_COMPOUT		0xF24C0001
> +
> +/* DEBUG_LT1 */
> +#define	R367_OFDM_DEBUG_LT1		0xF24D
> +#define	F367_OFDM_DBG_LT1		0xF24D00FF
> +
> +/* DEBUG_LT2 */
> +#define	R367_OFDM_DEBUG_LT2		0xF24E
> +#define	F367_OFDM_DBG_LT2		0xF24E00FF
> +
> +/* DEBUG_LT3 */
> +#define	R367_OFDM_DEBUG_LT3		0xF24F
> +#define	F367_OFDM_DBG_LT3		0xF24F00FF
> +
> +	/*	TSTSFMET */
> +#define	R367_OFDM_TSTSFMET			0xF250
> +#define F367_OFDM_TSTSFEC_METRIQUES	0xF25000FF
> +
> +	/*	SELOUT */
> +#define	R367_OFDM_SELOUT				0xF252
> +#define	F367_OFDM_EN_SYNC			0xF2520080
> +#define	F367_OFDM_EN_TBUSDEMAP       0xF2520040 
> +#define	F367_OFDM_SELOUT_5			0xF2520020
> +#define	F367_OFDM_SELOUT_4			0xF2520010
> +#define	F367_OFDM_TSTSYNCHRO_MODE    0xF2520002
> +
> +	/*	TSYNC */
> +#define R367_OFDM_TSYNC				0xF253
> +#define F367_OFDM_CURPUN_INCMODE		0xF2530080
> +#define F367_OFDM_CERR_TSTMODE		0xF2530040
> +#define F367_OFDM_SHIFTSOF_MODE		0xF2530030
> +#define F367_OFDM_SLOWPHA_MODE		0xF2530008
> +#define F367_OFDM_PXX_BYPALL			0xF2530004
> +#define F367_OFDM_FROTA45_FIRST		0xF2530002
> +#define F367_OFDM_TST_BCHERROR		0xF2530001
> +
> +	/*	TSTERR */
> +#define R367_OFDM_TSTERR				0xF254
> +#define F367_OFDM_TST_LONGPKT		0xF2540080
> +#define F367_OFDM_TST_ISSYION		0xF2540040
> +#define F367_OFDM_TST_NPDON			0xF2540020
> +#define F367_OFDM_TSTERR_4			0xF2540010
> +#define F367_OFDM_TRACEBACK_MODE		0xF2540008
> +#define F367_OFDM_TST_RSPARITY		0xF2540004
> +#define F367_OFDM_METRIQUE_MODE		0xF2540003
> +
> +	/*	TSFSYNC */
> +#define R367_OFDM_TSFSYNC			0xF255
> +#define F367_OFDM_EN_SFECSYNC		0xF2550080
> +#define F367_OFDM_EN_SFECDEMAP		0xF2550040
> +#define F367_OFDM_SFCERR_TSTMODE		0xF2550020
> +#define F367_OFDM_SFECPXX_BYPALL		0xF2550010
> +#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F
> +
> +	/*	TSTSFERR */
> +#define R367_OFDM_TSTSFERR			0xF256
> +#define F367_OFDM_TSTSTERR_7			0xF2560080
> +#define F367_OFDM_TSTSTERR_6			0xF2560040
> +#define F367_OFDM_TSTSTERR_5 		0xF2560020
> +#define F367_OFDM_TSTSTERR_4			0xF2560010
> +#define F367_OFDM_SFECTRACEBACK_MODE	0xF2560008
> +#define F367_OFDM_SFEC_NCONVPROG		0xF2560004
> +#define F367_OFDM_SFECMETRIQUE_MODE	0xF2560003
> +
> +	/*	TSTTSSF1 */
> +#define R367_OFDM_TSTTSSF1			0xF258
> +#define F367_OFDM_TSTERSSF			0xF2580080
> +#define F367_OFDM_TSTTSSFEN			0xF2580040
> +#define F367_OFDM_SFEC_OUTMODE		0xF2580030
> +#define F367_OFDM_XLSF_NOFTHRESHOLD  0xF2580008
> +#define F367_OFDM_TSTTSSF_STACKSEL	0xF2580007
> +
> +	/*	TSTTSSF2 */
> +#define R367_OFDM_TSTTSSF2			0xF259
> +#define F367_OFDM_DILSF_DBBHEADER	0xF2590080
> +#define F367_OFDM_TSTTSSF_DISBUG		0xF2590040
> +#define F367_OFDM_TSTTSSF_NOBADSTART	0xF2590020
> +#define F367_OFDM_TSTTSSF_SELECT 	0xF259001F
> +
> +	/*	TSTTSSF3 */
> +#define R367_OFDM_TSTTSSF3			0xF25A
> +#define F367_OFDM_TSTTSSF3_7			0xF25A0080
> +#define F367_OFDM_TSTTSSF3_6			0xF25A0040
> +#define F367_OFDM_TSTTSSF3_5			0xF25A0020
> +#define F367_OFDM_TSTTSSF3_4			0xF25A0010
> +#define F367_OFDM_TSTTSSF3_3			0xF25A0008
> +#define F367_OFDM_TSTTSSF3_2			0xF25A0004
> +#define F367_OFDM_TSTTSSF3_1			0xF25A0002
> +#define F367_OFDM_DISSF_CLKENABLE    0xF25A0001
> +
> +	/*	TSTTS1 */
> +#define R367_OFDM_TSTTS1				0xF25C
> +#define F367_OFDM_TSTERS				0xF25C0080
> +#define F367_OFDM_TSFIFO_DSSSYNCB	0xF25C0040
> +#define F367_OFDM_TSTTS_FSPYBEFRS	0xF25C0020
> +#define F367_OFDM_NFORCE_SYNCBYTE	0xF25C0010
> +#define F367_OFDM_XL_NOFTHRESHOLD	0xF25C0008
> +#define F367_OFDM_TSTTS_FRFORCEPKT	0xF25C0004
> +#define F367_OFDM_DESCR_NOTAUTO		0xF25C0002
> +#define F367_OFDM_TSTTSEN			0xF25C0001
> +		    
> +	/*	TSTTS2 */
> +#define R367_OFDM_TSTTS2				0xF25D
> +#define F367_OFDM_DIL_DBBHEADER		0xF25D0080
> +#define F367_OFDM_TSTTS_NOBADXXX		0xF25D0040
> +#define F367_OFDM_TSFIFO_DELSPEEDUP	0xF25D0020
> +#define F367_OFDM_TSTTS_SELECT		0xF25D001F
> +		    
> +	/*	TSTTS3 */
> +#define R367_OFDM_TSTTS3				0xF25E
> +#define F367_OFDM_TSTTS_NOPKTGAIN	0xF25E0080
> +#define F367_OFDM_TSTTS_NOPKTENE		0xF25E0040
> +#define F367_OFDM_TSTTS_ISOLATION	0xF25E0020
> +#define F367_OFDM_TSTTS_DISBUG		0xF25E0010
> +#define F367_OFDM_TSTTS_NOBADSTART	0xF25E0008
> +#define F367_OFDM_TSTTS_STACKSEL		0xF25E0007
> +
> +	/*	TSTTS4 */
> +#define R367_OFDM_TSTTS4				0xF25F
> +#define F367_OFDM_TSTTS4_7			0xF25F0080
> +#define F367_OFDM_TSTTS4_6			0xF25F0040
> +#define F367_OFDM_TSTTS4_5			0xF25F0020
> +#define F367_OFDM_TSTTS_DISDSTATE	0xF25F0010
> +#define F367_OFDM_TSTTS_FASTNOSYNC	0xF25F0008
> +#define F367_OFDM_EXT_FECSPYIN		0xF25F0004
> +#define F367_OFDM_TSTTS_NODPZERO		0xF25F0002
> +#define F367_OFDM_TSTTS_NODIV3		0xF25F0001
> +
> +	/*	TSTTSRC */
> +#define R367_OFDM_TSTTSRC				0xF26C
> +#define F367_OFDM_TSTTSRC_7				0xF26C0080
> +#define F367_OFDM_TSRCFIFO_DSSSYNCB		0xF26C0040
> +#define F367_OFDM_TSRCFIFO_DPUNACTIVE	0xF26C0020
> +#define F367_OFDM_TSRCFIFO_DELSPEEDUP	0xF26C0010
> +#define F367_OFDM_TSTTSRC_NODIV3			0xF26C0008
> +#define F367_OFDM_TSTTSRC_FRFORCEPKT		0xF26C0004
> +#define F367_OFDM_SAT25_SDDORIGINE		0xF26C0002
> +#define F367_OFDM_TSTTSRC_INACTIVE		0xF26C0001
> +
> +	/*	TSTTSRS */
> +#define R367_OFDM_TSTTSRS				0xF26D
> +#define F367_OFDM_TSTTSRS_7				0xF26D0080
> +#define F367_OFDM_TSTTSRS_6				0xF26D0040
> +#define F367_OFDM_TSTTSRS_5				0xF26D0020
> +#define F367_OFDM_TSTTSRS_4				0xF26D0010
> +#define F367_OFDM_TSTTSRS_3				0xF26D0008
> +#define F367_OFDM_TSTTSRS_2				0xF26D0004
> +#define F367_OFDM_TSTRS_DISRS2			0xF26D0002
> +#define F367_OFDM_TSTRS_DISRS1			0xF26D0001
> +
> +/* TSSTATEM */
> +#define	R367_OFDM_TSSTATEM		0xF270
> +#define	F367_OFDM_TSDIL_ON		0xF2700080
> +#define	F367_OFDM_TSSKIPRS_ON		0xF2700040
> +#define	F367_OFDM_TSRS_ON		0xF2700020
> +#define	F367_OFDM_TSDESCRAMB_ON		0xF2700010
> +#define	F367_OFDM_TSFRAME_MODE		0xF2700008
> +#define	F367_OFDM_TS_DISABLE		0xF2700004
> +#define	F367_OFDM_TSACM_MODE		0xF2700002
> +#define	F367_OFDM_TSOUT_NOSYNC		0xF2700001
> +
> +/* TSSTATEL */
> +#define	R367_OFDM_TSSTATEL		0xF271
> +#define	F367_OFDM_TSNOSYNCBYTE		0xF2710080
> +#define	F367_OFDM_TSPARITY_ON		0xF2710040
> +#define	F367_OFDM_TSSYNCOUTRS_ON		0xF2710020
> +#define	F367_OFDM_TSDVBS2_MODE		0xF2710010
> +#define	F367_OFDM_TSISSYI_ON		0xF2710008
> +#define	F367_OFDM_TSNPD_ON		0xF2710004
> +#define	F367_OFDM_TSCRC8_ON		0xF2710002
> +#define	F367_OFDM_TSDSS_PACKET		0xF2710001
> +
> +/* TSCFGH */
> +#define	R367_OFDM_TSCFGH		0xF272
> +#define	F367_OFDM_TSFIFO_DVBCI		0xF2720080
> +#define	F367_OFDM_TSFIFO_SERIAL		0xF2720040
> +#define	F367_OFDM_TSFIFO_TEIUPDATE		0xF2720020
> +#define	F367_OFDM_TSFIFO_DUTY50		0xF2720010
> +#define	F367_OFDM_TSFIFO_HSGNLOUT		0xF2720008
> +#define	F367_OFDM_TSFIFO_ERRMODE		0xF2720006
> +#define	F367_OFDM_RST_HWARE		0xF2720001
> +
> +/* TSCFGM */
> +#define	R367_OFDM_TSCFGM		0xF273
> +#define	F367_OFDM_TSFIFO_MANSPEED		0xF27300C0
> +#define	F367_OFDM_TSFIFO_PERMDATA		0xF2730020
> +#define	F367_OFDM_TSFIFO_NONEWSGNL		0xF2730010
> +#define	F367_OFDM_TSFIFO_BITSPEED		0xF2730008
> +#define	F367_OFDM_NPD_SPECDVBS2		0xF2730004
> +#define	F367_OFDM_TSFIFO_STOPCKDIS		0xF2730002
> +#define	F367_OFDM_TSFIFO_INVDATA		0xF2730001
> +
> +/* TSCFGL */
> +#define	R367_OFDM_TSCFGL		0xF274
> +#define	F367_OFDM_TSFIFO_BCLKDEL1CK		0xF27400C0
> +#define	F367_OFDM_BCHERROR_MODE		0xF2740030
> +#define	F367_OFDM_TSFIFO_NSGNL2DATA		0xF2740008
> +#define	F367_OFDM_TSFIFO_EMBINDVB		0xF2740004
> +#define	F367_OFDM_TSFIFO_DPUNACT		0xF2740002
> +#define	F367_OFDM_TSFIFO_NPDOFF		0xF2740001
> +
> +/* TSSYNC */
> +#define	R367_OFDM_TSSYNC		0xF275
> +#define	F367_OFDM_TSFIFO_PERMUTE		0xF2750080
> +#define	F367_OFDM_TSFIFO_FISCR3B		0xF2750060
> +#define	F367_OFDM_TSFIFO_SYNCMODE		0xF2750018
> +#define	F367_OFDM_TSFIFO_SYNCSEL		0xF2750007
> +
> +/* TSINSDELH */
> +#define	R367_OFDM_TSINSDELH		0xF276
> +#define	F367_OFDM_TSDEL_SYNCBYTE		0xF2760080
> +#define	F367_OFDM_TSDEL_XXHEADER		0xF2760040
> +#define	F367_OFDM_TSDEL_BBHEADER		0xF2760020
> +#define	F367_OFDM_TSDEL_DATAFIELD		0xF2760010
> +#define	F367_OFDM_TSINSDEL_ISCR		0xF2760008
> +#define	F367_OFDM_TSINSDEL_NPD		0xF2760004
> +#define	F367_OFDM_TSINSDEL_RSPARITY		0xF2760002
> +#define	F367_OFDM_TSINSDEL_CRC8		0xF2760001
> +
> +/* TSINSDELM */
> +#define	R367_OFDM_TSINSDELM		0xF277
> +#define	F367_OFDM_TSINS_BBPADDING		0xF2770080
> +#define	F367_OFDM_TSINS_BCHFEC		0xF2770040
> +#define	F367_OFDM_TSINS_LDPCFEC		0xF2770020
> +#define	F367_OFDM_TSINS_EMODCOD		0xF2770010
> +#define	F367_OFDM_TSINS_TOKEN		0xF2770008
> +#define	F367_OFDM_TSINS_XXXERR		0xF2770004
> +#define	F367_OFDM_TSINS_MATYPE		0xF2770002
> +#define	F367_OFDM_TSINS_UPL		0xF2770001
> +
> +/* TSINSDELL */
> +#define	R367_OFDM_TSINSDELL		0xF278
> +#define	F367_OFDM_TSINS_DFL		0xF2780080
> +#define	F367_OFDM_TSINS_SYNCD		0xF2780040
> +#define	F367_OFDM_TSINS_BLOCLEN		0xF2780020
> +#define	F367_OFDM_TSINS_SIGPCOUNT		0xF2780010
> +#define	F367_OFDM_TSINS_FIFO		0xF2780008
> +#define	F367_OFDM_TSINS_REALPACK		0xF2780004
> +#define	F367_OFDM_TSINS_TSCONFIG		0xF2780002
> +#define	F367_OFDM_TSINS_LATENCY		0xF2780001
> +
> +/* TSDIVN */
> +#define	R367_OFDM_TSDIVN		0xF279
> +#define	F367_OFDM_TSFIFO_LOWSPEED		0xF2790080
> +#define	F367_OFDM_BYTE_OVERSAMPLING		0xF2790070
> +#define	F367_OFDM_TSMANUAL_PACKETNBR		0xF279000F
> +
> +/* TSDIVPM */
> +#define	R367_OFDM_TSDIVPM		0xF27A
> +#define	F367_OFDM_TSMANUAL_P_HI		0xF27A00FF
> +
> +/* TSDIVPL */
> +#define	R367_OFDM_TSDIVPL		0xF27B
> +#define	F367_OFDM_TSMANUAL_P_LO		0xF27B00FF
> +
> +/* TSDIVQM */
> +#define	R367_OFDM_TSDIVQM		0xF27C
> +#define	F367_OFDM_TSMANUAL_Q_HI		0xF27C00FF
> +
> +/* TSDIVQL */
> +#define	R367_OFDM_TSDIVQL		0xF27D
> +#define	F367_OFDM_TSMANUAL_Q_LO		0xF27D00FF
> +
> +/* TSDILSTKM */
> +#define	R367_OFDM_TSDILSTKM		0xF27E
> +#define	F367_OFDM_TSFIFO_DILSTK_HI		0xF27E00FF
> +
> +/* TSDILSTKL */
> +#define	R367_OFDM_TSDILSTKL		0xF27F
> +#define	F367_OFDM_TSFIFO_DILSTK_LO		0xF27F00FF
> +
> +/* TSSPEED */
> +#define	R367_OFDM_TSSPEED		0xF280
> +#define	F367_OFDM_TSFIFO_OUTSPEED		0xF28000FF
> +
> +/* TSSTATUS */
> +#define	R367_OFDM_TSSTATUS		0xF281
> +#define	F367_OFDM_TSFIFO_LINEOK		0xF2810080
> +#define	F367_OFDM_TSFIFO_ERROR		0xF2810040
> +#define	F367_OFDM_TSFIFO_DATA7		0xF2810020
> +#define	F367_OFDM_TSFIFO_NOSYNC		0xF2810010
> +#define	F367_OFDM_ISCR_INITIALIZED		0xF2810008
> +#define	F367_OFDM_ISCR_UPDATED		0xF2810004
> +#define	F367_OFDM_SOFFIFO_UNREGUL		0xF2810002
> +#define	F367_OFDM_DIL_READY		0xF2810001
> +
> +/* TSSTATUS2 */
> +#define	R367_OFDM_TSSTATUS2		0xF282
> +#define	F367_OFDM_TSFIFO_DEMODSEL		0xF2820080
> +#define	F367_OFDM_TSFIFOSPEED_STORE		0xF2820040
> +#define	F367_OFDM_DILXX_RESET		0xF2820020
> +#define	F367_OFDM_TSSERIAL_IMPOSSIBLE		0xF2820010
> +#define	F367_OFDM_TSFIFO_UNDERSPEED		0xF2820008
> +#define	F367_OFDM_BITSPEED_EVENT		0xF2820004
> +#define	F367_OFDM_UL_SCRAMBDETECT		0xF2820002
> +#define	F367_OFDM_ULDTV67_FALSELOCK		0xF2820001
> +
> +/* TSBITRATEM */
> +#define	R367_OFDM_TSBITRATEM		0xF283
> +#define	F367_OFDM_TSFIFO_BITRATE_HI		0xF28300FF
> +
> +/* TSBITRATEL */
> +#define	R367_OFDM_TSBITRATEL		0xF284
> +#define	F367_OFDM_TSFIFO_BITRATE_LO		0xF28400FF
> +
> +/* TSPACKLENM */
> +#define	R367_OFDM_TSPACKLENM		0xF285
> +#define	F367_OFDM_TSFIFO_PACKCPT		0xF28500E0
> +#define	F367_OFDM_DIL_RPLEN_HI		0xF285001F
> +
> +/* TSPACKLENL */
> +#define	R367_OFDM_TSPACKLENL		0xF286
> +#define	F367_OFDM_DIL_RPLEN_LO		0xF28600FF
> +
> +/* TSBLOCLENM */
> +#define	R367_OFDM_TSBLOCLENM		0xF287
> +#define	F367_OFDM_TSFIFO_PFLEN_HI		0xF28700FF
> +
> +/* TSBLOCLENL */
> +#define	R367_OFDM_TSBLOCLENL		0xF288
> +#define	F367_OFDM_TSFIFO_PFLEN_LO		0xF28800FF
> +
> +/* TSDLYH */
> +#define	R367_OFDM_TSDLYH		0xF289
> +#define	F367_OFDM_SOFFIFO_TSTIMEVALID		0xF2890080
> +#define	F367_OFDM_SOFFIFO_SPEEDUP		0xF2890040
> +#define	F367_OFDM_SOFFIFO_STOP		0xF2890020
> +#define	F367_OFDM_SOFFIFO_REGULATED		0xF2890010
> +#define	F367_OFDM_SOFFIFO_REALSBOFF_HI		0xF289000F
> +
> +/* TSDLYM */
> +#define	R367_OFDM_TSDLYM		0xF28A
> +#define	F367_OFDM_SOFFIFO_REALSBOFF_MED		0xF28A00FF
> +
> +/* TSDLYL */
> +#define	R367_OFDM_TSDLYL		0xF28B
> +#define	F367_OFDM_SOFFIFO_REALSBOFF_LO		0xF28B00FF
> +
> +/* TSNPDAV */
> +#define	R367_OFDM_TSNPDAV		0xF28C
> +#define	F367_OFDM_TSNPD_AVERAGE		0xF28C00FF
> +
> +/* TSBUFSTATH */
> +#define	R367_OFDM_TSBUFSTATH		0xF28D
> +#define	F367_OFDM_TSISCR_3BYTES		0xF28D0080
> +#define	F367_OFDM_TSISCR_NEWDATA		0xF28D0040
> +#define	F367_OFDM_TSISCR_BUFSTAT_HI		0xF28D003F
> +
> +/* TSBUFSTATM */
> +#define	R367_OFDM_TSBUFSTATM		0xF28E
> +#define	F367_OFDM_TSISCR_BUFSTAT_MED		0xF28E00FF
> +
> +/* TSBUFSTATL */
> +#define	R367_OFDM_TSBUFSTATL		0xF28F
> +#define	F367_OFDM_TSISCR_BUFSTAT_LO		0xF28F00FF
> +
> +/* TSDEBUGM */
> +#define	R367_OFDM_TSDEBUGM		0xF290
> +#define	F367_OFDM_TSFIFO_ILLPACKET		0xF2900080
> +#define	F367_OFDM_DIL_NOSYNC		0xF2900040
> +#define	F367_OFDM_DIL_ISCR		0xF2900020
> +#define	F367_OFDM_DILOUT_BSYNCB		0xF2900010
> +#define	F367_OFDM_TSFIFO_EMPTYPKT		0xF2900008
> +#define	F367_OFDM_TSFIFO_EMPTYRD		0xF2900004
> +#define	F367_OFDM_SOFFIFO_STOPM		0xF2900002
> +#define	F367_OFDM_SOFFIFO_SPEEDUPM		0xF2900001
> +
> +/* TSDEBUGL */
> +#define	R367_OFDM_TSDEBUGL		0xF291
> +#define	F367_OFDM_TSFIFO_PACKLENFAIL		0xF2910080
> +#define	F367_OFDM_TSFIFO_SYNCBFAIL		0xF2910040
> +#define	F367_OFDM_TSFIFO_VITLIBRE		0xF2910020
> +#define	F367_OFDM_TSFIFO_BOOSTSPEEDM		0xF2910010
> +#define	F367_OFDM_TSFIFO_UNDERSPEEDM		0xF2910008
> +#define	F367_OFDM_TSFIFO_ERROR_EVNT		0xF2910004
> +#define	F367_OFDM_TSFIFO_FULL		0xF2910002
> +#define	F367_OFDM_TSFIFO_OVERFLOWM		0xF2910001
> +
> +/* TSDLYSETH */
> +#define	R367_OFDM_TSDLYSETH		0xF292
> +#define	F367_OFDM_SOFFIFO_OFFSET		0xF29200E0
> +#define	F367_OFDM_SOFFIFO_SYMBOFFSET_HI		0xF292001F
> +
> +/* TSDLYSETM */
> +#define	R367_OFDM_TSDLYSETM		0xF293
> +#define	F367_OFDM_SOFFIFO_SYMBOFFSET_MED		0xF29300FF
> +
> +/* TSDLYSETL */
> +#define	R367_OFDM_TSDLYSETL		0xF294
> +#define	F367_OFDM_SOFFIFO_SYMBOFFSET_LO		0xF29400FF
> +
> +/* TSOBSCFG */
> +#define	R367_OFDM_TSOBSCFG		0xF295
> +#define	F367_OFDM_TSFIFO_OBSCFG		0xF29500FF
> +
> +/* TSOBSM */
> +#define	R367_OFDM_TSOBSM		0xF296
> +#define	F367_OFDM_TSFIFO_OBSDATA_HI		0xF29600FF
> +
> +/* TSOBSL */
> +#define	R367_OFDM_TSOBSL		0xF297
> +#define	F367_OFDM_TSFIFO_OBSDATA_LO		0xF29700FF
> +
> +/* ERRCTRL1 */
> +#define	R367_OFDM_ERRCTRL1		0xF298
> +#define	F367_OFDM_ERR_SRC1		0xF29800F0
> +#define	F367_OFDM_ERRCTRL1_3		0xF2980008
> +#define	F367_OFDM_NUM_EVT1		0xF2980007
> +
> +/* ERRCNT1H */
> +#define	R367_OFDM_ERRCNT1H		0xF299
> +#define	F367_OFDM_ERRCNT1_OLDVALUE		0xF2990080
> +#define	F367_OFDM_ERR_CNT1		0xF299007F
> +
> +/* ERRCNT1M */
> +#define	R367_OFDM_ERRCNT1M		0xF29A
> +#define	F367_OFDM_ERR_CNT1_HI		0xF29A00FF
> +
> +/* ERRCNT1L */
> +#define	R367_OFDM_ERRCNT1L		0xF29B
> +#define	F367_OFDM_ERR_CNT1_LO		0xF29B00FF
> +
> +/* ERRCTRL2 */
> +#define	R367_OFDM_ERRCTRL2		0xF29C
> +#define	F367_OFDM_ERR_SRC2		0xF29C00F0
> +#define	F367_OFDM_ERRCTRL2_3		0xF29C0008
> +#define	F367_OFDM_NUM_EVT2		0xF29C0007
> +
> +/* ERRCNT2H */
> +#define	R367_OFDM_ERRCNT2H		0xF29D
> +#define	F367_OFDM_ERRCNT2_OLDVALUE		0xF29D0080
> +#define	F367_OFDM_ERR_CNT2_HI		0xF29D007F
> +
> +/* ERRCNT2M */
> +#define	R367_OFDM_ERRCNT2M		0xF29E
> +#define	F367_OFDM_ERR_CNT2_MED		0xF29E00FF
> +
> +/* ERRCNT2L */
> +#define	R367_OFDM_ERRCNT2L		0xF29F
> +#define	F367_OFDM_ERR_CNT2_LO		0xF29F00FF
> +
> +/* FECSPY */
> +#define	R367_OFDM_FECSPY		0xF2A0
> +#define	F367_OFDM_SPY_ENABLE		0xF2A00080
> +#define	F367_OFDM_NO_SYNCBYTE		0xF2A00040
> +#define	F367_OFDM_SERIAL_MODE		0xF2A00020
> +#define	F367_OFDM_UNUSUAL_PACKET		0xF2A00010
> +#define	F367_OFDM_BERMETER_DATAMODE		0xF2A0000C
> +#define	F367_OFDM_BERMETER_LMODE		0xF2A00002
> +#define	F367_OFDM_BERMETER_RESET		0xF2A00001
> +
> +/* FSPYCFG */
> +#define	R367_OFDM_FSPYCFG		0xF2A1
> +#define	F367_OFDM_FECSPY_INPUT		0xF2A100C0
> +#define	F367_OFDM_RST_ON_ERROR		0xF2A10020
> +#define	F367_OFDM_ONE_SHOT		0xF2A10010
> +#define	F367_OFDM_I2C_MOD		0xF2A1000C
> +#define	F367_OFDM_SPY_HYSTERESIS		0xF2A10003
> +
> +/* FSPYDATA */
> +#define	R367_OFDM_FSPYDATA		0xF2A2
> +#define	F367_OFDM_SPY_STUFFING		0xF2A20080
> +#define	F367_OFDM_NOERROR_PKTJITTER		0xF2A20040
> +#define	F367_OFDM_SPY_CNULLPKT		0xF2A20020
> +#define	F367_OFDM_SPY_OUTDATA_MODE		0xF2A2001F
> +
> +/* FSPYOUT */
> +#define	R367_OFDM_FSPYOUT		0xF2A3
> +#define	F367_OFDM_FSPY_DIRECT		0xF2A30080
> +#define	F367_OFDM_FSPYOUT_6		0xF2A30040
> +#define	F367_OFDM_SPY_OUTDATA_BUS		0xF2A30038
> +#define	F367_OFDM_STUFF_MODE		0xF2A30007
> +
> +/* FSTATUS */
> +#define	R367_OFDM_FSTATUS		0xF2A4
> +#define	F367_OFDM_SPY_ENDSIM		0xF2A40080
> +#define	F367_OFDM_VALID_SIM		0xF2A40040
> +#define	F367_OFDM_FOUND_SIGNAL		0xF2A40020
> +#define	F367_OFDM_DSS_SYNCBYTE		0xF2A40010
> +#define	F367_OFDM_RESULT_STATE		0xF2A4000F
> +
> +/* FGOODPACK */
> +#define	R367_OFDM_FGOODPACK		0xF2A5
> +#define	F367_OFDM_FGOOD_PACKET		0xF2A500FF
> +
> +/* FPACKCNT */
> +#define	R367_OFDM_FPACKCNT		0xF2A6
> +#define	F367_OFDM_FPACKET_COUNTER		0xF2A600FF
> +
> +/* FSPYMISC */
> +#define	R367_OFDM_FSPYMISC		0xF2A7
> +#define	F367_OFDM_FLABEL_COUNTER		0xF2A700FF
> +
> +/* FBERCPT4 */
> +#define	R367_OFDM_FBERCPT4		0xF2A8
> +#define	F367_OFDM_FBERMETER_CPT5		0xF2A800FF
> +
> +/* FBERCPT3 */
> +#define	R367_OFDM_FBERCPT3		0xF2A9
> +#define	F367_OFDM_FBERMETER_CPT4		0xF2A900FF
> +
> +/* FBERCPT2 */
> +#define	R367_OFDM_FBERCPT2		0xF2AA
> +#define	F367_OFDM_FBERMETER_CPT3		0xF2AA00FF
> +
> +/* FBERCPT1 */
> +#define	R367_OFDM_FBERCPT1		0xF2AB
> +#define	F367_OFDM_FBERMETER_CPT2		0xF2AB00FF
> +
> +/* FBERCPT0 */
> +#define	R367_OFDM_FBERCPT0		0xF2AC
> +#define	F367_OFDM_FBERMETER_CPT1		0xF2AC00FF
> +
> +/* FBERERR2 */
> +#define	R367_OFDM_FBERERR2		0xF2AD
> +#define	F367_OFDM_FBERMETER_ERR_HI		0xF2AD00FF
> +
> +/* FBERERR1 */
> +#define	R367_OFDM_FBERERR1		0xF2AE
> +#define	F367_OFDM_FBERMETER_ERR_MED		0xF2AE00FF
> +
> +/* FBERERR0 */
> +#define	R367_OFDM_FBERERR0		0xF2AF
> +#define	F367_OFDM_FBERMETER_ERR_LO		0xF2AF00FF
> +
> +/* FSTATESM */
> +#define	R367_OFDM_FSTATESM		0xF2B0
> +#define	F367_OFDM_RSTATE_F		0xF2B00080
> +#define	F367_OFDM_RSTATE_E		0xF2B00040
> +#define	F367_OFDM_RSTATE_D		0xF2B00020
> +#define	F367_OFDM_RSTATE_C		0xF2B00010
> +#define	F367_OFDM_RSTATE_B		0xF2B00008
> +#define	F367_OFDM_RSTATE_A		0xF2B00004
> +#define	F367_OFDM_RSTATE_9		0xF2B00002
> +#define	F367_OFDM_RSTATE_8		0xF2B00001
> +
> +/* FSTATESL */
> +#define	R367_OFDM_FSTATESL		0xF2B1
> +#define	F367_OFDM_RSTATE_7		0xF2B10080
> +#define	F367_OFDM_RSTATE_6		0xF2B10040
> +#define	F367_OFDM_RSTATE_5		0xF2B10020
> +#define	F367_OFDM_RSTATE_4		0xF2B10010
> +#define	F367_OFDM_RSTATE_3		0xF2B10008
> +#define	F367_OFDM_RSTATE_2		0xF2B10004
> +#define	F367_OFDM_RSTATE_1		0xF2B10002
> +#define	F367_OFDM_RSTATE_0		0xF2B10001
> +
> +/* FSPYBER */
> +#define	R367_OFDM_FSPYBER		0xF2B2
> +#define	F367_OFDM_FSPYBER_7		0xF2B20080
> +#define	F367_OFDM_FSPYOBS_XORREAD		0xF2B20040
> +#define	F367_OFDM_FSPYBER_OBSMODE		0xF2B20020
> +#define	F367_OFDM_FSPYBER_SYNCBYTE		0xF2B20010
> +#define	F367_OFDM_FSPYBER_UNSYNC		0xF2B20008
> +#define	F367_OFDM_FSPYBER_CTIME		0xF2B20007
> +
> +/* FSPYDISTM */
> +#define	R367_OFDM_FSPYDISTM		0xF2B3
> +#define	F367_OFDM_PKTTIME_DISTANCE_HI		0xF2B300FF
> +
> +/* FSPYDISTL */
> +#define	R367_OFDM_FSPYDISTL		0xF2B4
> +#define	F367_OFDM_PKTTIME_DISTANCE_LO		0xF2B400FF
> +
> +/* FSPYOBS7 */
> +#define	R367_OFDM_FSPYOBS7		0xF2B8
> +#define	F367_OFDM_FSPYOBS_SPYFAIL		0xF2B80080
> +#define	F367_OFDM_FSPYOBS_SPYFAIL1		0xF2B80040
> +#define	F367_OFDM_FSPYOBS_ERROR		0xF2B80020
> +#define	F367_OFDM_FSPYOBS_STROUT		0xF2B80010
> +#define	F367_OFDM_FSPYOBS_RESULTSTATE1		0xF2B8000F
> +
> +/* FSPYOBS6 */
> +#define	R367_OFDM_FSPYOBS6		0xF2B9
> +#define	F367_OFDM_FSPYOBS_RESULTSTATE0		0xF2B900F0
> +#define	F367_OFDM_FSPYOBS_RESULTSTATEM1		0xF2B9000F
> +
> +/* FSPYOBS5 */
> +#define	R367_OFDM_FSPYOBS5		0xF2BA
> +#define	F367_OFDM_FSPYOBS_BYTEOFPACKET1		0xF2BA00FF
> +
> +/* FSPYOBS4 */
> +#define	R367_OFDM_FSPYOBS4		0xF2BB
> +#define	F367_OFDM_FSPYOBS_BYTEVALUE1		0xF2BB00FF
> +
> +/* FSPYOBS3 */
> +#define	R367_OFDM_FSPYOBS3		0xF2BC
> +#define	F367_OFDM_FSPYOBS_DATA1		0xF2BC00FF
> +
> +/* FSPYOBS2 */
> +#define	R367_OFDM_FSPYOBS2		0xF2BD
> +#define	F367_OFDM_FSPYOBS_DATA0		0xF2BD00FF
> +
> +/* FSPYOBS1 */
> +#define	R367_OFDM_FSPYOBS1		0xF2BE
> +#define	F367_OFDM_FSPYOBS_DATAM1		0xF2BE00FF
> +
> +/* FSPYOBS0 */
> +#define	R367_OFDM_FSPYOBS0		0xF2BF
> +#define	F367_OFDM_FSPYOBS_DATAM2		0xF2BF00FF
> +
> +/* SFDEMAP */
> +#define	R367_OFDM_SFDEMAP		0xF2C0
> +#define	F367_OFDM_SFDEMAP_7		0xF2C00080
> +#define	F367_OFDM_SFEC_K_DIVIDER_VIT		0xF2C0007F
> +
> +/* SFERROR */
> +#define	R367_OFDM_SFERROR		0xF2C1
> +#define	F367_OFDM_SFEC_REGERR_VIT		0xF2C100FF
> +
> +/* SFAVSR */
> +#define	R367_OFDM_SFAVSR		0xF2C2
> +#define	F367_OFDM_SFEC_SUMERRORS		0xF2C20080
> +#define	F367_OFDM_SERROR_MAXMODE		0xF2C20040
> +#define	F367_OFDM_SN_SFEC		0xF2C20030
> +#define	F367_OFDM_KDIV_MODE_SFEC		0xF2C2000C
> +#define	F367_OFDM_SFAVSR_1		0xF2C20002
> +#define	F367_OFDM_SFAVSR_0		0xF2C20001
> +
> +/* SFECSTATUS */
> +#define	R367_OFDM_SFECSTATUS		0xF2C3
> +#define	F367_OFDM_SFEC_ON		0xF2C30080
> +#define	F367_OFDM_SFSTATUS_6		0xF2C30040
> +#define	F367_OFDM_SFSTATUS_5		0xF2C30020
> +#define	F367_OFDM_SFSTATUS_4		0xF2C30010
> +#define	F367_OFDM_LOCKEDSFEC		0xF2C30008
> +#define	F367_OFDM_SFEC_DELOCK		0xF2C30004
> +#define	F367_OFDM_SFEC_DEMODSEL1		0xF2C30002
> +#define	F367_OFDM_SFEC_OVFON		0xF2C30001
> +
> +/* SFKDIV12 */
> +#define	R367_OFDM_SFKDIV12		0xF2C4
> +#define	F367_OFDM_SFECKDIV12_MAN		0xF2C40080
> +#define	F367_OFDM_SFEC_K_DIVIDER_12		0xF2C4007F
> +
> +/* SFKDIV23 */
> +#define	R367_OFDM_SFKDIV23		0xF2C5
> +#define	F367_OFDM_SFECKDIV23_MAN		0xF2C50080
> +#define	F367_OFDM_SFEC_K_DIVIDER_23		0xF2C5007F
> +
> +/* SFKDIV34 */
> +#define	R367_OFDM_SFKDIV34		0xF2C6
> +#define	F367_OFDM_SFECKDIV34_MAN		0xF2C60080
> +#define	F367_OFDM_SFEC_K_DIVIDER_34		0xF2C6007F
> +
> +/* SFKDIV56 */
> +#define	R367_OFDM_SFKDIV56		0xF2C7
> +#define	F367_OFDM_SFECKDIV56_MAN		0xF2C70080
> +#define	F367_OFDM_SFEC_K_DIVIDER_56		0xF2C7007F
> +
> +/* SFKDIV67 */
> +#define	R367_OFDM_SFKDIV67		0xF2C8
> +#define	F367_OFDM_SFECKDIV67_MAN		0xF2C80080
> +#define	F367_OFDM_SFEC_K_DIVIDER_67		0xF2C8007F
> +
> +/* SFKDIV78 */
> +#define	R367_OFDM_SFKDIV78		0xF2C9
> +#define	F367_OFDM_SFECKDIV78_MAN		0xF2C90080
> +#define	F367_OFDM_SFEC_K_DIVIDER_78		0xF2C9007F
> +
> +/* SFDILSTKM */
> +#define	R367_OFDM_SFDILSTKM		0xF2CA
> +#define	F367_OFDM_SFEC_PACKCPT		0xF2CA00E0
> +#define	F367_OFDM_SFEC_DILSTK_HI		0xF2CA001F
> +
> +/* SFDILSTKL */
> +#define	R367_OFDM_SFDILSTKL		0xF2CB
> +#define	F367_OFDM_SFEC_DILSTK_LO		0xF2CB00FF
> +
> +/* SFSTATUS */
> +#define	R367_OFDM_SFSTATUS		0xF2CC
> +#define	F367_OFDM_SFEC_LINEOK		0xF2CC0080
> +#define	F367_OFDM_SFEC_ERROR		0xF2CC0040
> +#define	F367_OFDM_SFEC_DATA7		0xF2CC0020
> +#define	F367_OFDM_SFEC_OVERFLOW		0xF2CC0010
> +#define	F367_OFDM_SFEC_DEMODSEL2		0xF2CC0008
> +#define	F367_OFDM_SFEC_NOSYNC		0xF2CC0004
> +#define	F367_OFDM_SFEC_UNREGULA		0xF2CC0002
> +#define	F367_OFDM_SFEC_READY		0xF2CC0001
> +
> +/* SFDLYH */
> +#define	R367_OFDM_SFDLYH		0xF2CD
> +#define	F367_OFDM_SFEC_TSTIMEVALID		0xF2CD0080
> +#define	F367_OFDM_SFEC_SPEEDUP		0xF2CD0040
> +#define	F367_OFDM_SFEC_STOP		0xF2CD0020
> +#define	F367_OFDM_SFEC_REGULATED		0xF2CD0010
> +#define	F367_OFDM_SFEC_REALSYMBOFFSET		0xF2CD000F
> +
> +/* SFDLYM */
> +#define	R367_OFDM_SFDLYM		0xF2CE
> +#define	F367_OFDM_SFEC_REALSYMBOFFSET_HI		0xF2CE00FF
> +
> +/* SFDLYL */
> +#define	R367_OFDM_SFDLYL		0xF2CF
> +#define	F367_OFDM_SFEC_REALSYMBOFFSET_LO		0xF2CF00FF
> +
> +/* SFDLYSETH */
> +#define	R367_OFDM_SFDLYSETH		0xF2D0
> +#define	F367_OFDM_SFEC_OFFSET		0xF2D000E0
> +#define	F367_OFDM_SFECDLYSETH_4		0xF2D00010
> +#define	F367_OFDM_RST_SFEC		0xF2D00008
> +#define	F367_OFDM_SFECDLYSETH_2		0xF2D00004
> +#define	F367_OFDM_SFEC_DISABLE		0xF2D00002
> +#define	F367_OFDM_SFEC_UNREGUL		0xF2D00001
> +
> +/* SFDLYSETM */
> +#define	R367_OFDM_SFDLYSETM		0xF2D1
> +#define	F367_OFDM_SFECDLYSETM_7		0xF2D10080
> +#define	F367_OFDM_SFEC_SYMBOFFSET_HI		0xF2D1007F
> +
> +/* SFDLYSETL */
> +#define	R367_OFDM_SFDLYSETL		0xF2D2
> +#define	F367_OFDM_SFEC_SYMBOFFSET_LO		0xF2D200FF
> +
> +/* SFOBSCFG */
> +#define	R367_OFDM_SFOBSCFG		0xF2D3
> +#define	F367_OFDM_SFEC_OBSCFG		0xF2D300FF
> +
> +/* SFOBSM */
> +#define	R367_OFDM_SFOBSM		0xF2D4
> +#define	F367_OFDM_SFEC_OBSDATA_HI		0xF2D400FF
> +
> +/* SFOBSL */
> +#define	R367_OFDM_SFOBSL		0xF2D5
> +#define	F367_OFDM_SFEC_OBSDATA_LO		0xF2D500FF
> +
> +/* SFECINFO */
> +#define	R367_OFDM_SFECINFO		0xF2D6
> +#define	F367_OFDM_SFECINFO_7		0xF2D60080
> +#define	F367_OFDM_SFEC_SYNCDLSB		0xF2D60070
> +#define	F367_OFDM_SFCE_S1CPHASE		0xF2D6000F
> +
> +/* SFERRCTRL */
> +#define	R367_OFDM_SFERRCTRL		0xF2D8
> +#define	F367_OFDM_SFEC_ERR_SOURCE		0xF2D800F0
> +#define	F367_OFDM_SFERRCTRL_3		0xF2D80008
> +#define	F367_OFDM_SFEC_NUM_EVENT		0xF2D80007
> +
> +/* SFERRCNTH */
> +#define	R367_OFDM_SFERRCNTH		0xF2D9
> +#define	F367_OFDM_SFERRC_OLDVALUE		0xF2D90080
> +#define	F367_OFDM_SFEC_ERR_CNT		0xF2D9007F
> +
> +/* SFERRCNTM */
> +#define	R367_OFDM_SFERRCNTM		0xF2DA
> +#define	F367_OFDM_SFEC_ERR_CNT_HI		0xF2DA00FF
> +
> +/* SFERRCNTL */
> +#define	R367_OFDM_SFERRCNTL		0xF2DB
> +#define	F367_OFDM_SFEC_ERR_CNT_LO		0xF2DB00FF
> +
> +/* SYMBRATEM */
> +#define	R367_OFDM_SYMBRATEM		0xF2E0
> +#define	F367_OFDM_DEFGEN_SYMBRATE_HI		0xF2E000FF
> +
> +/* SYMBRATEL */
> +#define	R367_OFDM_SYMBRATEL		0xF2E1
> +#define	F367_OFDM_DEFGEN_SYMBRATE_LO		0xF2E100FF
> +
> +/* SYMBSTATUS */
> +#define	R367_OFDM_SYMBSTATUS		0xF2E2
> +#define	F367_OFDM_SYMBDLINE2_OFF		0xF2E20080
> +#define	F367_OFDM_SDDL_REINIT1		0xF2E20040
> +#define	F367_OFDM_SDD_REINIT1		0xF2E20020
> +#define	F367_OFDM_TOKENID_ERROR		0xF2E20010
> +#define	F367_OFDM_SYMBRATE_OVERFLOW		0xF2E20008
> +#define	F367_OFDM_SYMBRATE_UNDERFLOW		0xF2E20004
> +#define	F367_OFDM_TOKENID_RSTEVENT		0xF2E20002
> +#define	F367_OFDM_TOKENID_RESET1		0xF2E20001
> +
> +/* SYMBCFG */
> +#define	R367_OFDM_SYMBCFG		0xF2E3
> +#define	F367_OFDM_SYMBCFG_7		0xF2E30080
> +#define	F367_OFDM_SYMBCFG_6		0xF2E30040
> +#define	F367_OFDM_SYMBCFG_5		0xF2E30020
> +#define	F367_OFDM_SYMBCFG_4		0xF2E30010
> +#define	F367_OFDM_SYMRATE_FSPEED		0xF2E3000C
> +#define	F367_OFDM_SYMRATE_SSPEED		0xF2E30003
> +
> +/* SYMBFIFOM */
> +#define	R367_OFDM_SYMBFIFOM		0xF2E4
> +#define	F367_OFDM_SYMBFIFOM_7		0xF2E40080
> +#define	F367_OFDM_SYMBFIFOM_6		0xF2E40040
> +#define	F367_OFDM_DEFGEN_SYMFIFO_HI		0xF2E4003F
> +
> +/* SYMBFIFOL */
> +#define	R367_OFDM_SYMBFIFOL		0xF2E5
> +#define	F367_OFDM_DEFGEN_SYMFIFO_LO		0xF2E500FF
> +
> +/* SYMBOFFSM */
> +#define	R367_OFDM_SYMBOFFSM		0xF2E6
> +#define	F367_OFDM_TOKENID_RESET2		0xF2E60080
> +#define	F367_OFDM_SDDL_REINIT2		0xF2E60040
> +#define	F367_OFDM_SDD_REINIT2		0xF2E60020
> +#define	F367_OFDM_SYMBOFFSM_4		0xF2E60010
> +#define	F367_OFDM_SYMBOFFSM_3		0xF2E60008
> +#define	F367_OFDM_DEFGEN_SYMBOFFSET_HI		0xF2E60007
> +
> +/* SYMBOFFSL */
> +#define	R367_OFDM_SYMBOFFSL		0xF2E7
> +#define	F367_OFDM_DEFGEN_SYMBOFFSET_LO		0xF2E700FF
> +
> +/* DEBUG_LT4 */
> +#define	R367_DEBUG_LT4		0xF400
> +#define	F367_F_DEBUG_LT4		0xF40000FF
> +
> +/* DEBUG_LT5 */
> +#define	R367_DEBUG_LT5		0xF401
> +#define	F367_F_DEBUG_LT5		0xF40100FF
> +
> +/* DEBUG_LT6 */
> +#define	R367_DEBUG_LT6		0xF402
> +#define	F367_F_DEBUG_LT6		0xF40200FF
> +
> +/* DEBUG_LT7 */
> +#define	R367_DEBUG_LT7		0xF403
> +#define	F367_F_DEBUG_LT7		0xF40300FF
> +
> +/* DEBUG_LT8 */
> +#define	R367_DEBUG_LT8		0xF404
> +#define	F367_F_DEBUG_LT8		0xF40400FF
> +
> +/* DEBUG_LT9 */
> +#define	R367_DEBUG_LT9		0xF405
> +#define	F367_F_DEBUG_LT9		0xF40500FF
> +
> +/* CTRL_1 */
> +#define	R367_QAM_CTRL_1		0xF402
> +#define	F367_QAM_SOFT_RST		0xF4020080
> +#define	F367_QAM_EQU_RST		0xF4020008
> +#define	F367_QAM_CRL_RST		0xF4020004
> +#define	F367_QAM_TRL_RST		0xF4020002
> +#define	F367_QAM_AGC_RST		0xF4020001
> +
> +/* CTRL_2 */
> +#define	R367_QAM_CTRL_2		0xF403
> +#define	F367_QAM_DEINT_RST		0xF4030008
> +#define	F367_QAM_RS_RST		0xF4030004
> +
> +/* IT_STATUS1 */
> +#define	R367_QAM_IT_STATUS1		0xF408
> +#define	F367_QAM_SWEEP_OUT		0xF4080080
> +#define	F367_QAM_FSM_CRL		0xF4080040
> +#define	F367_QAM_CRL_LOCK		0xF4080020
> +#define	F367_QAM_MFSM		0xF4080010
> +#define	F367_QAM_TRL_LOCK		0xF4080008
> +#define	F367_QAM_TRL_AGC_LIMIT		0xF4080004
> +#define	F367_QAM_ADJ_AGC_LOCK		0xF4080002
> +#define	F367_QAM_AGC_QAM_LOCK		0xF4080001
> +
> +/* IT_STATUS2 */
> +#define	R367_QAM_IT_STATUS2		0xF409
> +#define	F367_QAM_TSMF_CNT		0xF4090080
> +#define	F367_QAM_TSMF_EOF		0xF4090040
> +#define	F367_QAM_TSMF_RDY		0xF4090020
> +#define	F367_QAM_FEC_NOCORR		0xF4090010
> +#define	F367_QAM_SYNCSTATE		0xF4090008
> +#define	F367_QAM_DEINT_LOCK		0xF4090004
> +#define	F367_QAM_FADDING_FRZ		0xF4090002
> +#define	F367_QAM_TAPMON_ALARM		0xF4090001
> +
> +/* IT_EN1 */
> +#define	R367_QAM_IT_EN1		0xF40A
> +#define	F367_QAM_SWEEP_OUTE		0xF40A0080
> +#define	F367_QAM_FSM_CRLE		0xF40A0040
> +#define	F367_QAM_CRL_LOCKE		0xF40A0020
> +#define	F367_QAM_MFSME		0xF40A0010
> +#define	F367_QAM_TRL_LOCKE		0xF40A0008
> +#define	F367_QAM_TRL_AGC_LIMITE		0xF40A0004
> +#define	F367_QAM_ADJ_AGC_LOCKE		0xF40A0002
> +#define	F367_QAM_AGC_LOCKE		0xF40A0001
> +
> +/* IT_EN2 */
> +#define	R367_QAM_IT_EN2		0xF40B
> +#define	F367_QAM_TSMF_CNTE		0xF40B0080
> +#define	F367_QAM_TSMF_EOFE		0xF40B0040
> +#define	F367_QAM_TSMF_RDYE		0xF40B0020
> +#define	F367_QAM_FEC_NOCORRE		0xF40B0010
> +#define	F367_QAM_SYNCSTATEE		0xF40B0008
> +#define	F367_QAM_DEINT_LOCKE		0xF40B0004
> +#define	F367_QAM_FADDING_FRZE		0xF40B0002
> +#define	F367_QAM_TAPMON_ALARME		0xF40B0001
> +
> +/* CTRL_STATUS */
> +#define	R367_QAM_CTRL_STATUS		0xF40C
> +#define	F367_QAM_QAMFEC_LOCK		0xF40C0004
> +#define	F367_QAM_TSMF_LOCK		0xF40C0002
> +#define	F367_QAM_TSMF_ERROR		0xF40C0001
> +
> +/* TEST_CTL */
> +#define	R367_QAM_TEST_CTL		0xF40F
> +#define	F367_QAM_TST_BLK_SEL		0xF40F0060
> +#define	F367_QAM_TST_BUS_SEL		0xF40F001F
> +
> +/* AGC_CTL */
> +#define	R367_QAM_AGC_CTL		0xF410
> +#define	F367_QAM_AGC_LCK_TH		0xF41000F0
> +#define	F367_QAM_AGC_ACCUMRSTSEL		0xF4100007
> +
> +/* AGC_IF_CFG */
> +#define	R367_QAM_AGC_IF_CFG		0xF411
> +#define	F367_QAM_AGC_IF_BWSEL		0xF41100F0
> +#define	F367_QAM_AGC_IF_FREEZE		0xF4110002
> +
> +/* AGC_RF_CFG */
> +#define	R367_QAM_AGC_RF_CFG		0xF412
> +#define	F367_QAM_AGC_RF_BWSEL		0xF4120070
> +#define	F367_QAM_AGC_RF_FREEZE		0xF4120002
> +
> +/* AGC_PWM_CFG */
> +#define	R367_QAM_AGC_PWM_CFG		0xF413
> +#define	F367_QAM_AGC_RF_PWM_TST		0xF4130080
> +#define	F367_QAM_AGC_RF_PWM_INV		0xF4130040
> +#define	F367_QAM_AGC_IF_PWM_TST		0xF4130008
> +#define	F367_QAM_AGC_IF_PWM_INV		0xF4130004
> +#define	F367_QAM_AGC_PWM_CLKDIV		0xF4130003
> +
> +/* AGC_PWR_REF_L */
> +#define	R367_QAM_AGC_PWR_REF_L		0xF414
> +#define	F367_QAM_AGC_PWRREF_LO		0xF41400FF
> +
> +/* AGC_PWR_REF_H */
> +#define	R367_QAM_AGC_PWR_REF_H		0xF415
> +#define	F367_QAM_AGC_PWRREF_HI		0xF4150003
> +
> +/* AGC_RF_TH_L */
> +#define	R367_QAM_AGC_RF_TH_L		0xF416
> +#define	F367_QAM_AGC_RF_TH_LO		0xF41600FF
> +
> +/* AGC_RF_TH_H */
> +#define	R367_QAM_AGC_RF_TH_H		0xF417
> +#define	F367_QAM_AGC_RF_TH_HI		0xF417000F
> +
> +/* AGC_IF_LTH_L */
> +#define	R367_QAM_AGC_IF_LTH_L		0xF418
> +#define	F367_QAM_AGC_IF_THLO_LO		0xF41800FF
> +
> +/* AGC_IF_LTH_H */
> +#define	R367_QAM_AGC_IF_LTH_H		0xF419
> +#define	F367_QAM_AGC_IF_THLO_HI		0xF419000F
> +
> +/* AGC_IF_HTH_L */
> +#define	R367_QAM_AGC_IF_HTH_L		0xF41A
> +#define	F367_QAM_AGC_IF_THHI_LO		0xF41A00FF
> +
> +/* AGC_IF_HTH_H */
> +#define	R367_QAM_AGC_IF_HTH_H		0xF41B
> +#define	F367_QAM_AGC_IF_THHI_HI		0xF41B000F
> +
> +/* AGC_PWR_RD_L */
> +#define	R367_QAM_AGC_PWR_RD_L		0xF41C
> +#define	F367_QAM_AGC_PWR_WORD_LO		0xF41C00FF
> +
> +/* AGC_PWR_RD_M */
> +#define	R367_QAM_AGC_PWR_RD_M		0xF41D
> +#define	F367_QAM_AGC_PWR_WORD_ME		0xF41D00FF
> +
> +/* AGC_PWR_RD_H */
> +#define	R367_QAM_AGC_PWR_RD_H		0xF41E
> +#define	F367_QAM_AGC_PWR_WORD_HI		0xF41E0003
> +
> +/* AGC_PWM_IFCMD_L */
> +#define	R367_QAM_AGC_PWM_IFCMD_L		0xF420
> +#define	F367_QAM_AGC_IF_PWMCMD_LO		0xF42000FF
> +
> +/* AGC_PWM_IFCMD_H */
> +#define	R367_QAM_AGC_PWM_IFCMD_H		0xF421
> +#define	F367_QAM_AGC_IF_PWMCMD_HI		0xF421000F
> +
> +/* AGC_PWM_RFCMD_L */
> +#define	R367_QAM_AGC_PWM_RFCMD_L		0xF422
> +#define	F367_QAM_AGC_RF_PWMCMD_LO		0xF42200FF
> +
> +/* AGC_PWM_RFCMD_H */
> +#define	R367_QAM_AGC_PWM_RFCMD_H		0xF423
> +#define	F367_QAM_AGC_RF_PWMCMD_HI		0xF423000F
> +
> +/* IQDEM_CFG */
> +#define	R367_QAM_IQDEM_CFG		0xF424
> +#define	F367_QAM_IQDEM_CLK_SEL		0xF4240004
> +#define	F367_QAM_IQDEM_INVIQ		0xF4240002
> +#define	F367_QAM_IQDEM_A2DTYPE		0xF4240001
> +
> +/* MIX_NCO_LL */
> +#define	R367_QAM_MIX_NCO_LL		0xF425
> +#define	F367_QAM_MIX_NCO_INC_LL		0xF42500FF
> +
> +/* MIX_NCO_HL */
> +#define	R367_QAM_MIX_NCO_HL		0xF426
> +#define	F367_QAM_MIX_NCO_INC_HL		0xF42600FF
> +
> +/* MIX_NCO_HH */
> +#define	R367_QAM_MIX_NCO_HH		0xF427
> +#define	F367_QAM_MIX_NCO_INVCNST		0xF4270080
> +#define	F367_QAM_MIX_NCO_INC_HH		0xF427007F
> +
> +/* SRC_NCO_LL */
> +#define	R367_QAM_SRC_NCO_LL		0xF428
> +#define	F367_QAM_SRC_NCO_INC_LL		0xF42800FF
> +
> +/* SRC_NCO_LH */
> +#define	R367_QAM_SRC_NCO_LH		0xF429
> +#define	F367_QAM_SRC_NCO_INC_LH		0xF42900FF
> +
> +/* SRC_NCO_HL */
> +#define	R367_QAM_SRC_NCO_HL		0xF42A
> +#define	F367_QAM_SRC_NCO_INC_HL		0xF42A00FF
> +
> +/* SRC_NCO_HH */
> +#define	R367_QAM_SRC_NCO_HH		0xF42B
> +#define	F367_QAM_SRC_NCO_INC_HH		0xF42B007F
> +
> +/* IQDEM_GAIN_SRC_L */
> +#define	R367_QAM_IQDEM_GAIN_SRC_L		0xF42C
> +#define	F367_QAM_GAIN_SRC_LO		0xF42C00FF
> +
> +/* IQDEM_GAIN_SRC_H */
> +#define	R367_QAM_IQDEM_GAIN_SRC_H		0xF42D
> +#define	F367_QAM_GAIN_SRC_HI		0xF42D0003
> +
> +/* IQDEM_DCRM_CFG_LL */
> +#define	R367_QAM_IQDEM_DCRM_CFG_LL		0xF430
> +#define	F367_QAM_DCRM0_DCIN_L		0xF43000FF
> +
> +/* IQDEM_DCRM_CFG_LH */
> +#define	R367_QAM_IQDEM_DCRM_CFG_LH		0xF431
> +#define	F367_QAM_DCRM1_I_DCIN_L		0xF43100FC
> +#define	F367_QAM_DCRM0_DCIN_H		0xF4310003
> +
> +/* IQDEM_DCRM_CFG_HL */
> +#define	R367_QAM_IQDEM_DCRM_CFG_HL		0xF432
> +#define	F367_QAM_DCRM1_Q_DCIN_L		0xF43200F0
> +#define	F367_QAM_DCRM1_I_DCIN_H		0xF432000F
> +
> +/* IQDEM_DCRM_CFG_HH */
> +#define	R367_QAM_IQDEM_DCRM_CFG_HH		0xF433
> +#define	F367_QAM_DCRM1_FRZ		0xF4330080
> +#define	F367_QAM_DCRM0_FRZ		0xF4330040
> +#define	F367_QAM_DCRM1_Q_DCIN_H		0xF433003F
> +
> +/* IQDEM_ADJ_COEFF0 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF0		0xF434
> +#define	F367_QAM_ADJIIR_COEFF10_L		0xF43400FF
> +
> +/* IQDEM_ADJ_COEFF1 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF1		0xF435
> +#define	F367_QAM_ADJIIR_COEFF11_L		0xF43500FC
> +#define	F367_QAM_ADJIIR_COEFF10_H		0xF4350003
> +
> +/* IQDEM_ADJ_COEFF2 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF2		0xF436
> +#define	F367_QAM_ADJIIR_COEFF12_L		0xF43600F0
> +#define	F367_QAM_ADJIIR_COEFF11_H		0xF436000F
> +
> +/* IQDEM_ADJ_COEFF3 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF3		0xF437
> +#define	F367_QAM_ADJIIR_COEFF20_L		0xF43700C0
> +#define	F367_QAM_ADJIIR_COEFF12_H		0xF437003F
> +
> +/* IQDEM_ADJ_COEFF4 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF4		0xF438
> +#define	F367_QAM_ADJIIR_COEFF20_H		0xF43800FF
> +
> +/* IQDEM_ADJ_COEFF5 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF5		0xF439
> +#define	F367_QAM_ADJIIR_COEFF21_L		0xF43900FF
> +
> +/* IQDEM_ADJ_COEFF6 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF6		0xF43A
> +#define	F367_QAM_ADJIIR_COEFF22_L		0xF43A00FC
> +#define	F367_QAM_ADJIIR_COEFF21_H		0xF43A0003
> +
> +/* IQDEM_ADJ_COEFF7 */
> +#define	R367_QAM_IQDEM_ADJ_COEFF7		0xF43B
> +#define	F367_QAM_ADJIIR_COEFF22_H		0xF43B000F
> +
> +/* IQDEM_ADJ_EN */
> +#define	R367_QAM_IQDEM_ADJ_EN		0xF43C
> +#define	F367_QAM_ALLPASSFILT_EN		0xF43C0008
> +#define	F367_QAM_ADJ_AGC_EN		0xF43C0004
> +#define	F367_QAM_ADJ_COEFF_FRZ		0xF43C0002
> +#define	F367_QAM_ADJ_EN		0xF43C0001
> +
> +/* IQDEM_ADJ_AGC_REF */
> +#define	R367_QAM_IQDEM_ADJ_AGC_REF		0xF43D
> +#define	F367_QAM_ADJ_AGC_REF		0xF43D00FF
> +
> +/* ALLPASSFILT1 */
> +#define	R367_QAM_ALLPASSFILT1		0xF440
> +#define	F367_QAM_ALLPASSFILT_COEFF1_LO		0xF44000FF
> +
> +/* ALLPASSFILT2 */
> +#define	R367_QAM_ALLPASSFILT2		0xF441
> +#define	F367_QAM_ALLPASSFILT_COEFF1_ME		0xF44100FF
> +
> +/* ALLPASSFILT3 */
> +#define	R367_QAM_ALLPASSFILT3		0xF442
> +#define	F367_QAM_ALLPASSFILT_COEFF2_LO		0xF44200C0
> +#define	F367_QAM_ALLPASSFILT_COEFF1_HI		0xF442003F
> +
> +/* ALLPASSFILT4 */
> +#define	R367_QAM_ALLPASSFILT4		0xF443
> +#define	F367_QAM_ALLPASSFILT_COEFF2_MEL		0xF44300FF
> +
> +/* ALLPASSFILT5 */
> +#define	R367_QAM_ALLPASSFILT5		0xF444
> +#define	F367_QAM_ALLPASSFILT_COEFF2_MEH		0xF44400FF
> +
> +/* ALLPASSFILT6 */
> +#define	R367_QAM_ALLPASSFILT6		0xF445
> +#define	F367_QAM_ALLPASSFILT_COEFF3_LO		0xF44500F0
> +#define	F367_QAM_ALLPASSFILT_COEFF2_HI		0xF445000F
> +
> +/* ALLPASSFILT7 */
> +#define	R367_QAM_ALLPASSFILT7		0xF446
> +#define	F367_QAM_ALLPASSFILT_COEFF3_MEL		0xF44600FF
> +
> +/* ALLPASSFILT8 */
> +#define	R367_QAM_ALLPASSFILT8		0xF447
> +#define	F367_QAM_ALLPASSFILT_COEFF3_MEH		0xF44700FF
> +
> +/* ALLPASSFILT9 */
> +#define	R367_QAM_ALLPASSFILT9		0xF448
> +#define	F367_QAM_ALLPASSFILT_COEFF4_LO		0xF44800FC
> +#define	F367_QAM_ALLPASSFILT_COEFF3_HI		0xF4480003
> +
> +/* ALLPASSFILT10 */
> +#define	R367_QAM_ALLPASSFILT10		0xF449
> +#define	F367_QAM_ALLPASSFILT_COEFF4_ME		0xF44900FF
> +
> +/* ALLPASSFILT11 */
> +#define	R367_QAM_ALLPASSFILT11		0xF44A
> +#define	F367_QAM_ALLPASSFILT_COEFF4_HI		0xF44A00FF
> +
> +/* TRL_AGC_CFG */
> +#define	R367_QAM_TRL_AGC_CFG		0xF450
> +#define	F367_QAM_TRL_AGC_FREEZE		0xF4500080
> +#define	F367_QAM_TRL_AGC_REF		0xF450007F
> +
> +/* TRL_LPF_CFG */
> +#define	R367_QAM_TRL_LPF_CFG		0xF454
> +#define	F367_QAM_NYQPOINT_INV		0xF4540040
> +#define	F367_QAM_TRL_SHIFT		0xF4540030
> +#define	F367_QAM_NYQ_COEFF_SEL		0xF454000C
> +#define	F367_QAM_TRL_LPF_FREEZE		0xF4540002
> +#define	F367_QAM_TRL_LPF_CRT		0xF4540001
> +
> +/* TRL_LPF_ACQ_GAIN */
> +#define	R367_QAM_TRL_LPF_ACQ_GAIN		0xF455
> +#define	F367_QAM_TRL_GDIR_ACQ		0xF4550070
> +#define	F367_QAM_TRL_GINT_ACQ		0xF4550007
> +
> +/* TRL_LPF_TRK_GAIN */
> +#define	R367_QAM_TRL_LPF_TRK_GAIN		0xF456
> +#define	F367_QAM_TRL_GDIR_TRK		0xF4560070
> +#define	F367_QAM_TRL_GINT_TRK		0xF4560007
> +
> +/* TRL_LPF_OUT_GAIN */
> +#define	R367_QAM_TRL_LPF_OUT_GAIN		0xF457
> +#define	F367_QAM_TRL_GAIN_OUT		0xF4570007
> +
> +/* TRL_LOCKDET_LTH */
> +#define	R367_QAM_TRL_LOCKDET_LTH		0xF458
> +#define	F367_QAM_TRL_LCK_THLO		0xF4580007
> +
> +/* TRL_LOCKDET_HTH */
> +#define	R367_QAM_TRL_LOCKDET_HTH		0xF459
> +#define	F367_QAM_TRL_LCK_THHI		0xF45900FF
> +
> +/* TRL_LOCKDET_TRGVAL */
> +#define	R367_QAM_TRL_LOCKDET_TRGVAL		0xF45A
> +#define	F367_QAM_TRL_LCK_TRG		0xF45A00FF
> +
> +/* IQ_QAM */
> +#define	R367_QAM_IQ_QAM		0xF45C
> +#define	F367_QAM_IQ_INPUT		0xF45C0008
> +#define	F367_QAM_DETECT_MODE		0xF45C0007
> +
> +/* FSM_STATE */
> +#define	R367_QAM_FSM_STATE		0xF460
> +#define	F367_QAM_CRL_DFE		0xF4600080
> +#define	F367_QAM_DFE_START		0xF4600040
> +#define	F367_QAM_CTRLG_START		0xF4600030
> +#define	F367_QAM_FSM_FORCESTATE		0xF460000F
> +
> +/* FSM_CTL */
> +#define	R367_QAM_FSM_CTL		0xF461
> +#define	F367_QAM_FEC2_EN		0xF4610040
> +#define	F367_QAM_SIT_EN		0xF4610020
> +#define	F367_QAM_TRL_AHEAD		0xF4610010
> +#define	F367_QAM_TRL2_EN		0xF4610008
> +#define	F367_QAM_FSM_EQA1_EN		0xF4610004
> +#define	F367_QAM_FSM_BKP_DIS		0xF4610002
> +#define	F367_QAM_FSM_FORCE_EN		0xF4610001
> +
> +/* FSM_STS */
> +#define	R367_QAM_FSM_STS		0xF462
> +#define	F367_QAM_FSM_STATUS		0xF462000F
> +
> +/* FSM_SNR0_HTH */
> +#define	R367_QAM_FSM_SNR0_HTH		0xF463
> +#define	F367_QAM_SNR0_HTH		0xF46300FF
> +
> +/* FSM_SNR1_HTH */
> +#define	R367_QAM_FSM_SNR1_HTH		0xF464
> +#define	F367_QAM_SNR1_HTH		0xF46400FF
> +
> +/* FSM_SNR2_HTH */
> +#define	R367_QAM_FSM_SNR2_HTH		0xF465
> +#define	F367_QAM_SNR2_HTH		0xF46500FF
> +
> +/* FSM_SNR0_LTH */
> +#define	R367_QAM_FSM_SNR0_LTH		0xF466
> +#define	F367_QAM_SNR0_LTH		0xF46600FF
> +
> +/* FSM_SNR1_LTH */
> +#define	R367_QAM_FSM_SNR1_LTH		0xF467
> +#define	F367_QAM_SNR1_LTH		0xF46700FF
> +
> +/* FSM_EQA1_HTH */
> +#define	R367_QAM_FSM_EQA1_HTH		0xF468
> +#define	F367_QAM_SNR3_HTH_LO		0xF46800F0
> +#define	F367_QAM_EQA1_HTH		0xF468000F
> +
> +/* FSM_TEMPO */
> +#define	R367_QAM_FSM_TEMPO		0xF469
> +#define	F367_QAM_SIT		0xF46900C0
> +#define	F367_QAM_WST		0xF4690038
> +#define	F367_QAM_ELT		0xF4690006
> +#define	F367_QAM_SNR3_HTH_HI		0xF4690001
> +
> +/* FSM_CONFIG */
> +#define	R367_QAM_FSM_CONFIG		0xF46A
> +#define	F367_QAM_FEC2_DFEOFF		0xF46A0004
> +#define	F367_QAM_PRIT_STATE		0xF46A0002
> +#define	F367_QAM_MODMAP_STATE		0xF46A0001
> +
> +/* EQU_I_TESTTAP_L */
> +#define	R367_QAM_EQU_I_TESTTAP_L		0xF474
> +#define	F367_QAM_I_TEST_TAP_L		0xF47400FF
> +
> +/* EQU_I_TESTTAP_M */
> +#define	R367_QAM_EQU_I_TESTTAP_M		0xF475
> +#define	F367_QAM_I_TEST_TAP_M		0xF47500FF
> +
> +/* EQU_I_TESTTAP_H */
> +#define	R367_QAM_EQU_I_TESTTAP_H		0xF476
> +#define	F367_QAM_I_TEST_TAP_H		0xF476001F
> +
> +/* EQU_TESTAP_CFG */
> +#define	R367_QAM_EQU_TESTAP_CFG		0xF477
> +#define	F367_QAM_TEST_FFE_DFE_SEL		0xF4770040
> +#define	F367_QAM_TEST_TAP_SELECT		0xF477003F
> +
> +/* EQU_Q_TESTTAP_L */
> +#define	R367_QAM_EQU_Q_TESTTAP_L		0xF478
> +#define	F367_QAM_Q_TEST_TAP_L		0xF47800FF
> +
> +/* EQU_Q_TESTTAP_M */
> +#define	R367_QAM_EQU_Q_TESTTAP_M		0xF479
> +#define	F367_QAM_Q_TEST_TAP_M		0xF47900FF
> +
> +/* EQU_Q_TESTTAP_H */
> +#define	R367_QAM_EQU_Q_TESTTAP_H		0xF47A
> +#define	F367_QAM_Q_TEST_TAP_H		0xF47A001F
> +
> +/* EQU_TAP_CTRL */
> +#define	R367_QAM_EQU_TAP_CTRL		0xF47B
> +#define	F367_QAM_MTAP_FRZ		0xF47B0010
> +#define	F367_QAM_PRE_FREEZE		0xF47B0008
> +#define	F367_QAM_DFE_TAPMON_EN		0xF47B0004
> +#define	F367_QAM_FFE_TAPMON_EN		0xF47B0002
> +#define	F367_QAM_MTAP_ONLY		0xF47B0001
> +
> +/* EQU_CTR_CRL_CONTROL_L */
> +#define	R367_QAM_EQU_CTR_CRL_CONTROL_L		0xF47C
> +#define	F367_QAM_EQU_CTR_CRL_CONTROL_LO		0xF47C00FF
> +
> +/* EQU_CTR_CRL_CONTROL_H */
> +#define	R367_QAM_EQU_CTR_CRL_CONTROL_H		0xF47D
> +#define	F367_QAM_EQU_CTR_CRL_CONTROL_HI		0xF47D00FF
> +
> +/* EQU_CTR_HIPOW_L */
> +#define	R367_QAM_EQU_CTR_HIPOW_L		0xF47E
> +#define	F367_QAM_CTR_HIPOW_L		0xF47E00FF
> +
> +/* EQU_CTR_HIPOW_H */
> +#define	R367_QAM_EQU_CTR_HIPOW_H		0xF47F
> +#define	F367_QAM_CTR_HIPOW_H		0xF47F00FF
> +
> +/* EQU_I_EQU_LO */
> +#define	R367_QAM_EQU_I_EQU_LO		0xF480
> +#define	F367_QAM_EQU_I_EQU_L		0xF48000FF
> +
> +/* EQU_I_EQU_HI */
> +#define	R367_QAM_EQU_I_EQU_HI		0xF481
> +#define	F367_QAM_EQU_I_EQU_H		0xF4810003
> +
> +/* EQU_Q_EQU_LO */
> +#define	R367_QAM_EQU_Q_EQU_LO		0xF482
> +#define	F367_QAM_EQU_Q_EQU_L		0xF48200FF
> +
> +/* EQU_Q_EQU_HI */
> +#define	R367_QAM_EQU_Q_EQU_HI		0xF483
> +#define	F367_QAM_EQU_Q_EQU_H		0xF4830003
> +
> +/* EQU_MAPPER */
> +#define	R367_QAM_EQU_MAPPER		0xF484
> +#define	F367_QAM_QUAD_AUTO		0xF4840080
> +#define	F367_QAM_QUAD_INV		0xF4840040
> +#define	F367_QAM_QAM_MODE		0xF4840007
> +
> +/* EQU_SWEEP_RATE */
> +#define	R367_QAM_EQU_SWEEP_RATE		0xF485
> +#define	F367_QAM_SNR_PER		0xF48500C0
> +#define	F367_QAM_SWEEP_RATE		0xF485003F
> +
> +/* EQU_SNR_LO */
> +#define	R367_QAM_EQU_SNR_LO		0xF486
> +#define	F367_QAM_SNR_LO		0xF48600FF
> +
> +/* EQU_SNR_HI */
> +#define	R367_QAM_EQU_SNR_HI		0xF487
> +#define	F367_QAM_SNR_HI		0xF48700FF
> +
> +/* EQU_GAMMA_LO */
> +#define	R367_QAM_EQU_GAMMA_LO		0xF488
> +#define	F367_QAM_GAMMA_LO		0xF48800FF
> +
> +/* EQU_GAMMA_HI */
> +#define	R367_QAM_EQU_GAMMA_HI		0xF489
> +#define	F367_QAM_GAMMA_ME		0xF48900FF
> +
> +/* EQU_ERR_GAIN */
> +#define	R367_QAM_EQU_ERR_GAIN		0xF48A
> +#define	F367_QAM_EQA1MU		0xF48A0070
> +#define	F367_QAM_CRL2MU		0xF48A000E
> +#define	F367_QAM_GAMMA_HI		0xF48A0001
> +
> +/* EQU_RADIUS */
> +#define	R367_QAM_EQU_RADIUS		0xF48B
> +#define	F367_QAM_RADIUS		0xF48B00FF
> +
> +/* EQU_FFE_MAINTAP */
> +#define	R367_QAM_EQU_FFE_MAINTAP		0xF48C
> +#define	F367_QAM_FFE_MAINTAP_INIT		0xF48C00FF
> +
> +/* EQU_FFE_LEAKAGE */
> +#define	R367_QAM_EQU_FFE_LEAKAGE		0xF48E
> +#define	F367_QAM_LEAK_PER		0xF48E00F0
> +#define	F367_QAM_EQU_OUTSEL		0xF48E0002
> +#define	F367_QAM_PNT2DFE		0xF48E0001
> +
> +/* EQU_FFE_MAINTAP_POS */
> +#define	R367_QAM_EQU_FFE_MAINTAP_POS		0xF48F
> +#define	F367_QAM_FFE_LEAK_EN		0xF48F0080
> +#define	F367_QAM_DFE_LEAK_EN		0xF48F0040
> +#define	F367_QAM_FFE_MAINTAP_POS		0xF48F003F
> +
> +/* EQU_GAIN_WIDE */
> +#define	R367_QAM_EQU_GAIN_WIDE		0xF490
> +#define	F367_QAM_DFE_GAIN_WIDE		0xF49000F0
> +#define	F367_QAM_FFE_GAIN_WIDE		0xF490000F
> +
> +/* EQU_GAIN_NARROW */
> +#define	R367_QAM_EQU_GAIN_NARROW		0xF491
> +#define	F367_QAM_DFE_GAIN_NARROW		0xF49100F0
> +#define	F367_QAM_FFE_GAIN_NARROW		0xF491000F
> +
> +/* EQU_CTR_LPF_GAIN */
> +#define	R367_QAM_EQU_CTR_LPF_GAIN		0xF492
> +#define	F367_QAM_CTR_GTO		0xF4920080
> +#define	F367_QAM_CTR_GDIR		0xF4920070
> +#define	F367_QAM_SWEEP_EN		0xF4920008
> +#define	F367_QAM_CTR_GINT		0xF4920007
> +
> +/* EQU_CRL_LPF_GAIN */
> +#define	R367_QAM_EQU_CRL_LPF_GAIN		0xF493
> +#define	F367_QAM_CRL_GTO		0xF4930080
> +#define	F367_QAM_CRL_GDIR		0xF4930070
> +#define	F367_QAM_SWEEP_DIR		0xF4930008
> +#define	F367_QAM_CRL_GINT		0xF4930007
> +
> +/* EQU_GLOBAL_GAIN */
> +#define	R367_QAM_EQU_GLOBAL_GAIN		0xF494
> +#define	F367_QAM_CRL_GAIN		0xF49400F8
> +#define	F367_QAM_CTR_INC_GAIN		0xF4940004
> +#define	F367_QAM_CTR_FRAC		0xF4940003
> +
> +/* EQU_CRL_LD_SEN */
> +#define	R367_QAM_EQU_CRL_LD_SEN		0xF495
> +#define	F367_QAM_CTR_BADPOINT_EN		0xF4950080
> +#define	F367_QAM_CTR_GAIN		0xF4950070
> +#define	F367_QAM_LIMANEN		0xF4950008
> +#define	F367_QAM_CRL_LD_SEN		0xF4950007
> +
> +/* EQU_CRL_LD_VAL */
> +#define	R367_QAM_EQU_CRL_LD_VAL		0xF496
> +#define	F367_QAM_CRL_BISTH_LIMIT		0xF4960080
> +#define	F367_QAM_CARE_EN		0xF4960040
> +#define	F367_QAM_CRL_LD_PER		0xF4960030
> +#define	F367_QAM_CRL_LD_WST		0xF496000C
> +#define	F367_QAM_CRL_LD_TFS		0xF4960003
> +
> +/* EQU_CRL_TFR */
> +#define	R367_QAM_EQU_CRL_TFR		0xF497
> +#define	F367_QAM_CRL_LD_TFR		0xF49700FF
> +
> +/* EQU_CRL_BISTH_LO */
> +#define	R367_QAM_EQU_CRL_BISTH_LO		0xF498
> +#define	F367_QAM_CRL_BISTH_LO		0xF49800FF
> +
> +/* EQU_CRL_BISTH_HI */
> +#define	R367_QAM_EQU_CRL_BISTH_HI		0xF499
> +#define	F367_QAM_CRL_BISTH_HI		0xF49900FF
> +
> +/* EQU_SWEEP_RANGE_LO */
> +#define	R367_QAM_EQU_SWEEP_RANGE_LO		0xF49A
> +#define	F367_QAM_SWEEP_RANGE_LO		0xF49A00FF
> +
> +/* EQU_SWEEP_RANGE_HI */
> +#define	R367_QAM_EQU_SWEEP_RANGE_HI		0xF49B
> +#define	F367_QAM_SWEEP_RANGE_HI		0xF49B00FF
> +
> +/* EQU_CRL_LIMITER */
> +#define	R367_QAM_EQU_CRL_LIMITER		0xF49C
> +#define	F367_QAM_BISECTOR_EN		0xF49C0080
> +#define	F367_QAM_PHEST128_EN		0xF49C0040
> +#define	F367_QAM_CRL_LIM		0xF49C003F
> +
> +/* EQU_MODULUS_MAP */
> +#define	R367_QAM_EQU_MODULUS_MAP		0xF49D
> +#define	F367_QAM_PNT_DEPTH		0xF49D00E0
> +#define	F367_QAM_MODULUS_CMP		0xF49D001F
> +
> +/* EQU_PNT_GAIN */
> +#define	R367_QAM_EQU_PNT_GAIN		0xF49E
> +#define	F367_QAM_PNT_EN		0xF49E0080
> +#define	F367_QAM_MODULUSMAP_EN		0xF49E0040
> +#define	F367_QAM_PNT_GAIN		0xF49E003F
> +
> +/* FEC_AC_CTR_0 */
> +#define	R367_QAM_FEC_AC_CTR_0		0xF4A8
> +#define	F367_QAM_BE_BYPASS		0xF4A80020
> +#define	F367_QAM_REFRESH47		0xF4A80010
> +#define	F367_QAM_CT_NBST		0xF4A80008
> +#define	F367_QAM_TEI_ENA		0xF4A80004
> +#define	F367_QAM_DS_ENA		0xF4A80002
> +#define	F367_QAM_TSMF_EN		0xF4A80001
> +
> +/* FEC_AC_CTR_1 */
> +#define	R367_QAM_FEC_AC_CTR_1		0xF4A9
> +#define	F367_QAM_DEINT_DEPTH		0xF4A900FF
> +
> +/* FEC_AC_CTR_2 */
> +#define	R367_QAM_FEC_AC_CTR_2		0xF4AA
> +#define	F367_QAM_DEINT_M		0xF4AA00F8
> +#define	F367_QAM_DIS_UNLOCK		0xF4AA0004
> +#define	F367_QAM_DESCR_MODE		0xF4AA0003
> +
> +/* FEC_AC_CTR_3 */
> +#define	R367_QAM_FEC_AC_CTR_3		0xF4AB
> +#define	F367_QAM_DI_UNLOCK		0xF4AB0080
> +#define	F367_QAM_DI_FREEZE		0xF4AB0040
> +#define	F367_QAM_MISMATCH		0xF4AB0030
> +#define	F367_QAM_ACQ_MODE		0xF4AB000C
> +#define	F367_QAM_TRK_MODE		0xF4AB0003
> +
> +/* FEC_STATUS */
> +#define	R367_QAM_FEC_STATUS		0xF4AC
> +#define	F367_QAM_DEINT_SMCNTR		0xF4AC00E0
> +#define	F367_QAM_DEINT_SYNCSTATE		0xF4AC0018
> +#define	F367_QAM_DEINT_SYNLOST		0xF4AC0004
> +#define	F367_QAM_DESCR_SYNCSTATE		0xF4AC0002
> +
> +/* RS_COUNTER_0 */
> +#define	R367_QAM_RS_COUNTER_0		0xF4AE
> +#define	F367_QAM_BK_CT_L		0xF4AE00FF
> +
> +/* RS_COUNTER_1 */
> +#define	R367_QAM_RS_COUNTER_1		0xF4AF
> +#define	F367_QAM_BK_CT_H		0xF4AF00FF
> +
> +/* RS_COUNTER_2 */
> +#define	R367_QAM_RS_COUNTER_2		0xF4B0
> +#define	F367_QAM_CORR_CT_L		0xF4B000FF
> +
> +/* RS_COUNTER_3 */
> +#define	R367_QAM_RS_COUNTER_3		0xF4B1
> +#define	F367_QAM_CORR_CT_H		0xF4B100FF
> +
> +/* RS_COUNTER_4 */
> +#define	R367_QAM_RS_COUNTER_4		0xF4B2
> +#define	F367_QAM_UNCORR_CT_L		0xF4B200FF
> +
> +/* RS_COUNTER_5 */
> +#define	R367_QAM_RS_COUNTER_5		0xF4B3
> +#define	F367_QAM_UNCORR_CT_H		0xF4B300FF
> +
> +/* BERT_0 */
> +#define	R367_QAM_BERT_0		0xF4B4
> +#define	F367_QAM_RS_NOCORR		0xF4B40004
> +#define	F367_QAM_CT_HOLD		0xF4B40002
> +#define	F367_QAM_CT_CLEAR		0xF4B40001
> +
> +/* BERT_1 */
> +#define	R367_QAM_BERT_1		0xF4B5
> +#define	F367_QAM_BERT_ON		0xF4B50020
> +#define	F367_QAM_BERT_ERR_SRC		0xF4B50010
> +#define	F367_QAM_BERT_ERR_MODE		0xF4B50008
> +#define	F367_QAM_BERT_NBYTE		0xF4B50007
> +
> +/* BERT_2 */
> +#define	R367_QAM_BERT_2		0xF4B6
> +#define	F367_QAM_BERT_ERRCOUNT_L		0xF4B600FF
> +
> +/* BERT_3 */
> +#define	R367_QAM_BERT_3		0xF4B7
> +#define	F367_QAM_BERT_ERRCOUNT_H		0xF4B700FF
> +
> +/* OUTFORMAT_0 */
> +#define	R367_QAM_OUTFORMAT_0		0xF4B8
> +#define	F367_QAM_CLK_POLARITY		0xF4B80080
> +#define	F367_QAM_FEC_TYPE		0xF4B80040
> +#define	F367_QAM_SYNC_STRIP		0xF4B80008
> +#define	F367_QAM_TS_SWAP		0xF4B80004
> +#define	F367_QAM_OUTFORMAT		0xF4B80003
> +
> +/* OUTFORMAT_1 */
> +#define	R367_QAM_OUTFORMAT_1		0xF4B9
> +#define	F367_QAM_CI_DIVRANGE		0xF4B900FF
> +
> +/* SMOOTHER_2 */
> +#define	R367_QAM_SMOOTHER_2		0xF4BE
> +#define	F367_QAM_FIFO_BYPASS		0xF4BE0020
> +
> +/* TSMF_CTRL_0 */
> +#define	R367_QAM_TSMF_CTRL_0		0xF4C0
> +#define	F367_QAM_TS_NUMBER		0xF4C0001E
> +#define	F367_QAM_SEL_MODE		0xF4C00001
> +
> +/* TSMF_CTRL_1 */
> +#define	R367_QAM_TSMF_CTRL_1		0xF4C1
> +#define	F367_QAM_CHECK_ERROR_BIT		0xF4C10080
> +#define	F367_QAM_CHCK_F_SYNC		0xF4C10040
> +#define	F367_QAM_H_MODE		0xF4C10008
> +#define	F367_QAM_D_V_MODE		0xF4C10004
> +#define	F367_QAM_MODE		0xF4C10003
> +
> +/* TSMF_CTRL_3 */
> +#define	R367_QAM_TSMF_CTRL_3		0xF4C3
> +#define	F367_QAM_SYNC_IN_COUNT		0xF4C300F0
> +#define	F367_QAM_SYNC_OUT_COUNT		0xF4C3000F
> +
> +/* TS_ON_ID_0 */
> +#define	R367_QAM_TS_ON_ID_0		0xF4C4
> +#define	F367_QAM_TS_ID_L		0xF4C400FF
> +
> +/* TS_ON_ID_1 */
> +#define	R367_QAM_TS_ON_ID_1		0xF4C5
> +#define	F367_QAM_TS_ID_H		0xF4C500FF
> +
> +/* TS_ON_ID_2 */
> +#define	R367_QAM_TS_ON_ID_2		0xF4C6
> +#define	F367_QAM_ON_ID_L		0xF4C600FF
> +
> +/* TS_ON_ID_3 */
> +#define	R367_QAM_TS_ON_ID_3		0xF4C7
> +#define	F367_QAM_ON_ID_H		0xF4C700FF
> +
> +/* RE_STATUS_0 */
> +#define	R367_QAM_RE_STATUS_0		0xF4C8
> +#define	F367_QAM_RECEIVE_STATUS_L		0xF4C800FF
> +
> +/* RE_STATUS_1 */
> +#define	R367_QAM_RE_STATUS_1		0xF4C9
> +#define	F367_QAM_RECEIVE_STATUS_LH		0xF4C900FF
> +
> +/* RE_STATUS_2 */
> +#define	R367_QAM_RE_STATUS_2		0xF4CA
> +#define	F367_QAM_RECEIVE_STATUS_HL		0xF4CA00FF
> +
> +/* RE_STATUS_3 */
> +#define	R367_QAM_RE_STATUS_3		0xF4CB
> +#define	F367_QAM_RECEIVE_STATUS_HH		0xF4CB003F
> +
> +/* TS_STATUS_0 */
> +#define	R367_QAM_TS_STATUS_0		0xF4CC
> +#define	F367_QAM_TS_STATUS_L		0xF4CC00FF
> +
> +/* TS_STATUS_1 */
> +#define	R367_QAM_TS_STATUS_1		0xF4CD
> +#define	F367_QAM_TS_STATUS_H		0xF4CD007F
> +
> +/* TS_STATUS_2 */
> +#define	R367_QAM_TS_STATUS_2		0xF4CE
> +#define	F367_QAM_ERROR		0xF4CE0080
> +#define	F367_QAM_EMERGENCY		0xF4CE0040
> +#define	F367_QAM_CRE_TS		0xF4CE0030
> +#define	F367_QAM_VER		0xF4CE000E
> +#define	F367_QAM_M_LOCK		0xF4CE0001
> +
> +/* TS_STATUS_3 */
> +#define	R367_QAM_TS_STATUS_3		0xF4CF
> +#define	F367_QAM_UPDATE_READY		0xF4CF0080
> +#define	F367_QAM_END_FRAME_HEADER		0xF4CF0040
> +#define	F367_QAM_CONTCNT		0xF4CF0020
> +#define	F367_QAM_TS_IDENTIFIER_SEL		0xF4CF000F
> +
> +/* T_O_ID_0 */
> +#define	R367_QAM_T_O_ID_0		0xF4D0
> +#define	F367_QAM_ON_ID_I_L		0xF4D000FF
> +
> +/* T_O_ID_1 */
> +#define	R367_QAM_T_O_ID_1		0xF4D1
> +#define	F367_QAM_ON_ID_I_H		0xF4D100FF
> +
> +/* T_O_ID_2 */
> +#define	R367_QAM_T_O_ID_2		0xF4D2
> +#define	F367_QAM_TS_ID_I_L		0xF4D200FF
> +
> +/* T_O_ID_3 */
> +#define	R367_QAM_T_O_ID_3		0xF4D3
> +#define	F367_QAM_TS_ID_I_H		0xF4D300FF
> +
> +#endif


-- 

Cheers,
Mauro

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

* Re: [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-03  0:31 ` [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner Maik Broemme
@ 2013-11-03  9:56   ` Mauro Carvalho Chehab
  2013-11-03 17:00     ` Antti Palosaari
  0 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03  9:56 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List, Antti Palosaari

Hi Maik,

Em Sun, 3 Nov 2013 01:31:04 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added support for the NXP TDA18212 silicon tuner used by recent
> Digital Devices hardware. This will allow update of ddbridge driver
> to support newer devices.
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/dvb-frontends/Kconfig      |   9 +
>  drivers/media/dvb-frontends/Makefile     |   1 +
>  drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
>  drivers/media/dvb-frontends/tda18212dd.h |  37 ++

I'm not sure if support for this tuner is not provided already by one of
the existing drivers. If not, it is ok to submit a driver for it, but you
should just call it as tda18212.

I'm c/c Antti, as he worked on some NXP drivers recently, and may be aware
if a driver already supports TDA18212.

This is not a full review, as I can't review quickly code that is not
following the Linux Coding Style.

Yet, it points to some issues that I was able to notice on it.

Regards,
Mauro 

>  4 files changed, 981 insertions(+)
>  create mode 100644 drivers/media/dvb-frontends/tda18212dd.c
>  create mode 100644 drivers/media/dvb-frontends/tda18212dd.h
> 
> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> index 7cac015..a34c1c7 100644
> --- a/drivers/media/dvb-frontends/Kconfig
> +++ b/drivers/media/dvb-frontends/Kconfig
> @@ -65,6 +65,15 @@ config DVB_STV0367DD
>  
>            Say Y when you want to support this frontend.
>  
> +config DVB_TDA18212DD
> +	tristate "NXP TDA18212 silicon tuner (DD)"
> +	depends on DVB_CORE && I2C
> +	default m if DVB_FE_CUSTOMISE
> +	help
> +	  NXP TDA18212 silicon tuner (Digital Devices driver).
> +
> +	  Say Y when you want to support this tuner.
> +
>  comment "DVB-S (satellite) frontends"
>  	depends on DVB_CORE
>  
> diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
> index de100f1..ed12424 100644
> --- a/drivers/media/dvb-frontends/Makefile
> +++ b/drivers/media/dvb-frontends/Makefile
> @@ -98,6 +98,7 @@ obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
>  obj-$(CONFIG_DVB_DRXK) += drxk.o
>  obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
>  obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
> +obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
>  obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
>  obj-$(CONFIG_DVB_A8293) += a8293.o
>  obj-$(CONFIG_DVB_TDA10071) += tda10071.o
> diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c
> new file mode 100644
> index 0000000..3d2e04e
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/tda18212dd.c
> @@ -0,0 +1,934 @@
> +/*
> + *  tda18212dd.c: Driver for the TDA18212 tuner
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#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 <asm/div64.h>
> +
> +#include "dvb_frontend.h"
> +
> +#ifndef CHK_ERROR
> +    #define CHK_ERROR(s) if ((status = s) < 0) break
> +#endif

Don't do that. Using macros to do break/return is explicitly forbidden
at linux coding style. See Documentation/CodingStyle.

If you take a look on the git history for drx-k:
	$ git log --follow drivers/media/dvb-frontends/drxk_hard.c

you'll see that I fixed it there, using some perl scripts, on 
this changeset:

commit ea90f011fdcc3d4fde78532eab8af09637176765
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Sun Jul 3 18:06:07 2011 -0300

    [media] drxk: Remove the CHK_ERROR macro
    
    The CHK_ERROR macro does a flow control, violating chapter 12
    of the Documentation/CodingStyle. Doing flow controls inside
    macros is a bad idea, as it hides what's happening. It also
    hides the var "status" with is also a bad idea.
    
    The changes were done by this small perl script:
        my $blk=0;
        while (<>) {
                s /^\s+// if ($blk);
                $f =~ s/\s+$// if ($blk && /^\(/);
                $blk = 1 if (!m/\#/ && m/CHK_ERROR/);
                $blk=0 if ($blk && m/\;/);
                s/\n/ / if ($blk);
                $f.=$_;
        };
        $f=~ s,\n(\t+)CHK_ERROR\((.*)\)\;([^\n]*),\n\1status = \2;\3\n\1if (status < 0)\n\1\tbreak;,g;
        print $f;
    
    And manually fixed.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Eventually, the very same script could be useful for you.

Btw, I suggest you take a look at the cleanup patches for DRX-K, as
you'll likely need to to the same here.

> +
> +#define MASTER_PSM_AGC1     0
> +#define MASTER_AGC1_6_15dB  1
> +
> +#define SLAVE_PSM_AGC1      1
> +#define SLAVE_AGC1_6_15dB   0
> +
> +// 0 = 2 Vpp ... 2 = 1 Vpp,   7 = 0.5 Vpp

C99 comments is forbidden. Please review your code with 
script/checkpatch.pl to be sure that you're following our coding style.

> +#define IF_LEVEL_DVBC    2
> +#define IF_LEVEL_DVBT    2
> +
> +enum {
> +	ID_1                = 0x00,
> +	ID_2                = 0x01,
> +	ID_3                = 0x02,
> +	THERMO_1,
> +	THERMO_2,
> +	POWER_STATE_1,
> +	POWER_STATE_2,
> +	INPUT_POWER_LEVEL,
> +	IRQ_STATUS,
> +	IRQ_ENABLE,
> +	IRQ_CLEAR,
> +	IRQ_SET,
> +	AGC1_1,
> +	AGC2_1,
> +	AGCK_1,
> +	RF_AGC_1,
> +	IR_MIXER_1          = 0x10,
> +	AGC5_1,
> +	IF_AGC,
> +	IF_1,
> +	REFERENCE,
> +	IF_FREQUENCY_1,
> +	RF_FREQUENCY_1,
> +	RF_FREQUENCY_2,
> +	RF_FREQUENCY_3,
> +	MSM_1,
> +	MSM_2,
> +	PSM_1,
> +	DCC_1,
> +	FLO_MAX,
> +	IR_CAL_1,
> +	IR_CAL_2,
> +	IR_CAL_3            = 0x20,
> +	IR_CAL_4,
> +	VSYNC_MGT,
> +	IR_MIXER_2,
> +	AGC1_2,
> +	AGC5_2,
> +	RF_CAL_1,
> +	RF_CAL_2,
> +	RF_CAL_3,
> +	RF_CAL_4,
> +	RF_CAL_5,
> +	RF_CAL_6,
> +	RF_FILTER_1,
> +	RF_FILTER_2,
> +	RF_FILTER_3,
> +	RF_BAND_PASS_FILTER,
> +	CP_CURRENT          = 0x30,
> +	AGC_DET_OUT         = 0x31,
> +	RF_AGC_GAIN_1       = 0x32,
> +	RF_AGC_GAIN_2       = 0x33,
> +	IF_AGC_GAIN         = 0x34,
> +	POWER_1             = 0x35,
> +	POWER_2             = 0x36,
> +	MISC_1,
> +	RFCAL_LOG_1,
> +	RFCAL_LOG_2,
> +	RFCAL_LOG_3,
> +	RFCAL_LOG_4,
> +	RFCAL_LOG_5,
> +	RFCAL_LOG_6,
> +	RFCAL_LOG_7,
> +	RFCAL_LOG_8,
> +	RFCAL_LOG_9         = 0x40,
> +	RFCAL_LOG_10        = 0x41,
> +	RFCAL_LOG_11        = 0x42,
> +	RFCAL_LOG_12        = 0x43,
> +	REG_MAX,
> +};
> +
> +enum HF_Standard {

No CammelCase is allowed.

> +	HF_None=0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
> +	HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
> +	HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
> +	HF_DVBC_8MHZ, HF_DVBC
> +};
> +
> +struct SStandardParams {
> +	s32   m_IFFrequency;
> +	u32   m_BandWidth;
> +	u8    m_IF_1;         // FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3
> +	u8    m_IR_MIXER_2;   // 03 :6 HI_Pass:1 DC_Notch:1
> +	u8    m_AGC1_1;       // 0F :4 AGC1_Top:4
> +	u8    m_AGC2_1;       // 0F :4 AGC2_Top:4
> +	u8    m_RF_AGC_1_Low; // EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
> +	u8    m_RF_AGC_1_High;// EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
> +	u8    m_IR_MIXER_1;   // 0F :4 IR_mixer_Top:4
> +	u8    m_AGC5_1;       // 1F :3 AGC5_Ana AGC5_Top:4
> +	u8    m_AGCK_1;       // 0F :4 AGCK_Step:2 AGCK_Mode:2
> +	u8    m_PSM_1;        // 20 :2 PSM_StoB:1 :5
> +	bool  m_AGC1_Freeze;
> +	bool  m_LTO_STO_immune;
> +};
> +
> +#if 0
> +static struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] =

That "+1" looks weird... IMHO, what this code is trying to do is something like:

	static struct SStandardParams m_StandardTable[] = {
		{ some data },
		{ some data },
		{ some data },
		{ some data },
		{ 0 }
	};

If so, please do on the above way, explicitly showing that a "zero" element
at the end of the array is needed.

> +{
> +	{ 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_6MHZ
> +	{ 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_7MHZ
> +	{ 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_8MHZ
> +	{       0,       0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false },    // HF_DVBT (Unused)
> +	{ 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false },    // HF_ATSC
> +	{ 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_6MHZ
> +//    { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
> +//    { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
> +	{ 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
> +	{ 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
> +};
> +#else
> +static struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] =
> +{
> +     { 4000000, 6000000, 0x41, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_6MHZ
> +     { 4500000, 7000000, 0x42, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_7MHZ
> +     { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_8MHZ
> +     // ------------------------------
> +     {       0,       0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false },    // HF_DVBT (Unused)
> +     { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false },    // HF_ATSC
> +     { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_6MHZ
> +//    { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
> +//    { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
> +     { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
> +     { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
> +};
> +#endif
> +struct tda_state {
> +	struct i2c_adapter *i2c;
> +	u8 adr;
> +
> +	enum HF_Standard m_Standard;
> +	u32   m_Frequency;
> +	u32   IF;
> +
> +	bool    m_isMaster;
> +	bool    m_bPowerMeasurement;
> +	bool    m_bLTEnable;
> +	bool    m_bEnableFreeze;
> +
> +	u16   m_ID;
> +
> +	s32    m_SettlingTime;
> +
> +	u8    m_IFLevelDVBC;
> +	u8    m_IFLevelDVBT;
> +	u8    m_Regs[REG_MAX];
> +	u8    m_LastPowerLevel;
> +};
> +
> +static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
> +{
> +	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
> +				   .buf  = data, .len   = len}};
> +	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;

Error codes: just return the error code provided by Linux, instead of 
using any other error code convention.

> +}
> +
> +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) {
> +		printk("tda18212dd: i2c_read error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +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) {
> +		printk("tda18212: i2c_write error\n");
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int write_regs(struct tda_state *state,
> +		      u8 SubAddr, u8 *Regs, u16 nRegs)
> +{
> +	u8 data[nRegs+1];

Don't use dynamic arrays. This is evil, as the Kernel stack is too small,
and dynamic allocation disables the code that checks for the stack size at
compile time.

Instead, just use a fixed size, like:
	u8 data[80];

> +
> +	data[0] = SubAddr;
> +	memcpy(data + 1, Regs, nRegs);
> +	return i2c_write(state->i2c, state->adr, data, nRegs+1);
> +}
> +
> +static int write_reg(struct tda_state *state, u8 SubAddr,u8 Reg)
> +{
> +	u8 msg[2] = {SubAddr, Reg};
> +
> +	return i2c_write(state->i2c, state->adr, msg, 2);
> +}
> +
> +static int Read(struct tda_state *state, u8 * Regs)
> +{
> +	return i2c_readn(state->i2c, state->adr, Regs, REG_MAX);
> +}
> +
> +static int update_regs(struct tda_state *state, u8 RegFrom,u8 RegTo)
> +{
> +	return write_regs(state, RegFrom,
> +			  &state->m_Regs[RegFrom], RegTo-RegFrom+1);
> +}
> +
> +static int update_reg(struct tda_state *state, u8 Reg)
> +{
> +	return write_reg(state, Reg,state->m_Regs[Reg]);
> +}
> +
> +
> +static int read_regs(struct tda_state *state,
> +		    u8 SubAddr, u8 *Regs, u16 nRegs)
> +{
> +	return i2c_read(state->i2c, state->adr,
> +			&SubAddr, 1, Regs, nRegs);
> +}
> +
> +static int read_reg(struct tda_state *state,
> +		   u8 SubAddr, u8 *Reg)
> +{
> +	return i2c_read(state->i2c, state->adr,
> +			&SubAddr, 1, Reg, 1);
> +}
> +
> +static int read_reg1(struct tda_state *state, u8 Reg)
> +{
> +	return read_reg(state, Reg, &state->m_Regs[Reg]);
> +}
> +
> +static void init_state(struct tda_state *state)
> +{
> +    u32   ulIFLevelDVBC = IF_LEVEL_DVBC;
> +    u32   ulIFLevelDVBT = IF_LEVEL_DVBT;
> +    u32   ulPowerMeasurement = 1;
> +    u32   ulLTEnable = 1;
> +    u32   ulEnableFreeze = 0;
> +
> +    state->m_Frequency    = 0;
> +    state->m_isMaster = true;
> +    state->m_ID = 0;
> +    state->m_LastPowerLevel = 0xFF;
> +    state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07);
> +    state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07);
> +    state->m_bPowerMeasurement = (ulPowerMeasurement != 0);
> +    state->m_bLTEnable = (ulLTEnable != 0);
> +    state->m_bEnableFreeze = (ulEnableFreeze != 0);
> +}
> +
> +static int StartCalibration(struct tda_state *state)
> +{
> +	int  status = 0;
> +	do {
> +		state->m_Regs[POWER_2] &= ~0x02; // RSSI CK = 31.25 kHz
> +		CHK_ERROR(update_reg(state, POWER_2));
> +
> +		state->m_Regs[AGC1_2] = (state->m_Regs[AGC1_2] & ~0x60) | 0x40;    // AGC1 Do Step = 2
> +		CHK_ERROR(update_reg(state, AGC1_2));        // AGC
> +
> +		state->m_Regs[RF_FILTER_3] = (state->m_Regs[RF_FILTER_3] & ~0xC0) | 0x40;    // AGC2 Do Step = 1
> +		CHK_ERROR(update_reg(state, RF_FILTER_3));
> +
> +		state->m_Regs[AGCK_1] |= 0xC0; // AGCs Assym Up Step = 3      // Datasheet sets all bits to 1!
> +		CHK_ERROR(update_reg(state, AGCK_1));
> +
> +		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x60) | 0x40;    // AGCs Assym Do Step = 2
> +		CHK_ERROR(update_reg(state, AGC5_1));
> +
> +		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
> +		CHK_ERROR(update_reg(state, IRQ_CLEAR));
> +
> +		state->m_Regs[MSM_1] = 0x3B; // Set Calibration
> +		state->m_Regs[MSM_2] = 0x01; // Start MSM
> +		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
> +		state->m_Regs[MSM_2] = 0x00;
> +
> +	} while(0);
> +	return status;
> +}
> +
> +static int FinishCalibration(struct tda_state *state)
> +{
> +	int status = 0;
> +	u8 RFCal_Log[12];
> +
> +	do {
> +		u8 IRQ = 0;
> +		int Timeout = 150; // 1.5 s
> +		while(true) {
> +			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
> +			if ((IRQ & 0x80) != 0 )
> +				break;
> +			Timeout -= 1;
> +			if (Timeout == 0) {
> +				status = -1;
> +				break;
> +			}
> +			msleep(10);
> +		}
> +		CHK_ERROR(status);
> +
> +		state->m_Regs[FLO_MAX] = 0x0A;
> +		CHK_ERROR(update_reg(state, FLO_MAX));
> +
> +		state->m_Regs[AGC1_1] &= ~0xC0;
> +		if( state->m_bLTEnable ) state->m_Regs[AGC1_1] |= 0x80;    // LTEnable
> +
> +		state->m_Regs[AGC1_1] |= (state->m_isMaster ? MASTER_AGC1_6_15dB : SLAVE_AGC1_6_15dB ) << 6;
> +		CHK_ERROR(update_reg(state, AGC1_1));
> +
> +		state->m_Regs[PSM_1] &= ~0xC0;
> +		state->m_Regs[PSM_1] |= (state->m_isMaster ? MASTER_PSM_AGC1 : SLAVE_PSM_AGC1 ) << 6;
> +		CHK_ERROR(update_reg(state, PSM_1));
> +
> +		state->m_Regs[REFERENCE] |= 0x03; // XTOUT = 3
> +		CHK_ERROR(update_reg(state, REFERENCE));
> +
> +		CHK_ERROR(read_regs(state, RFCAL_LOG_1,RFCal_Log,sizeof(RFCal_Log)));
> +	} while(0);
> +	return status;
> +}
> +
> +static int PowerOn(struct tda_state *state)
> +{
> +	state->m_Regs[POWER_STATE_2] &= ~0x0F;
> +	update_reg(state, POWER_STATE_2);
> +	state->m_Regs[REFERENCE] |= 0x40;  // Digital clock source = Sigma Delta
> +	update_reg(state, REFERENCE);
> +	return 0;
> +}
> +
> +static int Standby(struct tda_state *state)
> +{
> +	int status = 0;
> +
> +	do {
> +		state->m_Regs[REFERENCE] &= ~0x40;  // Digital clock source = Quarz
> +		CHK_ERROR(update_reg(state, REFERENCE));
> +
> +		state->m_Regs[POWER_STATE_2] &= ~0x0F;
> +		state->m_Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E;
> +		CHK_ERROR(update_reg(state, POWER_STATE_2));
> +	} while(0);
> +	return status;
> +}
> +
> +static int attach_init(struct tda_state *state)
> +{
> +	int stat = 0;
> +	u8 Id[2];
> +	u8 PowerState = 0x00;
> +
> +	state->m_Standard = HF_None;
> +
> +	/* first read after cold reset sometimes fails on some cards,
> +	   try twice */
> +	stat = read_regs(state, ID_1, Id, sizeof(Id));
> +	stat = read_regs(state, ID_1, Id, sizeof(Id));
> +	if (stat < 0)
> +		return -1;
> +
> +	state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1];
> +	state->m_isMaster = ((Id[0] & 0x80) != 0);
> +	if( !state->m_isMaster )
> +		state->m_bLTEnable = false;
> +
> +	printk("tda18212dd: ChipID %04x\n", state->m_ID);
> +
> +	if( state->m_ID != 18212 )
> +		return -1;
> +
> +	stat = read_reg(state, POWER_STATE_1 ,&PowerState);
> +	if (stat < 0)
> +		return stat;
> +
> +	printk("tda18212dd: PowerState %02x\n", PowerState);
> +
> +	if (state->m_isMaster) {
> +		if( PowerState & 0x02 ) {
> +			// msleep for XTAL Calibration (on a PC this should be long done)
> +			u8 IRQStatus = 0;
> +			int Timeout = 10;
> +
> +			while(Timeout > 0) {
> +				read_reg(state, IRQ_STATUS, &IRQStatus);
> +				if (IRQStatus & 0x20)
> +					break;
> +				Timeout -= 1;
> +				msleep(10);
> +			}
> +			if( (IRQStatus & 0x20) == 0 ) {
> +				stat = -ETIMEDOUT;
> +			}
> +		}
> +	} else {
> +		write_reg(state, FLO_MAX, 0x00);
> +		write_reg(state, CP_CURRENT,0x68);
> +	}
> +	Read(state, state->m_Regs);
> +
> +	PowerOn(state);
> +	StartCalibration(state);
> +	FinishCalibration(state);
> +	Standby(state);
> +	return stat;
> +}
> +
> +static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel)
> +{
> +	int status = 0;
> +
> +	do {
> +		u8 IRQ = 0;
> +		int Timeout = 70; // 700 ms
> +
> +		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
> +		CHK_ERROR(update_reg(state, IRQ_CLEAR));
> +
> +		state->m_Regs[MSM_1] = 0x80; // power measurement
> +		state->m_Regs[MSM_2] = 0x01; // Start MSM
> +		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
> +		state->m_Regs[MSM_2] = 0x00;
> +
> +		while(true) {
> +			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
> +			if( (IRQ & 0x80) != 0 )
> +				break;
> +			Timeout -= 1;
> +			if( Timeout == 0 )
> +			{
> +				status = -1;
> +				break;
> +			}
> +			msleep(10);
> +		}
> +		CHK_ERROR(status);
> +
> +		CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL));
> +		*pPowerLevel = state->m_Regs[INPUT_POWER_LEVEL] & 0x7F;
> +
> +
> +		if( *pPowerLevel > 110 ) *pPowerLevel = 110;
> +	} while(0);
> +	/* printk("PL %d\n", *pPowerLevel); */
> +	return status;
> +}
> +
> +static int SetFrequency(struct tda_state *state, u32 Frequency, enum HF_Standard Standard)
> +{
> +	int status = 0;
> +	struct SStandardParams *StandardParams;
> +	u32   f = Frequency / 1000;
> +	u8 IRQ = 0;
> +	int Timeout = 25; // 250 ms
> +	u32 fRatio = Frequency / 16000000;
> +	u32 fDelta = Frequency - fRatio * 16000000;
> +
> +	if( Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ )
> +		return -EINVAL;
> +	StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ];
> +
> +	if( StandardParams->m_IFFrequency == 0 )
> +		return -EINVAL;
> +	state->m_Standard = HF_None;
> +	state->m_Frequency = 0;
> +
> +	do {
> +		// IF Level
> +		state->m_Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? state->m_IFLevelDVBC : state->m_IFLevelDVBT;
> +		CHK_ERROR(update_reg(state, IF_AGC));
> +
> +		// ---------------------------------------------------------------------------------
> +		// Standard setup
> +
> +		state->m_Regs[IF_1] = StandardParams->m_IF_1;
> +		CHK_ERROR(update_reg(state, IF_1));
> +
> +		state->m_Regs[IR_MIXER_2] = (state->m_Regs[IR_MIXER_2] & ~0x03) | StandardParams->m_IR_MIXER_2;
> +		CHK_ERROR(update_reg(state, IR_MIXER_2));
> +
> +		state->m_Regs[AGC1_1] = (state->m_Regs[AGC1_1] & ~0x0F) | StandardParams->m_AGC1_1;
> +		CHK_ERROR(update_reg(state, AGC1_1));
> +
> +		state->m_Regs[AGC2_1] = (state->m_Regs[AGC2_1] & ~0x0F) | StandardParams->m_AGC2_1;
> +		CHK_ERROR(update_reg(state, AGC2_1));
> +
> +		state->m_Regs[RF_AGC_1] &= ~0xEF;
> +		if( Frequency < 291000000 )
> +			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low;
> +		else
> +			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_High;
> +		CHK_ERROR(update_reg(state, RF_AGC_1));
> +
> +		state->m_Regs[IR_MIXER_1] = (state->m_Regs[IR_MIXER_1] & ~0x0F) | StandardParams->m_IR_MIXER_1;
> +		CHK_ERROR(update_reg(state, IR_MIXER_1));
> +
> +		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x1F) | StandardParams->m_AGC5_1;
> +		CHK_ERROR(update_reg(state, AGC5_1));
> +
> +		state->m_Regs[AGCK_1] = (state->m_Regs[AGCK_1] & ~0x0F) | StandardParams->m_AGCK_1;
> +		CHK_ERROR(update_reg(state, AGCK_1));
> +
> +		state->m_Regs[PSM_1] = (state->m_Regs[PSM_1] & ~0x20) | StandardParams->m_PSM_1;
> +		CHK_ERROR(update_reg(state, PSM_1));
> +
> +		state->m_Regs[IF_FREQUENCY_1] = ( StandardParams->m_IFFrequency / 50000 );
> +		CHK_ERROR(update_reg(state, IF_FREQUENCY_1));
> +
> +		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
> +		{
> +			u8 tmp;
> +			u8 RF_Filter_Gain;
> +
> +			CHK_ERROR(read_reg(state, RF_AGC_GAIN_1,&tmp));
> +			RF_Filter_Gain = (tmp & 0x30) >> 4;
> +
> +			state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
> +			CHK_ERROR(update_reg(state, RF_FILTER_1));
> +
> +			state->m_Regs[RF_FILTER_1] |= 0x10;    // Force
> +			CHK_ERROR(update_reg(state, RF_FILTER_1));
> +
> +			while( RF_Filter_Gain != 0 )
> +			{
> +				RF_Filter_Gain -= 1;
> +				state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
> +				CHK_ERROR(update_reg(state, RF_FILTER_1));
> +				msleep(10);
> +			}
> +			CHK_ERROR(status);
> +
> +			state->m_Regs[RF_AGC_1] |=  0x08;
> +			CHK_ERROR(update_reg(state, RF_AGC_1));
> +		}
> +
> +		// ---------------------------------------------------------------------------------
> +
> +		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
> +		CHK_ERROR(update_reg(state, IRQ_CLEAR));
> +
> +		CHK_ERROR(PowerOn(state));
> +
> +		state->m_Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF);
> +		state->m_Regs[RF_FREQUENCY_2] = ((f >>  8) & 0xFF);
> +		state->m_Regs[RF_FREQUENCY_3] = ((f      ) & 0xFF);
> +		CHK_ERROR(update_regs(state, RF_FREQUENCY_1,RF_FREQUENCY_3));
> +
> +		state->m_Regs[MSM_1] = 0x41; // Tune
> +		state->m_Regs[MSM_2] = 0x01; // Start MSM
> +		CHK_ERROR(update_regs(state, MSM_1, MSM_2));
> +		state->m_Regs[MSM_2] = 0x00;
> +
> +		while(true)
> +		{
> +			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
> +			if( (IRQ & 0x80) != 0 ) break;
> +			Timeout -= 1;
> +			if (Timeout == 0) {
> +				status = -1;
> +				break;
> +			}
> +			msleep(10);
> +		}
> +		CHK_ERROR(status);
> +
> +		// ---------------------------------------------------------------------------------
> +
> +		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
> +		{
> +			state->m_Regs[RF_AGC_1] &=  ~0x08;
> +			CHK_ERROR(update_reg(state, RF_AGC_1));
> +
> +			msleep(50);
> +
> +			state->m_Regs[RF_FILTER_1] &= ~0x10;    // remove force
> +			CHK_ERROR(update_reg(state, RF_FILTER_1));
> +		}
> +
> +		// ---------------------------------------------------------------------------------
> +		//  Spur reduction
> +
> +		if( Frequency < 72000000 )
> +		{
> +			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
> +		}
> +		else if( Frequency < 104000000 )
> +		{
> +			state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
> +		}
> +		else if( Frequency < 120000000 )
> +		{
> +			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
> +		}
> +		else
> +		{
> +			if( fDelta <= 8000000 )
> +			{
> +				if( fRatio & 1 ) state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
> +				else             state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
> +			}
> +			else
> +			{
> +				if( fRatio & 1 ) state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
> +				else             state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
> +			}
> +
> +		}
> +		CHK_ERROR(update_reg(state, REFERENCE));
> +
> +		if( StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze )
> +		{
> +			u8 tmp;
> +			int AGC1GainMin = 0;
> +			int nSteps = 10;
> +			int Step  = 0;
> +
> +			CHK_ERROR(read_reg(state, AGC1_2,&tmp));
> +
> +			if( (tmp & 0x80) == 0 )
> +			{
> +				state->m_Regs[AGC1_2] |= 0x80;         // Loop off
> +				CHK_ERROR(update_reg(state, AGC1_2));
> +				state->m_Regs[AGC1_2] |= 0x10 ;        // Force gain
> +				CHK_ERROR(update_reg(state, AGC1_2));
> +			}
> +			// Adapt
> +			if( state->m_Regs[AGC1_1] & 0x40 ) // AGC1_6_15dB set
> +			{
> +				AGC1GainMin = 6;
> +				nSteps = 4;
> +			}
> +			while( Step < nSteps )
> +			{
> +				int Down = 0;
> +				int Up = 0, i;
> +				u8 AGC1_Gain;
> +
> +				Step = Step + 1;
> +
> +				for (i = 0; i < 40; i += 1) {
> +					CHK_ERROR(read_reg(state, AGC_DET_OUT, &tmp));
> +					Up   += (tmp & 0x02) ?  1 : -4;
> +					Down += (tmp & 0x01) ? 14 : -1;
> +					msleep(1);
> +				}
> +				CHK_ERROR(status);
> +				AGC1_Gain = (state->m_Regs[AGC1_2] & 0x0F);
> +				if( Up >= 15 && AGC1_Gain != 9 )
> +				{
> +					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain + 1);
> +					CHK_ERROR(update_reg(state, AGC1_2));
> +				}
> +				else if ( Down >= 10 && AGC1_Gain != AGC1GainMin )
> +				{
> +					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain - 1);
> +					CHK_ERROR(update_reg(state, AGC1_2));
> +				}
> +				else
> +				{
> +					Step = nSteps;
> +				}
> +			}
> +		}
> +		else
> +		{
> +			state->m_Regs[AGC1_2] &= ~0x10 ;       // unforce gain
> +			CHK_ERROR(update_reg(state, AGC1_2));
> +			state->m_Regs[AGC1_2] &= ~0x80;         // Loop on
> +			CHK_ERROR(update_reg(state, AGC1_2));
> +		}
> +
> +		state->m_Standard = Standard;
> +		state->m_Frequency = Frequency;
> +
> +		if( state->m_bPowerMeasurement )
> +			PowerMeasurement(state, &state->m_LastPowerLevel);
> +	} while(0);
> +
> +	return status;
> +}
> +
> +static int sleep(struct dvb_frontend* fe)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +
> +	Standby(state);
> +	return 0;
> +}
> +
> +static int init(struct dvb_frontend* fe)
> +{
> +	//struct tda_state *state = fe->tuner_priv;
> +	return 0;
> +}
> +
> +static int release(struct dvb_frontend* fe)
> +{
> +	kfree(fe->tuner_priv);
> +	fe->tuner_priv = NULL;
> +	return 0;
> +}
> +
> +#ifndef USE_API3

Why do you need this? Both "set_params" look identical.

> +static int set_params(struct dvb_frontend *fe)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
> +	int status = 0;
> +	int Standard;
> +	u32 bw;
> +
> +	bw = (p->bandwidth_hz + 999999) / 1000000;
> +	state->m_Frequency = p->frequency;
> +	if (p->delivery_system == SYS_DVBT ||
> +	    p->delivery_system == SYS_DVBT2 ||
> +	    p->delivery_system == SYS_ISDBT ||
> +	    p->delivery_system == SYS_DVBC2) {
> +		switch (bw) {
> +		case 6:
> +			Standard = HF_DVBT_6MHZ;
> +			break;
> +		case 7:
> +			Standard = HF_DVBT_7MHZ;
> +			break;
> +		default:
> +		case 8:
> +			Standard = HF_DVBT_8MHZ;
> +			break;
> +		}
> +	} else if (p->delivery_system == SYS_DVBC_ANNEX_A) {
> +		switch (bw) {
> +		case 6:
> +			Standard = HF_DVBC_6MHZ;
> +			break;
> +		case 7:
> +			Standard = HF_DVBC_7MHZ;
> +			break;
> +		default:
> +		case 8:
> +			Standard = HF_DVBC_8MHZ;
> +			break;
> +		}
> +	} else
> +		return -EINVAL;
> +
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 1);
> +	SetFrequency(state, state->m_Frequency, Standard);
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 0);
> +
> +	return status;
> +}
> +#else
> +static int set_params(struct dvb_frontend *fe,
> +		      struct dvb_frontend_parameters *params)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +	int status = 0;
> +	int Standard;
> +
> +	state->m_Frequency = params->frequency;
> +
> +	if (fe->ops.info.type == FE_OFDM)
> +		switch (params->u.ofdm.bandwidth) {
> +		case BANDWIDTH_6_MHZ:
> +			Standard = HF_DVBT_6MHZ;
> +			break;
> +		case BANDWIDTH_7_MHZ:
> +			Standard = HF_DVBT_7MHZ;
> +			break;
> +		default:
> +		case BANDWIDTH_8_MHZ:
> +			Standard = HF_DVBT_8MHZ;
> +			break;
> +		}
> +	else if (fe->ops.info.type == FE_QAM) {
> +		Standard = HF_DVBC_8MHZ;
> +	} else
> +		return -EINVAL;
> +
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 1);
> +	SetFrequency(state, state->m_Frequency, Standard);
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 0);
> +
> +	return status;
> +}
> +#endif
> +
> +static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +
> +	*frequency = state->IF;
> +	return 0;
> +}
> +
> +static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +
> +	*st = state->m_LastPowerLevel;
> +	return 0;
> +}
> +
> +static int get_if(struct dvb_frontend *fe, u32 *frequency)
> +{
> +	struct tda_state *state = fe->tuner_priv;
> +
> +	state->IF = 0;
> +	if (state->m_Standard < HF_DVBT_6MHZ ||
> +	    state->m_Standard > HF_DVBC_8MHZ)
> +		return 0;
> +	state->IF = m_StandardTable[state->m_Standard - HF_DVBT_6MHZ].m_IFFrequency;
> +	*frequency = state->IF;
> +	return 0;
> +}
> +
> +static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
> +{
> +	//struct tda_state *state = fe->tuner_priv;
> +	//*bandwidth = priv->bandwidth;
> +	return 0;
> +}
> +
> +
> +static struct dvb_tuner_ops tuner_ops = {
> +	.info = {
> +		.name = "NXP TDA18212",
> +		.frequency_min  =  47125000,
> +		.frequency_max  = 865000000,
> +		.frequency_step =     62500
> +	},
> +	.init              = init,
> +	.sleep             = sleep,
> +	.set_params        = set_params,
> +	.release           = release,
> +	.get_frequency     = get_frequency,
> +	.get_if_frequency  = get_if,
> +	.get_bandwidth     = get_bandwidth,
> +	.get_rf_strength   = get_rf_strength,
> +};
> +
> +struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
> +				       struct i2c_adapter *i2c, u8 adr)
> +{
> +	struct tda_state *state;
> +	int stat;
> +
> +	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
> +	if (!state)
> +		return NULL;
> +	state->adr = adr;
> +	state->i2c = i2c;
> +	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
> +	init_state(state);
> +
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 1);
> +	stat = attach_init(state);
> +	if (fe->ops.i2c_gate_ctrl)
> +		fe->ops.i2c_gate_ctrl(fe, 0);
> +	if (stat < 0) {
> +		kfree(state);
> +		return 0;
> +	}
> +	fe->tuner_priv = state;
> +	return fe;
> +}
> +
> +EXPORT_SYMBOL_GPL(tda18212dd_attach);
> +MODULE_DESCRIPTION("TDA18212 driver");
> +MODULE_AUTHOR("DD");
> +MODULE_LICENSE("GPL");

> +
> +/*
> + * Local variables:
> + * c-basic-offset: 8
> + * End:
> + */

Don't add editor-specific macros.

> diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h
> new file mode 100644
> index 0000000..e276eff
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/tda18212dd.h
> @@ -0,0 +1,37 @@
> +/*
> + *  tda18212dd.h: Driver for the TDA18212 tuner
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#ifndef _TDA18212DD_H_
> +#define _TDA18212DD_H_
> +
> +#if IS_ENABLED(CONFIG_DVB_TDA18212DD)
> +struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
> +				       struct i2c_adapter *i2c, u8 adr);
> +#else
> +static inline struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
> +						     struct i2c_adapter *i2c, u8 adr);
> +{
> +        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
> +        return NULL;
> +}
> +#endif
> +
> +#endif


-- 

Cheers,
Mauro

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

* Re: [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
  2013-11-03  0:32 ` [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2 Maik Broemme
@ 2013-11-03 10:11   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:11 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:32:52 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added support for the CXD2843ER demodulator for DVB-T/T2/C/C2
> used by recent Digital Devices hardware.

The same CodingStyle issues I pointed on patch 4/12 also applies here.
I also noticed that on some places, the indent is not correct. Please
fix.

Let me point a few other stuff I noticed here.

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/dvb-frontends/Kconfig   |    9 +
>  drivers/media/dvb-frontends/Makefile  |    1 +
>  drivers/media/dvb-frontends/cxd2843.c | 1647 +++++++++++++++++++++++++++++++++
>  drivers/media/dvb-frontends/cxd2843.h |   47 +
>  4 files changed, 1704 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 a34c1c7..3e39319 100644
> --- a/drivers/media/dvb-frontends/Kconfig
> +++ b/drivers/media/dvb-frontends/Kconfig
> @@ -74,6 +74,15 @@ config DVB_TDA18212DD
>  
>  	  Say Y when you want to support this tuner.
>  
> +config DVB_CXD2843
> +	tristate "CXD2843ER based for DVB-T/T2/C/C2"
> +	depends on DVB_CORE && I2C
> +	default m if DVB_FE_CUSTOMISE
> +	help
> +	  Sony CXD2843ER/CXD2837ER DVB-T/T2/C/C2 demodulator.
> +
> +	  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 ed12424..90cad36 100644
> --- a/drivers/media/dvb-frontends/Makefile
> +++ b/drivers/media/dvb-frontends/Makefile
> @@ -99,6 +99,7 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o
>  obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
>  obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
>  obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
> +obj-$(CONFIG_DVB_CXD2843) += cxd2843.o
>  obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
>  obj-$(CONFIG_DVB_A8293) += a8293.o
>  obj-$(CONFIG_DVB_TDA10071) += tda10071.o
> diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
> new file mode 100644
> index 0000000..87a3000
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/cxd2843.c
> @@ -0,0 +1,1647 @@
> +/*
> + *  cxd2843.c: 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) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#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"
> +
> +
> +enum EDemodType { CXD2843, CXD2837, CXD2838 };
> +enum EDemodState { Unknown, Shutdown, Sleep, ActiveT, ActiveT2, ActiveC, ActiveC2, ActiveIT };
> +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 omode omode;
> +
> +	u8    IF_FS;
> +	int   ContinuousClock;
> +	int   SerialMode;
> +	u8    SerialClockFrequency;
> +	
> +	u32   LockTimeout;
> +	u32   TSLockTimeout;
> +	u32   L1PostTimeout;
> +	u32   DataSliceID;	
> +	int   FirstTimeLock;
> +	u32   PLPNumber;
> +	u32   last_status;
> +	
> +	u32 bandwidth;
> +	u32 bw;
> +};
> +
> +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) {
> +		printk("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) {
> +		printk("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 FreezeRegsT(struct cxd_state *cxd)
> +{
> +	mutex_lock(&cxd->mutex);
> +	return writereg(cxd, cxd->adrt, 1, 1);
> +}
> +
> +static int UnFreezeRegsT(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;
> +}
> +
> +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 // This looks broken (see enable)
> +        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 // This looks broken (see enable)
> +        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 // This looks broken (see enable)
> +        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;
> +
> +       ///* OSERCKMODE  OSERDUTYMODE  OTSCKPERIOD  OREG_CKSEL_TSIF                            */
> +       // {      1,          1,            8,             0        }, /* High Freq, full rate */
> +       // {      1,          1,            8,             1        }, /* Mid Freq,  full rate */
> +       // {      1,          1,            8,             2        }, /* Low Freq,  full rate */
> +       // {      2,          2,            16,            0        }, /* High Freq, half rate */
> +       // {      2,          2,            16,            1        }, /* Mid Freq,  half rate */
> +       // {      2,          2,            16,            2        }  /* Low Freq,  half rate */
> +
> +        u8 OSERCKMODE = 1;
> +        u8 OSERDUTYMODE = 1;
> +        u8 OTSCKPERIOD = 8;
> +        u8 OREG_CKSEL_TSIF = state->SerialClockFrequency;
> +	
> +        if (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
> +        writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); // OREG_CKSEL_TSIF
> +        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) {
> +	case 8:
> +	{
> +		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		static u8 CL_data[] = { 0x01, 0xE0 };
> +		static u8 NF_data[] = { 0x01, 0x02 };
> +		
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
> +		break;
> +	}
> +	case 7:
> +	{
> +		static u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
> +		static u8 CL_data[] = { 0x12, 0xF8 };
> +		static u8 NF_data[] = { 0x00, 0x03 };
> +		
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x02,0x07);   // System Bandwidth
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
> +		break;
> +	}
> +	case 6:
> +	{
> +		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		static u8 CL_data[] = { 0x1F, 0xDC };
> +		static u8 NF_data[] = { 0x00, 0x03 };
> +
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
> +		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));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		
> +		writebitst(state, 0x10,0xD7,0x06,0x07);   // System Bandwidth
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +		writeregst(state, 0x17,0x38,NF_data,sizeof(NF_data));   // notch filter 
> +                break;
> +	}
> +	}
> +}
> +
> +static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq)
> +{
> +	printk("%s\n", __FUNCTION__);
> +
> +        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
> +	
> +        // -- till here identical to DVB-C (apart from mode)
> +	
> +        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);
> +
> +        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:
> +	{
> +		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
> +	}
> +	break;
> +	case 7:
> +	{
> +		static u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x02,0x07);   // System Bandwidth
> +	}
> +	break;
> +	case 6:
> +	{
> +		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
> +	}
> +	break;
> +	case 5:
> +	{
> +		static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x06,0x07);   // System Bandwidth
> +	}
> +	break;
> +	case 1: // 1.7 MHz

That looks weird on my eyes... it seems better to not divide the bw by 1000000,
and check for 1700000 here, instead of checking for just "1" for 1.7 MHz. 

> +	{
> +		static u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC };
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +
> +		writebitst(state, 0x10,0xD7,0x03,0x07);   // System Bandwidth
> +	}
> +	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
> +        }

Why the braces?

> +        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);
> +
> +        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);   // iffreq
> +}
> +
> +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);
> +
> +        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) {
> +	case 8:
> +	{
> +		static u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
> +		static u8 data[2] = { 0x11, 0x9E };
> +
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +
> +		writebitst(state, 0x10,0xD7,0x00,0x07);   // System Bandwidth
> +		
> +		writeregst(state, 0x50,0xEC,data,sizeof(data));   // timeout
> +		writeregt(state, 0x50,0xEF,0x11);
> +		writeregt(state, 0x50,0xF1,0x9E);
> +	}
> +	break;
> +	case 6:
> +	{
> +		static u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
> +		static u8 data[2] = { 0x17, 0x70 };
> +
> +		writeregst(state, 0x20,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		writebitst(state, 0x10,0xD7,0x04,0x07);   // System Bandwidth
> +		
> +		writeregst(state, 0x50,0xEC,data,sizeof(data));   // timeout
> +		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:
> +	{
> +		static u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 };   // 20.5/41
> +		static u8 CL_data[] = { 0x15, 0xA8 };
> +
> +		// static u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 };  // 24
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		
> +		writeregt(state, 0x10,0xD7,0x00);   // System Bandwidth
> +		//static u8 CL_data[] = { 0x13, 0xFC };
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +	}
> +	break;
> +	case 7:
> +	{
> +		static u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 };
> +		static u8 CL_data[] = { 0x1B, 0x5D };
> +
> +		//static u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 };
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		
> +		writeregt(state, 0x10,0xD7,0x02);   // System Bandwidth
> +		//static u8 CL_data[] = { 0x1A, 0xFA };
> +		writeregst(state, 0x10,0xD9,CL_data,sizeof(CL_data));   // core latency 
> +	}
> +	break;
> +	case 6:
> +	{
> +		static u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 };
> +		static u8 CL_data[] = { 0x1F, 0xEC };
> +		//static u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 };
> +		//static u8 CL_data[] = { 0x1F, 0x79 };
> +		
> +		writeregst(state, 0x10,0x9F,TR_data,sizeof(TR_data));   // Timing recovery
> +		// Add EQ Optimisation for tuner here
> +		writeregst(state, 0x10,0xB6,IF_data,sizeof(IF_data));   // iffreq
> +		
> +		writeregt(state, 0x10,0xD7,0x04);   // System Bandwidth
> +		writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data));   // core latency 
> +	}
> +	break;
> +        }
> +}
> +
> +static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq)
> +{
> +	static u8 data2[3] = { 0xB9,0xBA,0x63 };  // 20.5/41 MHz
> +        //static u8 data2[3] = { 0xB7,0x1B,0x00 };  // 24 MHz
> +        static u8 TSIF_data[2] = { 0x61,0x60 } ; // 20.5/41 MHz
> +        //static u8 TSIF_data[2] = { 0x60,0x00 } ; // 24 MHz
> +
> +	printk("%s\n", __FUNCTION__);
> +
> +        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
> +	
> +        //u8 Profile = 0x05;       // Lite
> +        //u8 notT2time = 40;
> +	
> +        //u8 Profile = 0x00;       // Any
> +        //u8 notT2time = 40;
> +	
> +	
> +        if (state->PLPNumber != 0xffffffff) {
> +		writeregt(state, 0x23, 0xAF, state->PLPNumber);
> +		writeregt(state, 0x23, 0xAD, 0x01);
> +	} else {
> +		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;
> +
> +	printk("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->PLPNumber & 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->FirstTimeLock = 1;
> +	
> +	if (state->state == newDemodState ) {
> +		writeregt(state, 0x00, 0xC3, 0x01);   /* Disable TS Output */
> +		switch (newDemodState) {
> +		case ActiveT:  
> +			writeregt(state, 0x10,0x67, 0x00);  /* Stick with HP ( 0x01 = LP ) */
> +			BandSettingT(state, iffreq);  
> +			break;
> +		case ActiveT2: 
> +			T2_SetParameters(state);
> +			BandSettingT2(state, iffreq);
> +			break;
> +		case ActiveC:
> +			BandSettingC(state, iffreq);
> +			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:  
> +			writeregt(state, 0x10,0x67, 0x00);  // Stick with HP ( 0x01 = LP )
> +			Sleep_to_ActiveT(state, iffreq);  
> +			break;
> +		case ActiveT2: 
> +			T2_SetParameters(state);
> +			Sleep_to_ActiveT2(state, iffreq);
> +			break;
> +		case ActiveC:  
> +			Sleep_to_ActiveC(state, iffreq);
> +			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;

Why don't you just do "state->omode = delivery_system" and remove this
enum?

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

Btw, that code that checks for 1.7MHz will not work, as you're actually
rounding 1.7 to "2" on the above.

> +	state->DataSliceID = 0;//fe->dtv_property_cache.slice_id;
> +	state->PLPNumber = fe->dtv_property_cache.stream_id;
> +	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);
> +	msleep(4);
> +	writeregx(state, 0x00, 0x10, 0x01);
> +        
> +	writeregsx(state, 0x00, 0x13, data, 2);
> +        writeregx(state, 0x00, 0x10, 0x00);
> +        msleep(2);
> +        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, 0x80, 0x98);
> +        writebitst(state, 0x00, 0xC5, 0x00, 0x07);
> +        writebitst(state, 0x00, 0xCB, 0x00, 0x01);
> +        writebitst(state, 0x00, 0xC6, 0x00, 0x1D);
> +        writebitst(state, 0x00, 0xC8, 0x00, 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 = 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;
> +	state->IF_FS = 0x50; // IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V 
> +}
> +
> +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;
> +	}

The above looks weird... it is jus returning -EINVAL on all cases.

> +}
> +
> +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 read_ber(struct dvb_frontend *fe, u32 *ber)
> +{
> +	//struct cxd_state *state = fe->demodulator_priv;
> +
> +	*ber = 0;
> +	return 0;
> +}

Just don't implement it, if you don't support.

> +
> +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)

We have already code for doing log10 calculus at the dvb core. Please
reuse it.

> +{
> +	static u32 LookupTable[100] = {
> +		101157945, 103514217, 105925373, 108392691, 110917482,
> +		113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5
> +		127350308, 130316678, 133352143, 136458314, 139636836,
> +		142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
> +		160324539, 164058977, 167880402, 171790839, 175792361,
> +		179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
> +		201836636, 206538016, 211348904, 216271852, 221309471,
> +		226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
> +		254097271, 260015956, 266072506, 272270131, 278612117,
> +		285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
> +		319889511, 327340695, 334965439, 342767787, 350751874,
> +		358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
> +		402717034, 412097519, 421696503, 431519077, 441570447,
> +		451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
> +		506990708, 518800039, 530884444, 543250331, 555904257,
> +		568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
> +		638263486, 653130553, 668343918, 683911647, 699841996,
> +		716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
> +		803526122, 822242650, 841395142, 860993752, 881048873,
> +		901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
> +	};
> +	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)
> +{

Why to comment it?

> +	u8 nPids = 0;
> +	
> +	*Returned = 0;
> +	if (state->state != ActiveT2 )
> +		return;
> +	if (state->last_status != 0x1f)
> +		return;
> +	
> +	FreezeRegsT(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;
> +	
> +	UnFreezeRegsT(state);
> +}
> +#endif
> +
> +static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise)
> +{
> +	u8 Data[2];
> +	u32 reg;
> +        
> +	FreezeRegsT(state);
> +	readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data));
> +	UnFreezeRegsT(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;
> +        
> +	FreezeRegsT(state);
> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
> +	UnFreezeRegsT(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;
> +        
> +	FreezeRegsT(state);
> +	readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data));
> +	UnFreezeRegsT(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;
> +
> +	FreezeRegsT(state);
> +	readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data));
> +	UnFreezeRegsT(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;
> +	
> +	FreezeRegsT(state);
> +	readregst_unlocked(state, 0x40, 0x19, &Constellation, 1);
> +	readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data));
> +	UnFreezeRegsT(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;
> +}

Please implement it as a DVBv5 stats.

> +
> +static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
> +{
> +	*ucblocks = 0;
> +	return 0;
> +}

If frontend doesn't support, just don't implement it.

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

-1 is the wrong error code here. -ENODEV is likely the proper one.

> +	}

IMHO, the better is to add a printk info message, saying what chip
got detected.

> +	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;
> +	}
> +	printk("cxd2843: not found\n");
> +	kfree(state);
> +	return NULL;
> +}
> +
> +MODULE_DESCRIPTION("CXD2843/37/38 driver");
> +MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
> +MODULE_LICENSE("GPL");
> +
> +EXPORT_SYMBOL(cxd2843_attach);
> +
> diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h
> new file mode 100644
> index 0000000..b6bbc90
> --- /dev/null
> +++ b/drivers/media/dvb-frontends/cxd2843.h
> @@ -0,0 +1,47 @@
> +/*
> + *  cxd2843.h: 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) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#ifndef _CXD2843_H_
> +#define _CXD2843_H_
> +
> +#include <linux/types.h>
> +#include <linux/i2c.h>
> +
> +struct cxd2843_cfg {
> +	u8  adr;
> +	u32 ts_clock;
> +};
> +
> +#if IS_ENABLED(CONFIG_DVB_CXD2843)
> +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);
> +{
> +	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
> +	return NULL;
> +}
> +#endif
> +
> +#endif


-- 

Cheers,
Mauro

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

* Re: [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants
  2013-11-03  0:33 ` [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants Maik Broemme
@ 2013-11-03 10:16   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:16 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:33:54 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added EXPORT_SYMBOL(dvb_usercopy) to allow new ddbridge driver to
> use it. It is questionable if I should use it in this way or not.
> If not I will fix it.

I don't like the idea of doing that. This likely means that ddbridge
is needing to do something else. The better is to add core support for
that, if pertinent, instead of moving the code to ddbridge.

> 
> Added two new DVB device constants DVB_DEVICE_CI and DVB_DEVICE_MOD
> required by newer ddbridge driver. Again it is questionable to use
> them or modify ddbridge driver.

Why those new types are needed? How those are used?

It could be needed, but then you should document them at DocBook.

It is probably better to open a separate thread to discuss those API
changes in separate (DVB C2 properties and those two new types of
devices).

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/dvb-core/dvbdev.c | 1 +
>  drivers/media/dvb-core/dvbdev.h | 2 ++
>  2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index 401ef64..e451e9e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -438,6 +438,7 @@ out:
>  	kfree(mbuf);
>  	return err;
>  }
> +EXPORT_SYMBOL(dvb_usercopy);
>  
>  static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
>  {
> diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
> index 93a9470..016c46e 100644
> --- a/drivers/media/dvb-core/dvbdev.h
> +++ b/drivers/media/dvb-core/dvbdev.h
> @@ -47,6 +47,8 @@
>  #define DVB_DEVICE_CA         6
>  #define DVB_DEVICE_NET        7
>  #define DVB_DEVICE_OSD        8
> +#define DVB_DEVICE_CI         9
> +#define DVB_DEVICE_MOD       10
>  
>  #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
>  	static short adapter_nr[] = \


-- 

Cheers,
Mauro

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

* Re: [PATCH 07/12] ddbridge: Updated ddbridge registers
  2013-11-03  0:35 ` [PATCH 07/12] ddbridge: Updated ddbridge registers Maik Broemme
@ 2013-11-03 10:17   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:17 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:35:45 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Updated ddbridge registers:
> 
>   - Added GPIO and MDIO registers
>   - Added Clock Generator (Sil598 @ 0xAA I2c)
>   - Added DAC (AD9781/AD9783 SPI)
>   - Added Temperature Monitor (2x LM75A @ 0x90,0x92 I2c)
>   - Added CI Interface (only CI-Bridge)
>   - Added output control registers
>   - Added modulator channels
>   - Removed unneded defines (might be added later again if needed)
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>

You should be sure that this change won't break compilation and/or the
driver for the already supported devices. If this is not the case, then
this patch is ok.

> ---
>  drivers/media/pci/ddbridge/ddbridge-regs.h | 273 ++++++++++++++++++-----------
>  1 file changed, 168 insertions(+), 105 deletions(-)
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
> index a3ccb31..7d8bda4 100644
> --- a/drivers/media/pci/ddbridge/ddbridge-regs.h
> +++ b/drivers/media/pci/ddbridge/ddbridge-regs.h
> @@ -1,47 +1,53 @@
>  /*
> - * ddbridge-regs.h: Digital Devices PCIe bridge driver
> + *  ddbridge-regs.h: Digital Devices PCIe bridge driver
>   *
> - * Copyright (C) 2010-2011 Digital Devices GmbH
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
>   *
> - * 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 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.
>   *
> - * 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
> + *  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
>   */
>  
> -/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
> +#ifndef _DDBRIDGE_REGS_H_
> +#define _DDBRIDGE_REGS_H_
>  
>  /* Register Definitions */
> +#define CUR_REGISTERMAP_VERSION     0x10003
> +#define CUR_REGISTERMAP_VERSION_CI  0x10000
> +#define CUR_REGISTERMAP_VERSION_MOD 0x10000
>  
> -#define CUR_REGISTERMAP_VERSION 0x10000
> -
> -#define HARDWARE_VERSION       0x00
> -#define REGISTERMAP_VERSION    0x04
> +#define HARDWARE_VERSION            0x00
> +#define REGISTERMAP_VERSION         0x04
>  
> -/* ------------------------------------------------------------------------- */
>  /* SPI Controller */
> +#define SPI_CONTROL      0x10
> +#define SPI_DATA         0x14
>  
> -#define SPI_CONTROL     0x10
> -#define SPI_DATA        0x14
> +/* GPIO */
> +#define GPIO_OUTPUT      0x20
> +#define GPIO_DIRECTION   0x28
>  
> -/* ------------------------------------------------------------------------- */
> +/* MDIO */
> +#define MDIO_CTRL        0x20
> +#define MDIO_ADR         0x24
> +#define MDIO_REG         0x28
> +#define MDIO_VAL         0x2C
>  
> -/* Interrupt controller                                     */
> -/* How many MSI's are available depends on HW (Min 2 max 8) */
> -/* How many are usable also depends on Host platform        */
> +/* How many MSI's are available depends on HW (Min 2 max 8)
> +   How many are usable also depends on Host platform */
>  
> +/* Interrupt controller */
>  #define INTERRUPT_BASE   (0x40)
>  
>  #define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
> @@ -57,95 +63,152 @@
>  #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
>  #define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
>  
> -#define INTMASK_I2C1        (0x00000001)
> -#define INTMASK_I2C2        (0x00000002)
> -#define INTMASK_I2C3        (0x00000004)
> -#define INTMASK_I2C4        (0x00000008)
> -
> -#define INTMASK_CIRQ1       (0x00000010)
> -#define INTMASK_CIRQ2       (0x00000020)
> -#define INTMASK_CIRQ3       (0x00000040)
> -#define INTMASK_CIRQ4       (0x00000080)
> -
> -#define INTMASK_TSINPUT1    (0x00000100)
> -#define INTMASK_TSINPUT2    (0x00000200)
> -#define INTMASK_TSINPUT3    (0x00000400)
> -#define INTMASK_TSINPUT4    (0x00000800)
> -#define INTMASK_TSINPUT5    (0x00001000)
> -#define INTMASK_TSINPUT6    (0x00002000)
> -#define INTMASK_TSINPUT7    (0x00004000)
> -#define INTMASK_TSINPUT8    (0x00008000)
> -
> -#define INTMASK_TSOUTPUT1   (0x00010000)
> -#define INTMASK_TSOUTPUT2   (0x00020000)
> -#define INTMASK_TSOUTPUT3   (0x00040000)
> -#define INTMASK_TSOUTPUT4   (0x00080000)
> -
> -/* ------------------------------------------------------------------------- */
> -/* I2C Master Controller */
> -
> -#define I2C_BASE        (0x80)  /* Byte offset */
> -
> -#define I2C_COMMAND     (0x00)
> -#define I2C_TIMING      (0x04)
> -#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
> -#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
> +/* Clock Generator (Sil598 @ 0xAA I2c) */
> +#define CLOCKGEN_BASE       (0x80)
> +#define CLOCKGEN_CONTROL    (CLOCKGEN_BASE + 0x00)
> +#define CLOCKGEN_INDEX      (CLOCKGEN_BASE + 0x04)
> +#define CLOCKGEN_WRITEDATA  (CLOCKGEN_BASE + 0x08)
> +#define CLOCKGEN_READDATA   (CLOCKGEN_BASE + 0x0C)
>  
> -#define I2C_MONITOR     (0x1C)
> +/* DAC (AD9781/AD9783 SPI) */
> +#define DAC_BASE            (0x090)
> +#define DAC_CONTROL         (DAC_BASE)
> +#define DAC_WRITE_DATA      (DAC_BASE+4)
> +#define DAC_READ_DATA       (DAC_BASE+8)
>  
> -#define I2C_BASE_1      (I2C_BASE + 0x00)
> -#define I2C_BASE_2      (I2C_BASE + 0x20)
> -#define I2C_BASE_3      (I2C_BASE + 0x40)
> -#define I2C_BASE_4      (I2C_BASE + 0x60)
> +#define DAC_CONTROL_STARTIO (0x100)
> +#define DAC_CONTROL_RESET   (0x200)
>  
> -#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
> +/* Temperature Monitor (2x LM75A @ 0x90,0x92 I2c) */
> +#define TEMPMON_BASE        (0xA0)
> +#define TEMPMON_CONTROL     (TEMPMON_BASE + 0x00)
> +#define TEMPMON_SENSOR1     (TEMPMON_BASE + 0x08)    // SHORT Temperature in °C x 256
> +#define TEMPMON_SENSOR2     (TEMPMON_BASE + 0x0C)    // SHORT Temperature in °C x 256
>  
> -#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
> -#define I2C_TASKMEM_SIZE    (0x1000)
> -
> -#define I2C_SPEED_400   (0x04030404)
> -#define I2C_SPEED_200   (0x09080909)
> -#define I2C_SPEED_154   (0x0C0B0C0C)
> -#define I2C_SPEED_100   (0x13121313)
> -#define I2C_SPEED_77    (0x19181919)
> -#define I2C_SPEED_50    (0x27262727)
> -
> -
> -/* ------------------------------------------------------------------------- */
> -/* DMA  Controller */
> -
> -#define DMA_BASE_WRITE        (0x100)
> -#define DMA_BASE_READ         (0x140)
> +/* I2C Master Controller */
> +#define I2C_BASE            (0x80)   /* Byte offset */
>  
> -#define DMA_CONTROL     (0x00)                  /* 64 */
> -#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
> +#define I2C_COMMAND         (0x00)
> +#define I2C_TIMING          (0x04)
> +#define I2C_TASKLENGTH      (0x08)   /* High read, low write */
> +#define I2C_TASKADDRESS     (0x0C)   /* High read, low write */
> +#define I2C_TASKMEM_BASE    (0x1000) /* Byte offset */
> +#define I2C_TASKMEM_SIZE    (0x0800)
>  
> -#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
> -#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
> -#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
> -#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
> -#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
> -#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
> -#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
> -#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
> -#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
> +#define I2C_SPEED_400       (0x04030404)
> +#define I2C_SPEED_100       (0x13121313)
>  
> -/* ------------------------------------------------------------------------- */
> -/* DMA  Buffer */
> +/* DMA Controller */
> +#define DMA_BASE_WRITE      (0x100)
> +#define DMA_BASE_READ       (0x140)
>  
> +/* DMA Buffer */
>  #define TS_INPUT_BASE       (0x200)
> -#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
> +#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 0x10 + 0x00) 
> +#define TS_INPUT_CONTROL2(i)        (TS_INPUT_BASE + (i) * 0x10 + 0x04) 
>  
> -#define TS_OUTPUT_BASE       (0x280)
> -#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
> +#define TS_OUTPUT_BASE      (0x280)
> +#define TS_OUTPUT_CONTROL(i)        (TS_OUTPUT_BASE + (i) * 0x10 + 0x00) 
> +#define TS_OUTPUT_CONTROL2(i)       (TS_OUTPUT_BASE + (i) * 0x10 + 0x04) 
>  
>  #define DMA_BUFFER_BASE     (0x300)
> -
> -#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
> -#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
> -#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
> -#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
> +#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) 
> +#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 0x10 + 0x04)
> +#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
> +#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
>  
>  #define DMA_BASE_ADDRESS_TABLE  (0x2000)
> -#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
>  
> +/* CI Interface (only CI-Bridge) */
> +#define CI_BASE                     (0x400)
> +#define CI_CONTROL(i)               (CI_BASE + (i) * 32 + 0x00)
> +
> +#define CI_DO_ATTRIBUTE_RW(i)       (CI_BASE + (i) * 32 + 0x04)
> +#define CI_DO_IO_RW(i)              (CI_BASE + (i) * 32 + 0x08)
> +#define CI_READDATA(i)              (CI_BASE + (i) * 32 + 0x0c)
> +#define CI_DO_READ_ATTRIBUTES(i)    (CI_BASE + (i) * 32 + 0x10)
> +
> +#define CI_RESET_CAM                    (0x00000001)
> +#define CI_POWER_ON                     (0x00000002)
> +#define CI_ENABLE                       (0x00000004)
> +#define CI_BYPASS_DISABLE               (0x00000010)
> +
> +#define CI_CAM_READY                    (0x00010000)
> +#define CI_CAM_DETECT                   (0x00020000)
> +#define CI_READY                        (0x80000000)
> +
> +#define CI_READ_CMD                     (0x40000000)
> +#define CI_WRITE_CMD                    (0x80000000)
> +
> +#define CI_BUFFER_BASE                  (0x3000)
> +#define CI_BUFFER_SIZE                  (0x0800)
> +
> +#define CI_BUFFER(i)                    (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE )
> +
> +#define VCO1_BASE           (0xC0)
> +#define VCO1_CONTROL        (VCO1_BASE + 0x00)
> +#define VCO1_DATA           (VCO1_BASE + 0x04)  // 24 Bit
> +#define VCO1_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
> +#define VCO1_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
> +
> +#define VCO2_BASE           (0xC8)
> +#define VCO2_CONTROL        (VCO2_BASE + 0x00)
> +#define VCO2_DATA           (VCO2_BASE + 0x04)  // 24 Bit
> +#define VCO2_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
> +#define VCO2_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
> +
> +#define VCO3_BASE           (0xD0)
> +#define VCO3_CONTROL        (VCO3_BASE + 0x00)
> +#define VCO3_DATA           (VCO3_BASE + 0x04)  // 32 Bit
> +#define VCO3_CONTROL_WRITE  (0x00000001)   // 1 = Trigger write, resets when done
> +#define VCO3_CONTROL_CE     (0x00000002)   // 0 = Put VCO into power down
> +
> +#define RF_ATTENUATOR   (0xD8)
> +
> +/* Output control */
> +#define IQOUTPUT_BASE           (0x240)
> +#define IQOUTPUT_CONTROL        (IQOUTPUT_BASE + 0x00)
> +#define IQOUTPUT_CONTROL2       (IQOUTPUT_BASE + 0x04)    
> +#define IQOUTPUT_POSTSCALER     (IQOUTPUT_BASE + 0x0C)
> +#define IQOUTPUT_PRESCALER      (IQOUTPUT_BASE + 0x10)
> +
> +#define IQOUTPUT_EQUALIZER_0    (IQOUTPUT_BASE + 0x14)
> +
> +#define IQOUTPUT_CONTROL_RESET              (0x00000001)
> +#define IQOUTPUT_CONTROL_ENABLE             (0x00000002)
> +#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER   (0x00000010)
> +
> +#define MODULATOR_BASE            (0x200)
> +#define MODULATOR_CONTROL         (MODULATOR_BASE)
> +#define MODULATOR_IQTABLE_END     (MODULATOR_BASE+4)
> +#define MODULATOR_IQTABLE_INDEX   (MODULATOR_BASE+8)
> +#define MODULATOR_IQTABLE_DATA    (MODULATOR_BASE+12)
> +
> +#define MODULATOR_IQTABLE_INDEX_IQ_MASK       ( 0x00008000 )
> +#define MODULATOR_IQTABLE_INDEX_SEL_I         ( 0x00000000 )
> +#define MODULATOR_IQTABLE_INDEX_SEL_Q         ( MODULATOR_IQTABLE_INDEX_IQ_MASK )
> +
> +/* Modulator Channels */
> +#define CHANNEL_BASE                (0x400)
> +#define CHANNEL_CONTROL(i)          (CHANNEL_BASE + (i) * 64 + 0x00)
> +#define CHANNEL_SETTINGS(i)         (CHANNEL_BASE + (i) * 64 + 0x04)
> +#define CHANNEL_RATE_INCR(i)        (CHANNEL_BASE + (i) * 64 + 0x0C)
> +#define CHANNEL_PCR_ADJUST_OUTL(i)  (CHANNEL_BASE + (i) * 64 + 0x10)
> +#define CHANNEL_PCR_ADJUST_OUTH(i)  (CHANNEL_BASE + (i) * 64 + 0x14)
> +#define CHANNEL_PCR_ADJUST_INL(i)   (CHANNEL_BASE + (i) * 64 + 0x18)
> +#define CHANNEL_PCR_ADJUST_INH(i)   (CHANNEL_BASE + (i) * 64 + 0x1C)
> +#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20)
> +#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24)
> +#define CHANNEL_PKT_COUNT_OUT(i)    (CHANNEL_BASE + (i) * 64 + 0x28)
> +#define CHANNEL_PKT_COUNT_IN(i)     (CHANNEL_BASE + (i) * 64 + 0x2C)
> +
> +#define CHANNEL_CONTROL_RESET               (0x00000001)
> +#define CHANNEL_CONTROL_ENABLE_DVB          (0x00000002)
> +#define CHANNEL_CONTROL_ENABLE_IQ           (0x00000004)
> +#define CHANNEL_CONTROL_ENABLE_SOURCE       (0x00000008)
> +#define CHANNEL_CONTROL_ENABLE_PCRADJUST    (0x00000010)
> +#define CHANNEL_CONTROL_FREEZE_STATUS       (0x00000100)
> +
> +#define CHANNEL_CONTROL_BUSY                (0x01000000)
> +
> +#endif


-- 

Cheers,
Mauro

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

* Re: [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file
  2013-11-03  0:40 ` [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file Maik Broemme
@ 2013-11-03 10:23   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:23 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:40:15 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Moved i2c interfaces from ddbridge-core.c into separate file.
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/pci/ddbridge/ddbridge-i2c.c | 239 ++++++++++++++++++++++++++++++

Shouldn't you also be deleting it from ddbridge-core.c and updating the
Makefile?

Btw, please do the pure code move in one patch, and, on a next patch, do
the changes you need. That helps reviewers to check what actually changed
between the two versions.

Again, I won't repeat myself with regards to CodingStyle.

>  1 file changed, 239 insertions(+)
>  create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
> new file mode 100644
> index 0000000..5e9788c
> --- /dev/null
> +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
> @@ -0,0 +1,239 @@
> +/*
> + *  ddbridge-i2c.c: Digital Devices bridge i2c driver
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#include "ddbridge.h"
> +#include "ddbridge-regs.h"
> +
> +static int i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
> +{
> +	struct ddb *dev = i2c->dev;
> +	int stat;
> +	u32 val;
> +	u32 istat;
> +
> +	// i2c->done = 0;
> +	ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
> +
> +	// TODO: fix timeout issue.
> +	// stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
> +	stat = wait_for_completion_timeout(&i2c->completion, HZ);
> +	if (stat <= 0) {
> +		printk(KERN_ERR "DDBridge I2C timeout, card %d, port %d\n",
> +		       dev->nr, i2c->nr);
> +		istat = ddbreadl(dev, INTERRUPT_STATUS);
> +		printk(KERN_ERR "DDBridge IRS %08x\n", istat);
> +		ddbwritel(dev, istat, INTERRUPT_ACK);
> +		return -EIO;
> +	}
> +	val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
> +	if (val & 0x70000)
> +		return -EIO;
> +	return 0;
> +}
> +
> +static int i2c_master_xfer(struct i2c_adapter *adapter,
> +			   struct i2c_msg msg[], int num)
> +{
> +	struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
> +	struct ddb *dev = i2c->dev;
> +	u8 addr = 0;
> +
> +	if (num)
> +		addr = msg[0].addr;
> +	if (num == 2 && msg[1].flags & I2C_M_RD &&
> +	    !(msg[0].flags & I2C_M_RD)) {
> +		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
> +			    msg[0].buf, msg[0].len);
> +		ddbwritel(dev, msg[0].len|(msg[1].len << 16),
> +			  i2c->regs + I2C_TASKLENGTH);
> +		if (!i2c_cmd(i2c, addr, 1)) {
> +			memcpy_fromio(msg[1].buf,
> +				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
> +				      msg[1].len);
> +			return num;
> +		}
> +	}
> +	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
> +		ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, 
> +			 msg[0].buf, msg[0].len);
> +		ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
> +		if (!i2c_cmd(i2c, addr, 2)) {
> +			return num;
> +		}
> +	}
> +	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
> +		ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
> +		if (!i2c_cmd(i2c, addr, 3)) {
> +			ddbcpyfrom(dev, msg[0].buf,
> +				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
> +			return num;
> +		}
> +	}
> +	return -EIO;
> +}
> +
> +static u32 i2c_functionality(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +static void i2c_handler(unsigned long priv)
> +{
> +	struct ddb_i2c *i2c = (struct ddb_i2c *) priv; 
> +
> +	complete(&i2c->completion);
> +}
> +
> +static struct i2c_algorithm i2c_algo = {
> +	.master_xfer   = i2c_master_xfer,
> +	.functionality = i2c_functionality,
> +};
> +
> +int ddb_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;
> +}
> +
> +int ddb_i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
> +{
> +	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
> +				   .buf  = val,  .len   = 1 } };
> +	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
> +}
> +
> +int ddb_i2c_read_regs(struct i2c_adapter *adapter,
> +			 u8 adr, u8 reg, u8 *val, u8 len)
> +{
> +	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
> +				   .buf  = &reg, .len   = 1 },
> +				  {.addr = adr,  .flags = I2C_M_RD,
> +				   .buf  = val,  .len   = len } };
> +	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +int ddb_i2c_read_regs16(struct i2c_adapter *adapter, 
> +			   u8 adr, u16 reg, u8 *val, u8 len)
> +{
> +	u8 reg16[2] = { reg >> 8, reg };
> +	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
> +				   .buf  = reg16, .len   = 2 },
> +				  {.addr = adr,  .flags = I2C_M_RD,
> +				   .buf  = val,  .len   = len } };
> +	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +int ddb_i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
> +{
> +	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
> +				   .buf  = &reg, .len   = 1},
> +				  {.addr = adr,  .flags = I2C_M_RD,
> +				   .buf  = val,  .len   = 1 } };
> +	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +int ddb_i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
> +			  u16 reg, u8 *val)
> +{
> +	u8 msg[2] = {reg >> 8, reg & 0xff};
> +	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
> +				   .buf  = msg, .len   = 2},
> +				  {.addr = adr, .flags = I2C_M_RD,
> +				   .buf  = val, .len   = 1 } };
> +	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> +}
> +
> +int ddb_i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
> +			   u16 reg, u8 val)
> +{
> +	u8 msg[3] = {reg >> 8, reg & 0xff, val};
> +
> +	return ddb_i2c_write(adap, adr, msg, 3);
> +}
> +
> +int ddb_i2c_write_reg(struct i2c_adapter *adap, u8 adr,
> +			  u8 reg, u8 val)
> +{
> +	u8 msg[2] = {reg, val};
> +
> +	return ddb_i2c_write(adap, adr, msg, 2);
> +}
> +
> +void ddb_i2c_release(struct ddb *dev)
> +{
> +	int i;
> +	struct ddb_i2c *i2c;
> +	struct i2c_adapter *adap;
> +
> +	for (i = 0; i < dev->info->i2c_num; i++) {
> +		i2c = &dev->i2c[i];
> +		adap = &i2c->adap;
> +		i2c_del_adapter(adap);
> +	}
> +}
> +
> +int ddb_i2c_init(struct ddb *dev)
> +{
> +	int i, j, stat = 0;
> +	struct ddb_i2c *i2c;
> +	struct i2c_adapter *adap;
> +	
> +	for (i = 0; i < dev->info->i2c_num; i++) {
> +		i2c = &dev->i2c[i];
> +		dev->handler[i] = i2c_handler;
> +		dev->handler_data[i] = (unsigned long) i2c;
> +		i2c->dev = dev;
> +		i2c->nr = i;
> +		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
> +		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
> +		i2c->regs = 0x80 + i * 0x20;
> +		ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
> +		ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf,
> +			  i2c->regs + I2C_TASKADDRESS);
> +		// init_waitqueue_head(&i2c->wq);
> +		init_completion(&i2c->completion);
> +
> +		adap = &i2c->adap;
> +		i2c_set_adapdata(adap, i2c);
> +#ifdef I2C_ADAP_CLASS_TV_DIGITAL
> +		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
> +#else
> +#ifdef I2C_CLASS_TV_ANALOG
> +		adap->class = I2C_CLASS_TV_ANALOG;
> +#endif
> +#endif

FYI, the usage of adap->class is long gone. You can just remove the above
on the second patch (the one after the moving code, that does other changes).

> +		strcpy(adap->name, "ddbridge");
> +		adap->algo = &i2c_algo;
> +		adap->algo_data = (void *)i2c;
> +		adap->dev.parent = dev->dev;
> +		stat = i2c_add_adapter(adap);
> +		if (stat)
> +			break;
> +	}
> +	if (stat)
> +		for (j = 0; j < i; j++) {
> +			i2c = &dev->i2c[j];
> +			adap = &i2c->adap;
> +			i2c_del_adapter(adap);
> +		}
> +	return stat;
> +}


-- 

Cheers,
Mauro

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

* Re: [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
  2013-11-03  0:41 ` [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card Maik Broemme
@ 2013-11-03 10:44   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:44 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:41:38 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Added support for the Digital Devices Resi DVB-C Modulator card.

If I got this right, this driver provides functionality to modulate a
DVB signal, right?

This driver will likely require more discussions, as it is a modulator
driver, with is new at the subsystem. So, we should discuss about the
API used here.

Btw, it is not clear what kind of delivery system this modulator is
generating signals, nor the API provides enough control over all
delivery system properties.

I'm wandering how much of this code is generic enough to be part of 
a DVB modulator core.

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/pci/ddbridge/ddbridge-mod.c | 1033 +++++++++++++++++++++++++++++
>  1 file changed, 1033 insertions(+)
>  create mode 100644 drivers/media/pci/ddbridge/ddbridge-mod.c
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge-mod.c b/drivers/media/pci/ddbridge/ddbridge-mod.c
> new file mode 100644
> index 0000000..8f7c256
> --- /dev/null
> +++ b/drivers/media/pci/ddbridge/ddbridge-mod.c
> @@ -0,0 +1,1033 @@
> +/*
> + *  ddbridge-mod.c: Digital Devices DVB modulator driver
> + *
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
> + *
> + *  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
> + */
> +
> +#include "ddbridge.h"
> +#include "ddbridge-regs.h"
> +
> +inline s64 ConvertPCR(s64 a)
> +{
> +	s32 ext;
> +	s64 b;
> +	
> +	b = div_s64_rem(a, 300 << 22, &ext);
> +	
> +	return (b << 31) | ext;
> +
> +}
> +
> +inline s64 NegConvertPCR(s64 a)
> +{
> +	s32 ext;
> +	s64 b;
> +	
> +	b = -div_s64_rem(a, 300 << 22, &ext);
> +
> +	if( ext != 0 ) {
> +		ext = (300 << 22) - ext;
> +		b -= 1;
> +	}
> +	return (b << 31) | ext;
> +}
> +
> +inline s64 RoundPCR(s64 a)
> +{
> +	s64 b = a + (HW_LSB_MASK>>1);
> +	return b & ~(HW_LSB_MASK - 1);
> +}
> +
> +inline s64 RoundPCRUp(s64 a)
> +{
> +	s64 b = a + (HW_LSB_MASK - 1);
> +	return b & ~(HW_LSB_MASK - 1);
> +}
> +
> +inline s64 RoundPCRDown(s64 a)
> +{
> +	return a & ~(HW_LSB_MASK - 1);
> +}
> +
> +static int mod_busy(struct ddb *dev, int chan)
> +{
> +	u32 creg;
> +
> +	while (1) {
> +		creg = ddbreadl(dev, CHANNEL_CONTROL(chan));
> +		if (creg == 0xffffffff) 
> +			return -EFAULT;
> +		if ((creg & CHANNEL_CONTROL_BUSY) == 0)
> +			break;
> +	}
> +	return 0;
> +}
> +
> +void ddbridge_mod_output_stop(struct ddb_output *output)
> +{
> +	struct ddb *dev = output->port->dev;
> +	struct mod_state *mod= &dev->mod[output->nr];
> +
> +	mod->State = CM_IDLE;
> +	mod->Control = 0;
> +	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
> +
> +	mod_busy(dev, output->nr);
> +	printk("mod_output_stop %d.%d\n", dev->nr, output->nr);
> +}
> +
> +static void mod_set_incs(struct ddb_output *output)
> +{
> +	s64 pcr;
> +	struct ddb *dev = output->port->dev;
> +	struct mod_state *mod= &dev->mod[output->nr];
> +
> +	pcr = ConvertPCR(mod->PCRIncrement);
> +	ddbwritel(dev, 	pcr & 0xffffffff, 
> +		  CHANNEL_PCR_ADJUST_OUTL(output->nr));
> +	ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
> +		  CHANNEL_PCR_ADJUST_OUTH(output->nr));
> +	mod_busy(dev, output->nr);
> +	
> +	pcr = NegConvertPCR(mod->PCRDecrement);
> +	ddbwritel(dev, 	pcr & 0xffffffff, 
> +		  CHANNEL_PCR_ADJUST_INL(output->nr));
> +	ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
> +		  CHANNEL_PCR_ADJUST_INH(output->nr));
> +	mod_busy(dev, output->nr);
> +
> +}
> +
> +static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 };

Please better document it, with something like:

static u32 qamtab[6] = {
	[QPSK] = 0x000,
	[QAM_16] = 0x600,
	[QAM_32] = 0x601,
	[QAM_64] = 0x602,
	[QAM_128] = 0x903,
	[QAM_256] = 0x604,
};

This way, it is clearer what register value is needed for each type of
the supported modulations.

> +
> +void ddbridge_mod_output_start(struct ddb_output *output)
> +{
> +	struct ddb *dev = output->port->dev;
> +	struct mod_state *mod= &dev->mod[output->nr];
> +
> +	// PCRIncrement = RoundPCR(PCRIncrement);
> +	// PCRDecrement = RoundPCR(PCRDecrement);
> +
> +	mod->LastInPacketCount = 0;
> +	mod->LastOutPacketCount = 0;
> +	mod->InOverflowPacketCount = 0;
> +	mod->OutOverflowPacketCount = 0;
> +	mod->LastInPackets = 0;
> +	mod->LastOutPackets = 0;
> +	mod->LastPCRAdjust = 0;
> +	mod->PCRRunningCorr = 0;
> +	mod->MinInputPackets = 524288/2;   // we interrupt every 0x80000=524288 packets
> +	mod->PCRIncrement = 0;   // PCRIncrement;
> +	mod->PCRDecrement = 0;   // PCRDecrement;
> +
> +	mod->State = CM_STARTUP;
> +	mod->StateCounter = CM_STARTUP_DELAY;
> +
> +	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
> +	udelay(10);
> +	ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr));
> +	udelay(10);
> +	ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
> +
> +	// QAM: 600 601 602 903 604 = 16 32 64 128 256
> +	// ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr));
> +	ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr));
> +
> +	ddbwritel(dev, 	mod->rate_inc, CHANNEL_RATE_INCR(output->nr));
> +	mod_busy(dev, output->nr);
> +
> +	mod_set_incs(output);
> +
> +	mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | 
> +			CHANNEL_CONTROL_ENABLE_DVB |
> +			CHANNEL_CONTROL_ENABLE_SOURCE);
> +
> +	ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
> +	printk("mod_output_start %d.%d\n", dev->nr, output->nr);
> +}
> +
> +static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value)
> +{
> +	u32 RegValue = 0;
> +	
> +	ddbwritel(dev, Value, DAC_WRITE_DATA);
> +	ddbwritel(dev, DAC_CONTROL_STARTIO | Index, DAC_CONTROL);
> +	do {
> +		RegValue = ddbreadl(dev, DAC_CONTROL);
> +	} while ((RegValue & DAC_CONTROL_STARTIO) != 0 );
> +}
> +
> +static void mod_write_dac_register2(struct ddb *dev, u8 Index, u16 Value)
> +{
> +	u32 RegValue = 0;
> +	
> +	ddbwritel(dev, Value, DAC_WRITE_DATA);
> +	ddbwritel(dev, DAC_CONTROL_STARTIO | 0x20 | Index, DAC_CONTROL);
> +	do {
> +		RegValue = ddbreadl(dev, DAC_CONTROL);
> +	} while ((RegValue & DAC_CONTROL_STARTIO) != 0 );
> +}
> +
> +static int mod_read_dac_register(struct ddb *dev, u8 Index, u8 *pValue)
> +{
> +	u32 RegValue = 0;
> +	
> +	ddbwritel(dev, DAC_CONTROL_STARTIO | 0x80 | Index, DAC_CONTROL);
> +	do {
> +		RegValue = ddbreadl(dev, DAC_CONTROL);
> +	} while( (RegValue & DAC_CONTROL_STARTIO) != 0 );
> +	
> +	RegValue = ddbreadl(dev, DAC_READ_DATA);
> +	*pValue = (u8) RegValue;
> +	return 0;
> +}
> +
> +static void mod_set_up_converter_vco1(struct ddb *dev, u32 Value)
> +{
> +	u32 RegValue = 0;
> +
> +	/* Extra delay before writing N divider */
> +	if ((Value & 0x03) == 0x02) 
> +		msleep(50);
> +	do {
> +		RegValue = ddbreadl(dev, VCO1_CONTROL);
> +	} while( (RegValue & VCO1_CONTROL_WRITE) != 0 ); 
> +	
> +	if ((RegValue & VCO1_CONTROL_CE) == 0) {
> +		RegValue |= VCO1_CONTROL_CE;
> +		ddbwritel(dev, RegValue, VCO1_CONTROL);
> +		msleep(10);
> +	}
> +	
> +	ddbwritel(dev, Value, VCO1_DATA);
> +	ddbwritel(dev, RegValue | VCO1_CONTROL_WRITE, VCO1_CONTROL);
> +}
> +
> +static void mod_set_up_converter_vco2(struct ddb *dev, u32 Value)
> +{
> +	u32 RegValue = 0;
> +
> +	/* Extra delay before writing N divider */
> +	if ((Value & 0x03) == 0x02)
> +		msleep(50);
> +	do {
> +		RegValue = ddbreadl(dev, VCO2_CONTROL);
> +	} while ((RegValue & VCO2_CONTROL_WRITE) != 0); 
> +	
> +	if ((RegValue & VCO2_CONTROL_CE) == 0) {
> +		RegValue |= VCO2_CONTROL_CE;
> +		ddbwritel(dev, RegValue, VCO2_CONTROL);
> +		msleep(10);
> +	}
> +	
> +	ddbwritel(dev, Value, VCO2_DATA);
> +	ddbwritel(dev, RegValue | VCO2_CONTROL_WRITE, VCO2_CONTROL);
> +}
> +
> +static void mod_set_down_converter_vco(struct ddb *dev, u32 Value)
> +{
> +	u32 RegValue = 0;
> +
> +	do {
> +		RegValue = ddbreadl(dev, VCO3_CONTROL);
> +	} while( (RegValue & VCO3_CONTROL_WRITE) != 0 ); 
> +	
> +	if ((RegValue & VCO3_CONTROL_CE) == 0) {
> +		RegValue |= VCO3_CONTROL_CE;
> +		ddbwritel(dev, RegValue, VCO3_CONTROL);
> +		msleep(10);
> +	}
> +	ddbwritel(dev, Value, VCO3_DATA);
> +	ddbwritel(dev, RegValue | VCO3_CONTROL_WRITE, VCO3_CONTROL);
> +}
> +
> +static int mod_set_attenuator(struct ddb *dev, u32 Value)
> +{
> +	if (Value > 31)
> +		return -EINVAL;
> +	ddbwritel(dev, Value, RF_ATTENUATOR);
> +	return 0;
> +}
> +
> +static void mod_si598_readreg(struct ddb *dev, u8 index, u8 *val)
> +{
> +	ddbwritel(dev, index, CLOCKGEN_INDEX);
> +	ddbwritel(dev, 1, CLOCKGEN_CONTROL);
> +	msleep(5);
> +	*val = ddbreadl(dev, CLOCKGEN_READDATA);
> +}
> +
> +static void mod_si598_writereg(struct ddb *dev, u8 index, u8 val)
> +{
> +	ddbwritel(dev, index, CLOCKGEN_INDEX);
> +	ddbwritel(dev, val, CLOCKGEN_WRITEDATA);
> +	ddbwritel(dev, 3, CLOCKGEN_CONTROL);
> +	msleep(5);
> +}
> +
> +static int mod_set_si598(struct ddb *dev, u32 freq)
> +{
> +	u8 Data[6];
> +	u64 fDCO = 0;
> +	u64 RFreq = 0;
> +	u32 fOut = 10000000;
> +	u64 m_fXtal = 0;
> +	u32 N = 0;
> +	u64 HSDiv = 0;
> +
> +	u32 fxtal;
> +	u64 MinDiv, MaxDiv, Div;
> +	u64 RF;
> +
> +	if (freq < 10000000 || freq > 525000000 )
> +		return -EINVAL;
> +	mod_si598_writereg(dev, 137, 0x10);
> +
> +	if (m_fXtal == 0) {
> +		mod_si598_writereg(dev, 135, 0x01);
> +		mod_si598_readreg(dev, 7, &Data[0]);
> +		mod_si598_readreg(dev, 8, &Data[1]);
> +		mod_si598_readreg(dev, 9, &Data[2]);
> +		mod_si598_readreg(dev, 10, &Data[3]);
> +		mod_si598_readreg(dev, 11, &Data[4]);
> +		mod_si598_readreg(dev, 12, &Data[5]);
> +		
> +		printk(" Data = %02x %02x %02x %02x %02x %02x\n",
> +		       Data[0],Data[1],Data[2],Data[3],Data[4],Data[5]);
> +		RFreq = (((u64)Data[1] & 0x3F) << 32) | ((u64)Data[2] << 24) |
> +			((u64)Data[3] << 16) | ((u64)Data[4] << 8) | ((u64)Data[5]);
> +		if (RFreq == 0)
> +			return -EINVAL;
> +		HSDiv = ((Data[0] & 0xE0) >> 5) + 4;
> +		if (HSDiv == 8 || HSDiv == 10 ) 
> +			return -EINVAL;
> +		N = (((u32)(Data[0] & 0x1F) << 2) | ((u32)(Data[1] & 0xE0) >> 6)) + 1;
> +		fDCO = fOut * (u64)(HSDiv * N);  
> +		m_fXtal = fDCO << 28;
> +		printk("fxtal %016llx  rfreq %016llx\n", m_fXtal, RFreq);
> +		
> +		m_fXtal += RFreq >> 1;
> +		m_fXtal = div64_u64(m_fXtal, RFreq);
> +		
> +		printk(" fOut = %d fXtal = %d fDCO = %d HDIV = %2d, N = %3d \n",
> +		       (u32) fOut, (u32) m_fXtal, (u32) fDCO, (u32) HSDiv, N);
> +	}
> +	
> +	fOut = freq;
> +	MinDiv = 4850000000ULL; do_div(MinDiv, freq); MinDiv += 1;
> +	MaxDiv = 5670000000ULL; do_div(MaxDiv, freq);
> +	Div    = 5260000000ULL; do_div(Div, freq);

One instruction per line.

> +
> +	if( Div < MinDiv ) 
> +		Div = Div + 1;
> +	printk(" fOut = %d MinDiv = %4d MaxDiv = %4d StartDiv = %d\n", fOut, (u32) MinDiv, (u32) MaxDiv, (u32) Div);
> +	
> +	if( Div <= 11 ) {
> +		N = 1;
> +		HSDiv = Div;
> +	} else {
> +		int retry = 100;
> +		while (retry > 0) {
> +			N = 0;
> +			HSDiv = Div;
> +			while( (HSDiv > 11) /*|| ((HSDiv * N) != Div)*/ ) {
> +				N = N + 2;
> +				HSDiv = Div;
> +				do_div(HSDiv, N);
> +				if (N > 128) 
> +					break;
> +			}
> +			printk(" %3d: %llu %u %u %u\n", retry, Div, (u32) HSDiv*N, (u32) HSDiv, N);
> +			if (HSDiv * N < MinDiv) {
> +				Div = Div + 2;
> +			} else if (HSDiv * N > MaxDiv) {
> +				Div = Div - 2;
> +			} else
> +				break;
> +			retry = retry - 1;
> +		}
> +		if( retry == 0 ) {
> +			printk(" FAIL \n");
> +			return -EINVAL;
> +		}
> +	}
> +	
> +	if (HSDiv == 8 || HSDiv == 10)	{
> +		HSDiv = HSDiv >> 1;
> +		N = N * 2;
> +	}
> +	
> +	if (HSDiv < 4)
> +		return -EINVAL;
> +	
> +
> +	fDCO = (u64)fOut * (u64)N * (u64)HSDiv;
> +	printk("fdco %16llx\n", fDCO);
> +	RFreq = fDCO<<28;
> +	printk("%16llx %16llx\n", fDCO, RFreq);
> +
> +	fxtal = m_fXtal; 
> +	do_div(RFreq, fxtal);
> +	printk("%16llx %d\n", RFreq, fxtal);
> +	RF = RFreq;
> +	
> +	// printk("fOut = %d fXtal = %d fDCO = %d HDIV = %d, N = %d, RFreq = %d\n",fOut,m_fXtal,fDCO,HSDiv,N,RFreq);
> +	// printk("%16llx\n", RF);
> +
> +	Data[0] = (u8)( ((HSDiv - 4) << 5) | ((N - 1) >> 2) );
> +	Data[1] = (u8)( (((N - 1) & 0x03) << 6) | (( RF >> 32 ) & 0x3F ) );
> +	Data[2] = (u8)( (RF >> 24) & 0xFF );
> +	Data[3] = (u8)( (RF >> 16) & 0xFF );
> +	Data[4] = (u8)( (RF >>  8) & 0xFF );
> +	Data[5] = (u8)( (RF      ) & 0xFF );
> +	
> +	printk(" Data = %02x %02x %02x %02x %02x %02x\n",
> +	       Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]);
> +	mod_si598_writereg(dev, 7, Data[0]);
> +	mod_si598_writereg(dev, 8, Data[1]);
> +	mod_si598_writereg(dev, 9, Data[2]);
> +	mod_si598_writereg(dev, 10, Data[3]);
> +	mod_si598_writereg(dev, 11, Data[4]);
> +	mod_si598_writereg(dev, 12, Data[5]);
> +
> +	mod_si598_writereg(dev, 137, 0x00);
> +	mod_si598_writereg(dev, 135, 0x40);
> +	return 0;
> +}
> +
> +
> +static void mod_bypass_equalizer(struct ddb *dev, int bypass)
> +{
> +	u32  RegValue;
> +	
> +	RegValue = ddbreadl(dev, IQOUTPUT_CONTROL);
> +	RegValue &= ~IQOUTPUT_CONTROL_BYPASS_EQUALIZER;
> +	RegValue |= (bypass ? IQOUTPUT_CONTROL_BYPASS_EQUALIZER : 0x00);
> +	ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
> +}
> +
> +static int mod_set_equalizer(struct ddb *dev, u32 Num, s16 *cTable)
> +{
> +	u32 i, adr = IQOUTPUT_EQUALIZER_0;
> +	
> +	if (Num > 11) 
> +		return -EINVAL;
> +
> +	for (i = 0; i < 11 - Num; i += 1) {
> +		ddbwritel(dev, 0, adr);
> +		adr += 4;
> +	}
> +	for (i = 0; i < Num; i += 1) {
> +		ddbwritel(dev, (u32) cTable[i], adr);
> +		adr += 4;
> +	}
> +	return 0;
> +}
> +
> +static int mod_init_dac_input(struct ddb *dev)
> +{
> +	u8 Set = 0;
> +	u8 Hld = 0;
> +	u8 Sample = 0; 
> +	
> +	u8 Seek = 0;
> +	u8 ReadSeek = 0;
> +	
> +	u8 SetTable[32];
> +	u8 HldTable[32];
> +	u8 SeekTable[32];
> +
> +	u8 Sample1 = 0xFF;
> +	u8 Sample2 = 0xFF;
> +	
> +	u8 SelectSample = 0xFF;
> +	u8 DiffMin = 0xFF;
> +
> +	for (Sample = 0; Sample < 32; Sample++ ) {
> +		Set = 0;
> +		Hld = 0;
> +		
> +		mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
> +		mod_write_dac_register(dev, 0x05, Sample);
> +		mod_read_dac_register(dev, 0x06, &ReadSeek);
> +		Seek = ReadSeek & 0x01;
> +		SeekTable[Sample] = Seek;
> +		
> +		HldTable[Sample] = 15;
> +
> +		for (Hld = 1; Hld < 16; Hld += 1) {
> +			mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
> +			mod_read_dac_register(dev, 0x06, &ReadSeek);
> +			
> +			if ((ReadSeek & 0x01) != Seek) 
> +			{
> +				HldTable[Sample] = Hld;
> +				break;
> +			}
> +		}
> +		
> +		Hld = 0;
> +		SetTable[Sample] = 15;
> +		for (Set = 1; Set < 16; Set += 1) {
> +			mod_write_dac_register(dev, 0x04, Set << 4 | Hld);
> +			mod_read_dac_register(dev, 0x06, &ReadSeek);
> +			
> +			if( (ReadSeek & 0x01) != Seek ) {
> +				SetTable[Sample] = Set;
> +				break;
> +			}
> +		}
> +	}
> +	
> +	Seek = 1;
> +	for (Sample = 0; Sample < 32; Sample += 1 ) {
> +		// printk(" %2d: %d %2d %2d\n", Sample,SeekTable[Sample],SetTable[Sample],HldTable[Sample]);
> +		
> +		if (Sample1 == 0xFF && SeekTable[Sample] == 1 && Seek == 0 ) 
> +			Sample1 = Sample;
> +		if (Sample1 != 0xFF && Sample2 == 0xFF && SeekTable[Sample] == 0 && Seek == 1 )
> +			Sample2 = Sample;
> +		Seek = SeekTable[Sample];
> +	}
> +	
> +	if (Sample1 == 0xFF || Sample2 == 0xFF ) {
> +		printk(" No valid window found\n");
> +		return -EINVAL;
> +	}
> +	
> +	printk(" Window = %d - %d\n", Sample1, Sample2);

Don't add printks without specifying the level. Also, those seem to be
debug printks. The better is to use pr_debug().

> +
> +	for (Sample = Sample1; Sample < Sample2; Sample += 1) {
> +		if (SetTable[Sample] < HldTable[Sample]) {
> +			if (HldTable[Sample] - SetTable[Sample] < DiffMin) {
> +				DiffMin = HldTable[Sample] - SetTable[Sample];
> +				SelectSample = Sample;
> +			}
> +		}
> +	}
> +	
> +	printk("Select Sample %d\n", SelectSample);
> +	
> +	if (SelectSample == 0xFF) {
> +		printk("No valid sample found\n");
> +		return -EINVAL;
> +	}
> +	
> +	if (HldTable[SelectSample] + SetTable[SelectSample] < 8 ) {
> +		printk("Too high jitter\n");
> +		return -EINVAL;
> +	}
> +	
> +	mod_write_dac_register(dev, 0x04, 0x00);
> +	mod_write_dac_register(dev, 0x05, (SelectSample - 1) & 0x1F);
> +	mod_read_dac_register(dev, 0x06, &Seek);
> +	mod_write_dac_register(dev, 0x05, (SelectSample + 1) & 0x1F);
> +	mod_read_dac_register(dev, 0x06,&ReadSeek);
> +	Seek &= ReadSeek;
> +	
> +	mod_write_dac_register(dev, 0x05, SelectSample);
> +	mod_read_dac_register(dev, 0x06, &ReadSeek);
> +	Seek &= ReadSeek;
> +	if( (Seek & 0x01) == 0 ) {
> +		printk("Insufficient timing margin\n");
> +		return -EINVAL;
> +	}
> +	printk("Done\n");
> +	return 0;
> +}
> +
> +static void mod_set_up1(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
> +{
> +	u32 RDiv = Ext / Ref;
> +
> +	Frequency = Frequency / Ref;
> +	mod_set_up_converter_vco1(dev, 0x360001 | (RDiv << 2)); 
> +	mod_set_up_converter_vco1(dev, 0x0ff128);
> +	mod_set_up_converter_vco1(dev, 0x02 | (Frequency << 8));
> +}
> +
> +static void mod_set_up2(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
> +{
> +	u32 Rdiv = Ext / Ref;
> +	u32 PreScale = 8;
> +
> +	Frequency = Frequency / Ref;
> +	mod_set_up_converter_vco2(dev, 0x360001 | (Rdiv << 2));
> +	mod_set_up_converter_vco2(dev, 0x0fc128 | (((PreScale - 8) / 8) << 22));
> +	mod_set_up_converter_vco2(dev, 0x02 | ((Frequency / PreScale) << 8) 
> +				  | (Frequency & (PreScale - 1)) << 2);
> +}
> +
> +static int mod_set_down(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext)
> +{
> +	u32 BandSelect = Ref * 8;
> +	u32 RefMul = 1;
> +	u32 RefDiv2 = 1;
> +	u32 RefDiv = Ext * RefMul / (Ref * RefDiv2);
> +	
> +	if (Frequency < 2200 || Frequency > 4000) 
> +		return -EINVAL; 
> +
> +	Frequency = Frequency / Ref;
> +
> +	mod_set_down_converter_vco(dev, 0x0080003C | ((BandSelect & 0xFF) << 12));
> +	mod_set_down_converter_vco(dev, 0x00000003);
> +	mod_set_down_converter_vco(dev, 0x18001E42 | ((RefMul-1) << 25) | 
> +				   ((RefDiv2-1) << 24) | (RefDiv << 14) );
> +	mod_set_down_converter_vco(dev, 0x08008021);
> +	mod_set_down_converter_vco(dev, Frequency << 15);
> +	return 0;
> +}
> +
> +static int mod_set_dac_clock(struct ddb *dev, u32 Frequency)
> +{
> +	int hr, i;
> +
> +	if (Frequency) {
> +		ddbwritel(dev, DAC_CONTROL_RESET, DAC_CONTROL);
> +		msleep(10);
> +		if (mod_set_si598(dev, Frequency)) {
> +			printk("mod_set_si598 failed\n");
> +			return -1;
> +		}
> +		msleep(50);
> +		ddbwritel(dev, 0x000, DAC_CONTROL);
> +		msleep(10);
> +		mod_write_dac_register(dev, 0, 0x02);
> +	}
> +	
> +	for (i = 0; i < 10; i++) { 
> +		hr = mod_init_dac_input(dev);
> +		if (hr == 0)
> +			break;
> +		msleep(100);
> +	}
> +	printk("mod_set_dac_clock OK\n");
> +	return hr;
> +}
> +
> +static void mod_set_dac_current(struct ddb *dev, u32 Current1, u32 Current2)
> +{
> +	mod_write_dac_register2(dev, 0x0b, Current1 & 0x3ff);
> +	mod_write_dac_register2(dev, 0x0f, Current2 & 0x3ff);
> +}
> +
> +static void mod_output_enable(struct ddb *dev, int enable)
> +{
> +
> +	u32  RegValue;
> +	
> +	RegValue = ddbreadl(dev, IQOUTPUT_CONTROL);
> +	RegValue &= ~(IQOUTPUT_CONTROL_ENABLE | IQOUTPUT_CONTROL_RESET);
> +	ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
> +
> +	if (enable) {
> +		ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_RESET, IQOUTPUT_CONTROL);
> +		msleep(10);
> +		ddbwritel(dev, RegValue, IQOUTPUT_CONTROL);
> +		ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_ENABLE, IQOUTPUT_CONTROL);
> +	}
> +}
> +
> +static int mod_set_iq(struct ddb *dev, u32 steps, u32 chan, u32 freq)
> +{
> +	u32 i, j, k, fac = 8;
> +	u32 s1 = 22, s2 = 33;
> +	u64 amp = (1ULL << 17) - 1ULL; 
> +	u64 s = 0, c = (amp << s1), ss;
> +	u64 frq = 0xC90FDAA22168C234ULL;
> +	u32 *iqtab;
> +	u32 iqtabadr;
> +	u32 volatile regval;
> +
> +	iqtab = kmalloc((steps + 1) * 4, GFP_KERNEL);
> +	if (!iqtab)
> +		return -ENOMEM;
> +	frq = div64_u64(frq, steps * fac) >> (61 - s2);
> +
> +	/* create sine table */
> +	for (i = 0; i <= steps * fac / 4; i++) {
> +		if (!(i & (fac - 1))) {
> +			j = i / fac;
> +			ss = s >> s1;
> +			// ss = ((s >> (s1 - 1)) + 1) >> 1;
> +					
> +			iqtab[j] = iqtab[steps / 2 - j] = ss;
> +			iqtab[steps / 2 + j] = iqtab[steps - j] = -ss;
> +		}
> +		c -= ((s * frq) >> s2);
> +		s += ((c * frq) >> s2);
> +	}
> +
> +	iqtabadr = chan << 16;
> +	ddbwritel(dev, chan & 0x0f, MODULATOR_IQTABLE_INDEX);
> +	for (i = j = 0, k = steps / 4; i < steps; i++) {
> +		ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_I,
> +			  MODULATOR_IQTABLE_INDEX);
> +		ddbwritel(dev, iqtab[j], MODULATOR_IQTABLE_DATA);
> +		regval = ddbreadl(dev, MODULATOR_CONTROL);
> +		ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_Q,
> +			  MODULATOR_IQTABLE_INDEX);
> +		ddbwritel(dev, iqtab[k], MODULATOR_IQTABLE_DATA);
> +		regval = ddbreadl(dev, MODULATOR_CONTROL);
> +		j += freq;
> +		j %= steps;
> +		k += freq;
> +		k %= steps;
> +	}
> +	ddbwritel(dev, steps - 1, MODULATOR_IQTABLE_END);
> +	kfree(iqtab);
> +	return 0;
> +}
> +
> +u32 eqtab[] = {
> +	0x0000FFDB, 0x00000121, 0x0000FF0A, 0x000003D7, 
> +	0x000001C4, 0x000005A5, 0x000009CC, 0x0000F50D, 
> +	0x00001B23, 0x0000EEB7, 0x00006A28
> +};
> +
> +static void mod_set_channelsumshift(struct ddb *dev, u32 shift)
> +{
> +	ddbwritel(dev, (shift & 3) << 2, MODULATOR_CONTROL);
> +}
> +
> +static void mod_pre_eq_gain(struct ddb *dev, u16 gain)
> +{
> +	ddbwritel(dev, gain, IQOUTPUT_PRESCALER);
> +}
> +
> +static void mod_post_eq_gain(struct ddb *dev, u16 igain, u16 qgain)
> +{
> +	ddbwritel(dev, ((u32)qgain << 16) | igain, IQOUTPUT_POSTSCALER);
> +}
> +
> +static int set_base_frequency(struct ddb *dev, u32 freq)
> +{
> +	u32 Ext = 40;
> +        u32 UP1Frequency = 290;
> +        u32 UP2Frequency = 1896;
> +	u32 down, freq10;
> +
> +	printk("set base to %u\n", freq);
> +	dev->mod_base.frequency = freq;
> +	freq /= 1000000;
> +        freq10 = dev->mod_base.flat_start + 4;
> +	down = freq + 9 * 8 + freq10 + UP1Frequency + UP2Frequency;
> +
> +        if ((freq10 + 9 * 8) > (dev->mod_base.flat_end - 4)) {
> +		printk("Frequency out of range %d\n", freq10);
> +		return -EINVAL;
> +        }
> +        if (down % 8) {
> +		printk(" Invalid Frequency %d\n", down);
> +		return -EINVAL;
> +        }
> +	return mod_set_down(dev, down, 8, Ext);
> +}
> +
> +static int mod_init(struct ddb *dev, u32 Frequency)
> +{
> +	int stat = 0;
> +	u8 *buffer;
> +	struct DDMOD_FLASH *flash;
> +	u32 Ext = 40;
> +        u32 UP1Frequency = 290;
> +        u32 UP2Frequency = 1896;
> +	u32 DownFrequency;
> +        u32 FrequencyCH10;
> +	u32 iqfreq, iqsteps, i;
> +
> +	buffer = kmalloc(4096, GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +	flash = (struct DDMOD_FLASH *) buffer;
> +	
> +	ddbridge_flashread(dev, buffer, DDMOD_FLASH_START, 4096);
> +	
> +	if (flash->Magic != DDMOD_FLASH_MAGIC && flash->Magic != 1) {
> +		stat = -EINVAL;
> +		goto fail;
> +	}
> +	printk("srate = %d\n", flash->DataSet[0].Symbolrate * 1000);
> +
> +	mod_output_enable(dev, 0);
> +	stat = mod_set_dac_clock(dev, flash->DataSet[0].DACFrequency * 1000);
> +	if (stat < 0) {
> +		printk("setting DAC clock failed\n");
> +		goto fail;
> +	}
> +	mod_set_dac_current(dev, 512, 512);
> +
> +	ddbwritel(dev, flash->DataSet[0].Control2, IQOUTPUT_CONTROL2);	
> +
> +	mod_set_up1(dev, UP1Frequency, 5, Ext);
> +	mod_set_up2(dev, UP2Frequency, 8, Ext);
> +
> +        dev->mod_base.flat_start = flash->DataSet[0].FlatStart;
> +        dev->mod_base.flat_end = flash->DataSet[0].FlatEnd;
> +	
> +	Frequency /= 1000000;
> +        FrequencyCH10 = flash->DataSet[0].FlatStart + 4;
> +	DownFrequency = Frequency + 9 * 8 + FrequencyCH10 + UP1Frequency + UP2Frequency;
> +	printk("CH10 = %d, Down = %d\n", FrequencyCH10, DownFrequency);
> +
> +
> +        if ((FrequencyCH10 + 9 * 8) > (flash->DataSet[0].FlatEnd - 4)) {
> +		printk("Frequency out of range %d\n", FrequencyCH10);
> +		stat = -EINVAL;
> +		goto fail;
> +        }
> +
> +        if (DownFrequency % 8 != 0 ) {
> +		printk(" Invalid Frequency %d\n", DownFrequency);
> +		stat = -EINVAL;
> +		goto fail;
> +        }
> +
> +	mod_set_down(dev, DownFrequency, 8, Ext);
> +
> +	for (i = 0; i < 10; i++) {
> +		ddbwritel(dev, 0, CHANNEL_CONTROL(i));
> +		
> +		iqfreq = flash->DataSet[0].FrequencyFactor * (FrequencyCH10 + (9 - i) * 8);
> +		iqsteps = flash->DataSet[0].IQTableLength;
> +		mod_set_iq(dev, iqsteps, i, iqfreq);
> +
> +		dev->mod[i].modulation = QAM_256;
> +	}
> +	
> +	mod_bypass_equalizer(dev, 1);
> +	mod_set_equalizer(dev, 11, flash->DataSet[0].EQTap);
> +	mod_bypass_equalizer(dev, 0);
> +	mod_post_eq_gain(dev, flash->DataSet[0].PostScaleI, flash->DataSet[0].PostScaleQ);
> +	mod_pre_eq_gain(dev, flash->DataSet[0].PreScale);
> +	// mod_pre_eq_gain(dev, 0x0680);
> +	printk("prescaler %04x\n", flash->DataSet[0].PreScale);
> +	mod_set_channelsumshift(dev, 2);
> +	mod_output_enable(dev, 1);
> +
> +	// mod_set_attenuator(dev, 10);
> +fail:
> +	kfree(buffer);
> +	return stat;
> +}
> +
> +
> +void ddbridge_mod_rate_handler(unsigned long data)
> +{
> +	struct ddb_output *output = (struct ddb_output *) data;
> +	struct ddb_dma *dma = output->dma;
> +	struct ddb *dev = output->port->dev;
> +	struct mod_state *mod= &dev->mod[output->nr];
> +	
> +	u32 chan = output->nr;
> +	u32 OutPacketCount;
> +	u32 InPacketCount;
> +	u64 OutPackets, InPackets;
> +	s64 PCRAdjust;
> +	u32 PCRAdjustExt, PCRAdjustExtFrac, InPacketDiff, OutPacketDiff;
> +	s32 PCRCorr;
> +
> +	s64 pcr;
> +	s64 PCRIncrementDiff;
> +	s64 PCRIncrement;
> +	u64 mul;
> +
> +	if (!mod->do_handle)
> +		return;
> +	printk("rate_handler\n");
> +
> +	spin_lock(&dma->lock);
> +	ddbwritel(dev, mod->Control | CHANNEL_CONTROL_FREEZE_STATUS,
> +		  CHANNEL_CONTROL(output->nr));
> +	
> +	OutPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_OUT(chan));
> +	if (OutPacketCount < mod->LastOutPacketCount )
> +		mod->OutOverflowPacketCount += 1;
> +	mod->LastOutPacketCount = OutPacketCount;
> +
> +	InPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_IN(chan));
> +	if (InPacketCount < mod->LastInPacketCount )
> +		mod->InOverflowPacketCount += 1;
> +	mod->LastInPacketCount = InPacketCount;
> +	
> +	OutPackets = ((u64) (mod->OutOverflowPacketCount) << 20) | OutPacketCount;
> +	InPackets = ((u64) (mod->InOverflowPacketCount) << 20) | InPacketCount;
> +	
> +	PCRAdjust = (s64) ((u64) ddbreadl(dev, CHANNEL_PCR_ADJUST_ACCUL(chan)) | 
> +			   (((u64) ddbreadl(dev, CHANNEL_PCR_ADJUST_ACCUH(chan)) << 32)));
> +	PCRAdjustExt = (u32)((PCRAdjust & 0x7FFFFFFF) >> 22);
> +	PCRAdjustExtFrac = (u32)((PCRAdjust & 0x003FFFFF) >> 12);
> +	PCRAdjust >>= 31;
> +	InPacketDiff = (u32) (InPackets - mod->LastInPackets);
> +	OutPacketDiff = (u32) (OutPackets - mod->LastOutPackets);
> +	PCRCorr = 0;
> +	
> +	switch (mod->State) {
> +	case CM_STARTUP:
> +		if (mod->StateCounter) {
> +			if (mod->StateCounter == 1) {
> +				mul = (0x1000000 * (u64) (OutPacketDiff - InPacketDiff - InPacketDiff/1000));
> +				if (OutPacketDiff)
> +					mod->rate_inc = div_u64(mul, OutPacketDiff);
> +				else
> +					mod->rate_inc = 0;
> +				printk("RI %08x\n", mod->rate_inc);
> +				ddbwritel(dev, 	mod->rate_inc, CHANNEL_RATE_INCR(output->nr));
> +				mod_busy(dev, output->nr);
> +// #define PACKET_CLOCKS  (27000000ULL*1504)
> +// #define FACTOR  (1024<<12)
> +// double Increment =  FACTOR*PACKET_CLOCKS/double(m_OutputBitrate);
> +// double Decrement =  FACTOR*PACKET_CLOCKS/double(m_InputBitrate);
> +				mod->PCRIncrement = 3348148758ULL;
> +				if (InPacketDiff)
> +					mod->PCRDecrement = div_u64(3348148758ULL * (u64) OutPacketDiff, 
> +								    InPacketDiff); 
> +				else
> +					mod->PCRDecrement = 0;
> +				mod_set_incs(output);
> +			}
> +			mod->StateCounter--; 
> +			break;
> +		}
> +		if (InPacketDiff >= mod->MinInputPackets) {
> +			mod->State = CM_ADJUST;
> +			mod->Control |= CHANNEL_CONTROL_ENABLE_PCRADJUST;
> +			mod->InPacketsSum = 0;
> +			mod->OutPacketsSum = 0;
> +			mod->PCRAdjustSum = 0;
> +			mod->StateCounter = CM_AVERAGE;
> +		}
> +		break;
> +		
> +	case CM_ADJUST:
> +		if (InPacketDiff < mod->MinInputPackets) {
> +			printk("PCR Adjust reset  IN: %u  Min: %u\n",
> +			       InPacketDiff, mod->MinInputPackets);
> +			mod->InPacketsSum = 0;
> +			mod->OutPacketsSum = 0;
> +			mod->PCRAdjustSum = 0;
> +			mod->StateCounter = CM_AVERAGE;
> +			ddbwritel(dev, 
> +				  (mod->Control | CHANNEL_CONTROL_FREEZE_STATUS) & 
> +				  ~CHANNEL_CONTROL_ENABLE_PCRADJUST,
> +				  CHANNEL_CONTROL(chan));
> +			break;
> +		} 
> +
> +		mod->PCRAdjustSum += (s32) PCRAdjust;
> +		mod->InPacketsSum += InPacketDiff;
> +		mod->OutPacketsSum += OutPacketDiff;
> +		if (mod->StateCounter--) 
> +			break;
> +
> +		if (mod->OutPacketsSum)
> +			PCRIncrement = div_s64((s64)mod->InPacketsSum * 
> +					       (s64)mod->PCRDecrement + 
> +					       (s64)(mod->OutPacketsSum >> 1) ,
> +					       mod->OutPacketsSum);
> +		else
> +			PCRIncrement = 0;
> +		
> +		if( mod->PCRAdjustSum > 0 ) 
> +			PCRIncrement = RoundPCRDown(PCRIncrement);
> +		else    
> +			PCRIncrement = RoundPCRUp(PCRIncrement);
> +		
> +		PCRIncrementDiff = PCRIncrement - mod->PCRIncrement;
> +		if( PCRIncrementDiff > HW_LSB_MASK )
> +			PCRIncrementDiff = HW_LSB_MASK;
> +		if( PCRIncrementDiff < -HW_LSB_MASK ) 
> +			PCRIncrementDiff = -HW_LSB_MASK;
> +		
> +		mod->PCRIncrement += PCRIncrementDiff;
> +		pcr = ConvertPCR(mod->PCRIncrement);
> +		printk("outl %016llx\n", pcr);
> +		ddbwritel(dev, 	pcr & 0xffffffff, 
> +			  CHANNEL_PCR_ADJUST_OUTL(output->nr));
> +		ddbwritel(dev, 	(pcr >> 32) & 0xffffffff, 
> +			  CHANNEL_PCR_ADJUST_OUTH(output->nr));
> +		mod_busy(dev, chan);
> +
> +		PCRCorr = (s32) (PCRIncrementDiff >> HW_LSB_SHIFT);
> +		mod->PCRRunningCorr += PCRCorr;
> +		
> +		mod->InPacketsSum = 0;
> +		mod->OutPacketsSum = 0;
> +		mod->PCRAdjustSum = 0;
> +		mod->StateCounter = CM_AVERAGE;
> +		break;
> +		
> +	default:
> +		break;
> +	}
> +	ddbwritel(dev, mod->Control, CHANNEL_CONTROL(chan));
> +	
> +	mod->LastInPackets = InPackets;
> +	mod->LastOutPackets = OutPackets;
> +	mod->LastPCRAdjust = (s32) PCRAdjust;
> +
> +	printk("chan %d out %016llx in %016llx indiff %08x\n", chan, OutPackets, InPackets, InPacketDiff);
> +	printk("cnt  %d pcra %016llx pcraext %08x pcraextfrac %08x pcrcorr %08x pcri %016llx\n", 
> +	       mod->StateCounter, PCRAdjust, PCRAdjustExt, PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement);
> +	// Channel,OutPackets,InPackets,InPacketDiff,PCRAdjust,PCRAdjustExt,PCRAdjustExtFrac,PCRCorr, mod->PCRRunningCorr,mod->StateCounter ));
> +	spin_unlock(&dma->lock);
> +}
> +	      
> +int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
> +{
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb *dev = output->port->dev;
> +	
> +	// unsigned long arg = (unsigned long) parg;
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case DVB_MOD_SET:
> +	{
> +		struct dvb_mod_params *mp = parg;
> +		
> +		if (mp->base_frequency != dev->mod_base.frequency)
> +			if (set_base_frequency(dev, mp->base_frequency))
> +				return -EINVAL;
> +		mod_set_attenuator(dev, mp->attenuator);
> +		break;
> +	}
> +	case DVB_MOD_CHANNEL_SET:
> +	{
> +		struct dvb_mod_channel_params *cp = parg;
> +
> +		if (cp->modulation > QAM_256)
> +			return -EINVAL;
> +		dev->mod[output->nr].modulation = cp->modulation;
> +		dev->mod[output->nr].rate_inc = cp->rate_increment;
> +		ddbwritel(dev, dev->mod[output->nr].rate_inc, CHANNEL_RATE_INCR(output->nr));
> +		break;
> +	}

Here, you have a new undocumented API. It should be properly documented.

Also, the IOCTL handling logic should, be implemented at the core, of course
providing ways for ddbridge-mod to register their functions to select the
modulation type and parameters to enable/disable the modulator, and to
provide mpeg TS streams for it.


> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +int ddbridge_mod_init(struct ddb *dev)
> +{
> +	return mod_init(dev, 722000000);
> +}


-- 

Cheers,
Mauro

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

* Re: [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends
  2013-11-03  9:23   ` Mauro Carvalho Chehab
@ 2013-11-03 10:47     ` Ralph Metzler
  2013-11-03 11:22       ` Mauro Carvalho Chehab
  2013-11-03 12:20       ` Maik Broemme
  0 siblings, 2 replies; 39+ messages in thread
From: Ralph Metzler @ 2013-11-03 10:47 UTC (permalink / raw)
  To: Linux Media Mailing List

Mauro Carvalho Chehab writes:
 > Em Sun, 3 Nov 2013 01:24:25 +0100
 > Maik Broemme <mbroemme@parallels.com> escreveu:
 > 
 > > Added support for DVB-C2 to DVB frontends. It will be required
 > > by cxd2843 and tda18212dd (Digital Devices) frontends.
 > > 
 > > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
 > > ---
 > >  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 */
 > 
 > Please update also the documentation, at Documentation/DocBook/media/dvb.
 > 
 > Doesn't DVB-C2 provide any newer property? If so, please add it there as
 > well, and at frontend.h.
 > 

I asked about this on linux-media a week or so ago. The main question was
concerning STREAM_ID. I asked if it would be fine to combine PLP and
slice id (each 8 bit) into stream_id or if there should be a separate 
new property. And for which one, PLP or slice id? 
Probably slice id, because stream_id is also used for PLP in T2?
I combined them into stream_id for now (but that was after the 0.9.10 version
of the dddvb package).

There are also many new qam types, etc. but, as I said back then, it was not  
urgent for me to add those because the Sony demod does not allow setting those.
At least it is not documented how to do it.


Regards,
Ralph

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

* Re: [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10
  2013-11-03  0:44 ` [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10 Maik Broemme
@ 2013-11-03 10:49   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:49 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:44:32 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Updated ddbridge driver to version 0.9.10.

Kernel maintainers and driver reviewers really hate this kind of patches ;)

We really prefer incremental changes, as we can better identify potential
regressions on it, what changed, etc.

So, please try to break this change into smaller, incremental ones, to
help us to better review it.

Also, please be sure that the driver will compile fine (and work) after each
change, as breaking compilation is forbidden at the Kernel (as it breaks
git bisect for everybody). Also, breaking runtime execution is bad, as it
will make your life like hell when bugs get reported, and your users can't
rely on git bisect to pinpoint what change broke support for him.

Regards,
Mauro

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/pci/ddbridge/ddbridge-core.c | 3085 ++++++++++++++++++++--------
>  1 file changed, 2236 insertions(+), 849 deletions(-)
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
> index 9375f30..1d8ee74 100644
> --- a/drivers/media/pci/ddbridge/ddbridge-core.c
> +++ b/drivers/media/pci/ddbridge/ddbridge-core.c
> @@ -1,284 +1,216 @@
>  /*
> - * ddbridge.c: Digital Devices PCIe bridge driver
> + *  ddbridge-core.c: Digital Devices PCIe bridge driver
>   *
> - * Copyright (C) 2010-2011 Digital Devices GmbH
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
>   *
> - * 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 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.
>   *
> - * 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
> + *  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
>   */
>  
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/interrupt.h>
> -#include <linux/delay.h>
> -#include <linux/slab.h>
> -#include <linux/poll.h>
> -#include <linux/io.h>
> -#include <linux/pci.h>
> -#include <linux/pci_ids.h>
> -#include <linux/timer.h>
> -#include <linux/i2c.h>
> -#include <linux/swab.h>
> -#include <linux/vmalloc.h>
>  #include "ddbridge.h"
> -
>  #include "ddbridge-regs.h"
>  
> -#include "tda18271c2dd.h"
> +#include "cxd2843.h"
> +#include "lnbh24.h"
>  #include "stv6110x.h"
>  #include "stv090x.h"
> -#include "lnbh24.h"
> +#include "tda18212dd.h"
> +#include "stv0367dd.h"
> +#ifdef CONFIG_DVB_TDA18212
> +#include "tda18212.h"
> +#endif
> +#ifdef CONFIG_DVB_DRXK
>  #include "drxk.h"
> +#include "tda18271c2dd.h"
> +#endif
>  
> -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
> -
> -/* MSI had problems with lost interrupts, fixed but needs testing */
> -#undef CONFIG_PCI_MSI
> +static DEFINE_MUTEX(redirect_lock);
>  
> -/******************************************************************************/
> +static struct workqueue_struct *ddb_wq;
> +static int adapter_alloc;
>  
> -static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
> -{
> -	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
> -				   .buf  = val,  .len   = 1 } };
> -	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
> -}
> +module_param(adapter_alloc, int, 0444);
> +MODULE_PARM_DESC(adapter_alloc, "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
>  
> -static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
> -{
> -	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
> -				   .buf  = &reg, .len   = 1 },
> -				  {.addr = adr,  .flags = I2C_M_RD,
> -				   .buf  = val,  .len   = 1 } };
> -	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> -}
> +static int ci_bitrate = 72000;
> +module_param(ci_bitrate, int, 0444);
> +MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI.");
>  
> -static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
> -			  u16 reg, u8 *val)
> -{
> -	u8 msg[2] = {reg>>8, reg&0xff};
> -	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
> -				   .buf  = msg, .len   = 2},
> -				  {.addr = adr, .flags = I2C_M_RD,
> -				   .buf  = val, .len   = 1} };
> -	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> -}
> +static int ts_loop = -1;
> +module_param(ts_loop, int, 0444);
> +MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop");
>  
> -static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
> -{
> -	struct ddb *dev = i2c->dev;
> -	int stat;
> -	u32 val;
> +#define DDB_MAX_ADAPTER 32
> +static struct ddb *ddbs[DDB_MAX_ADAPTER];
>  
> -	i2c->done = 0;
> -	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
> -	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
> -	if (stat <= 0) {
> -		printk(KERN_ERR "I2C timeout\n");
> -		{ /* MSI debugging*/
> -			u32 istat = ddbreadl(INTERRUPT_STATUS);
> -			printk(KERN_ERR "IRS %08x\n", istat);
> -			ddbwritel(istat, INTERRUPT_ACK);
> -		}
> -		return -EIO;
> -	}
> -	val = ddbreadl(i2c->regs+I2C_COMMAND);
> -	if (val & 0x70000)
> -		return -EIO;
> -	return 0;
> -}
> +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>  
> -static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
> -			       struct i2c_msg msg[], int num)
> +static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
>  {
> -	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
> -	struct ddb *dev = i2c->dev;
> -	u8 addr = 0;
> -
> -	if (num)
> -		addr = msg[0].addr;
> -
> -	if (num == 2 && msg[1].flags & I2C_M_RD &&
> -	    !(msg[0].flags & I2C_M_RD)) {
> -		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
> -			    msg[0].buf, msg[0].len);
> -		ddbwritel(msg[0].len|(msg[1].len << 16),
> -			  i2c->regs+I2C_TASKLENGTH);
> -		if (!ddb_i2c_cmd(i2c, addr, 1)) {
> -			memcpy_fromio(msg[1].buf,
> -				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
> -				      msg[1].len);
> -			return num;
> -		}
> -	}
> +	u32 i, base;
> +	u64 mem;
>  
> -	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
> -		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
> -		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
> -		if (!ddb_i2c_cmd(i2c, addr, 2))
> -			return num;
> -	}
> -	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
> -		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
> -		if (!ddb_i2c_cmd(i2c, addr, 3)) {
> -			ddbcpyfrom(msg[0].buf,
> -				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
> -			return num;
> -		}
> +	if (!dma)
> +		return;
> +	base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100;
> +	for (i = 0; i < dma->num; i++) {
> +		mem = dma->pbuf[i];
> +		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
> +		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
>  	}
> -	return -EIO;
> +	dma->bufreg = (dma->div << 16) | 
> +		((dma->num & 0x1f) << 11) | 
> +		((dma->size >> 7) & 0x7ff);
>  }
>  
> -
> -static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
> +static void ddb_set_dma_tables(struct ddb *dev)
>  {
> -	return I2C_FUNC_SMBUS_EMUL;
> -}
> +	u32 i;
>  
> -struct i2c_algorithm ddb_i2c_algo = {
> -	.master_xfer   = ddb_i2c_master_xfer,
> -	.functionality = ddb_i2c_functionality,
> -};
> +	for (i = 0; i < dev->info->port_num * 2; i++)
> +		ddb_set_dma_table(dev, dev->input[i].dma);
> +	for (i = 0; i < dev->info->port_num; i++)
> +		ddb_set_dma_table(dev, dev->output[i].dma);
> +}
>  
> -static void ddb_i2c_release(struct ddb *dev)
> +static void ddb_redirect_dma(struct ddb *dev,
> +			     struct ddb_dma *sdma,
> +			     struct ddb_dma *ddma)
>  {
> -	int i;
> -	struct ddb_i2c *i2c;
> -	struct i2c_adapter *adap;
> +	u32 i, base;
> +	u64 mem;
>  
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		i2c = &dev->i2c[i];
> -		adap = &i2c->adap;
> -		i2c_del_adapter(adap);
> +	sdma->bufreg = ddma->bufreg;
> +	base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100;
> +	for (i = 0; i < ddma->num; i++) {
> +		mem = ddma->pbuf[i];
> +		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
> +		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
>  	}
>  }
>  
> -static int ddb_i2c_init(struct ddb *dev)
> +static int ddb_unredirect(struct ddb_port *port)
>  {
> -	int i, j, stat = 0;
> -	struct ddb_i2c *i2c;
> -	struct i2c_adapter *adap;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		i2c = &dev->i2c[i];
> -		i2c->dev = dev;
> -		i2c->nr = i;
> -		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
> -		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
> -		i2c->regs = 0x80 + i * 0x20;
> -		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
> -		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
> -			  i2c->regs + I2C_TASKADDRESS);
> -		init_waitqueue_head(&i2c->wq);
> -
> -		adap = &i2c->adap;
> -		i2c_set_adapdata(adap, i2c);
> -#ifdef I2C_ADAP_CLASS_TV_DIGITAL
> -		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
> -#else
> -#ifdef I2C_CLASS_TV_ANALOG
> -		adap->class = I2C_CLASS_TV_ANALOG;
> -#endif
> -#endif
> -		strcpy(adap->name, "ddbridge");
> -		adap->algo = &ddb_i2c_algo;
> -		adap->algo_data = (void *)i2c;
> -		adap->dev.parent = &dev->pdev->dev;
> -		stat = i2c_add_adapter(adap);
> -		if (stat)
> -			break;
> +	struct ddb_input *oredi, *iredi = 0;
> +	struct ddb_output *iredo = 0;
> +	
> +	// printk("unredirect %d.%d\n", port->dev->nr, port->nr);
> +	mutex_lock(&redirect_lock);
> +	if (port->output->dma->running) {
> +		mutex_unlock(&redirect_lock);
> +		return -EBUSY;
>  	}
> -	if (stat)
> -		for (j = 0; j < i; j++) {
> -			i2c = &dev->i2c[j];
> -			adap = &i2c->adap;
> -			i2c_del_adapter(adap);
> -		}
> -	return stat;
> +	oredi = port->output->redi;
> +	if (!oredi)
> +		goto done;
> +	if (port->input[0]) {
> +		iredi = port->input[0]->redi;
> +		iredo = port->input[0]->redo;
> +		
> +		if (iredo) {
> +			iredo->port->output->redi = oredi;
> +			if (iredo->port->input[0]) {
> +				iredo->port->input[0]->redi = iredi;
> +				ddb_redirect_dma(oredi->port->dev, 
> +						 oredi->dma, iredo->dma);
> +			}
> +			port->input[0]->redo = 0;
> +			ddb_set_dma_table(port->dev, port->input[0]->dma);
> +		} 
> +		oredi->redi = iredi;
> +		port->input[0]->redi = 0;
> +	}
> +	oredi->redo = 0;
> +	port->output->redi = 0;
> +
> +	ddb_set_dma_table(oredi->port->dev, oredi->dma);
> +done:
> +	mutex_unlock(&redirect_lock);
> +	return 0;
>  }
>  
> +static int ddb_redirect(u32 i, u32 p)
> +{
> +	struct ddb *idev = ddbs[(i >> 4) & 0x1f];
> +	struct ddb_input *input, *input2;
> +	struct ddb *pdev = ddbs[(p >> 4) & 0x1f];
> +	struct ddb_port *port;
>  
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> +	if (!idev->has_dma || !pdev->has_dma)
> +		return -EINVAL;
> +	if (!idev || !pdev)
> +		return -EINVAL;
>  
> -#if 0
> -static void set_table(struct ddb *dev, u32 off,
> -		      dma_addr_t *pbuf, u32 num)
> -{
> -	u32 i, base;
> -	u64 mem;
> +	port = &pdev->port[p & 0x0f];
> +	if (!port->output)
> +		return -EINVAL;
> +	if (ddb_unredirect(port))
> +		return -EBUSY;
>  
> -	base = DMA_BASE_ADDRESS_TABLE + off;
> -	for (i = 0; i < num; i++) {
> -		mem = pbuf[i];
> -		ddbwritel(mem & 0xffffffff, base + i * 8);
> -		ddbwritel(mem >> 32, base + i * 8 + 4);
> -	}
> -}
> -#endif
> +	if (i == 8)
> +		return 0;
>  
> -static void ddb_address_table(struct ddb *dev)
> -{
> -	u32 i, j, base;
> -	u64 mem;
> -	dma_addr_t *pbuf;
> -
> -	for (i = 0; i < dev->info->port_num * 2; i++) {
> -		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
> -		pbuf = dev->input[i].pbuf;
> -		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
> -			mem = pbuf[j];
> -			ddbwritel(mem & 0xffffffff, base + j * 8);
> -			ddbwritel(mem >> 32, base + j * 8 + 4);
> -		}
> +	input = &idev->input[i & 7];
> +	if (!input) 
> +		return -EINVAL;
> +
> +	mutex_lock(&redirect_lock);
> +	if (port->output->dma->running || input->dma->running) {
> +		mutex_unlock(&redirect_lock);
> +		return -EBUSY;
>  	}
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
> -		pbuf = dev->output[i].pbuf;
> -		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
> -			mem = pbuf[j];
> -			ddbwritel(mem & 0xffffffff, base + j * 8);
> -			ddbwritel(mem >> 32, base + j * 8 + 4);
> -		}
> +	if ((input2 = port->input[0])) {
> +		if (input->redi) {
> +			input2->redi = input->redi;
> +			input->redi = 0;
> +		} else
> +			input2->redi = input;
>  	}
> +	input->redo = port->output;
> +	port->output->redi = input;
> +
> +	ddb_redirect_dma(input->port->dev, input->dma, port->output->dma);
> +	mutex_unlock(&redirect_lock);
> +	return 0;
>  }
>  
> -static void io_free(struct pci_dev *pdev, u8 **vbuf,
> -		    dma_addr_t *pbuf, u32 size, int num)
> +static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
>  {
>  	int i;
>  
> -	for (i = 0; i < num; i++) {
> -		if (vbuf[i]) {
> -			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
> -			vbuf[i] = 0;
> +	if (!dma)
> +		return;
> +	for (i = 0; i < dma->num; i++) {
> +		if (dma->vbuf[i]) {
> +			pci_free_consistent(pdev, dma->size,
> +					    dma->vbuf[i], dma->pbuf[i]);
> +			dma->vbuf[i] = 0;
>  		}
>  	}
>  }
>  
> -static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
> -		    dma_addr_t *pbuf, u32 size, int num)
> +static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
>  {
>  	int i;
>  
> -	for (i = 0; i < num; i++) {
> -		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
> -		if (!vbuf[i])
> +	if (!dma)
> +		return 0;
> +	for (i = 0; i < dma->num; i++) {
> +		dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size,
> +						    &dma->pbuf[i]);
> +		if (!dma->vbuf[i])
>  			return -ENOMEM;
>  	}
>  	return 0;
> @@ -293,34 +225,24 @@ static int ddb_buffers_alloc(struct ddb *dev)
>  		port = &dev->port[i];
>  		switch (port->class) {
>  		case DDB_PORT_TUNER:
> -			if (io_alloc(dev->pdev, port->input[0]->vbuf,
> -				     port->input[0]->pbuf,
> -				     port->input[0]->dma_buf_size,
> -				     port->input[0]->dma_buf_num) < 0)
> +			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
>  				return -1;
> -			if (io_alloc(dev->pdev, port->input[1]->vbuf,
> -				     port->input[1]->pbuf,
> -				     port->input[1]->dma_buf_size,
> -				     port->input[1]->dma_buf_num) < 0)
> +			if (dma_alloc(dev->pdev, port->input[1]->dma, 0) < 0)
>  				return -1;
>  			break;
>  		case DDB_PORT_CI:
> -			if (io_alloc(dev->pdev, port->input[0]->vbuf,
> -				     port->input[0]->pbuf,
> -				     port->input[0]->dma_buf_size,
> -				     port->input[0]->dma_buf_num) < 0)
> +		case DDB_PORT_LOOP:
> +			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
>  				return -1;
> -			if (io_alloc(dev->pdev, port->output->vbuf,
> -				     port->output->pbuf,
> -				     port->output->dma_buf_size,
> -				     port->output->dma_buf_num) < 0)
> +		case DDB_PORT_MOD:
> +			if (dma_alloc(dev->pdev, port->output->dma, 1) < 0)
>  				return -1;
>  			break;
>  		default:
>  			break;
>  		}
>  	}
> -	ddb_address_table(dev);
> +	ddb_set_dma_tables(dev);
>  	return 0;
>  }
>  
> @@ -328,112 +250,171 @@ static void ddb_buffers_free(struct ddb *dev)
>  {
>  	int i;
>  	struct ddb_port *port;
> -
> +	
>  	for (i = 0; i < dev->info->port_num; i++) {
>  		port = &dev->port[i];
> -		io_free(dev->pdev, port->input[0]->vbuf,
> -			port->input[0]->pbuf,
> -			port->input[0]->dma_buf_size,
> -			port->input[0]->dma_buf_num);
> -		io_free(dev->pdev, port->input[1]->vbuf,
> -			port->input[1]->pbuf,
> -			port->input[1]->dma_buf_size,
> -			port->input[1]->dma_buf_num);
> -		io_free(dev->pdev, port->output->vbuf,
> -			port->output->pbuf,
> -			port->output->dma_buf_size,
> -			port->output->dma_buf_num);
> +		
> +		if (port->input[0])
> +			dma_free(dev->pdev, port->input[0]->dma, 0);
> +		if (port->input[1])
> +			dma_free(dev->pdev, port->input[1]->dma, 0);
> +		if (port->output)
> +			dma_free(dev->pdev, port->output->dma, 1);
>  	}
>  }
>  
> -static void ddb_input_start(struct ddb_input *input)
> +static void ddb_output_start(struct ddb_output *output)
>  {
> -	struct ddb *dev = input->port->dev;
> +	struct ddb *dev = output->port->dev;
> +	u32 con2;
>  
> -	spin_lock_irq(&input->lock);
> -	input->cbuf = 0;
> -	input->coff = 0;
> +	con2 = ((output->port->obr << 13) + 71999) / 72000; 
> +	con2 = (con2 << 16) | output->port->gap;
>  
> -	/* reset */
> -	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
> -	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
> -	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
> +	if (output->dma) {
> +		spin_lock_irq(&output->dma->lock);
> +		output->dma->cbuf = 0;
> +		output->dma->coff = 0;
> +		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
> +	}
> +	if (output->port->class == DDB_PORT_MOD) 
> +		ddbridge_mod_output_start(output);
> +	else {
> +		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
> +		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr));
> +		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
> +		ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr));
> +		ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr));
> +	}
> +	if (output->dma) {
> +		ddbwritel(dev, output->dma->bufreg, DMA_BUFFER_SIZE(output->dma->nr));
> +		ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
> +		ddbwritel(dev, 1, DMA_BASE_READ);
> +		ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr));
> +	}
> +	if (output->port->class != DDB_PORT_MOD) {
> +		if (output->port->input[0]->port->class == DDB_PORT_LOOP)
> +			// ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr));
> +			// ddbwritel(dev, 0x45, TS_OUTPUT_CONTROL(output->nr));
> +			ddbwritel(dev, (1 << 13) | 0x15, TS_OUTPUT_CONTROL(output->nr));
> +		else
> +			ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr));
> +	}
> +	if (output->dma) { 
> +		output->dma->running = 1;
> +		spin_unlock_irq(&output->dma->lock);
> +	}
> +}
>  
> -	ddbwritel((1 << 16) |
> -		  (input->dma_buf_num << 11) |
> -		  (input->dma_buf_size >> 7),
> -		  DMA_BUFFER_SIZE(input->nr));
> -	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
> +static void ddb_output_stop(struct ddb_output *output)
> +{
> +	struct ddb *dev = output->port->dev;
>  
> -	ddbwritel(1, DMA_BASE_WRITE);
> -	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
> -	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
> -	input->running = 1;
> -	spin_unlock_irq(&input->lock);
> +	if (output->dma)
> +		spin_lock_irq(&output->dma->lock);
> +	if (output->port->class == DDB_PORT_MOD) 
> +		ddbridge_mod_output_stop(output);
> +	else
> +		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
> +	if (output->dma) {
> +		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
> +		output->dma->running = 0;
> +		spin_unlock_irq(&output->dma->lock);
> +	}
>  }
>  
>  static void ddb_input_stop(struct ddb_input *input)
>  {
>  	struct ddb *dev = input->port->dev;
>  
> -	spin_lock_irq(&input->lock);
> -	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
> -	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
> -	input->running = 0;
> -	spin_unlock_irq(&input->lock);
> +	if (input->dma)
> +		spin_lock_irq(&input->dma->lock);
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
> +	if (input->dma) {
> +		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
> +		input->dma->running = 0;
> +		spin_unlock_irq(&input->dma->lock);
> +	}
> +	// printk("input_stop %d.%d\n", dev->nr, input->nr);
>  }
>  
> -static void ddb_output_start(struct ddb_output *output)
> +static void ddb_input_start(struct ddb_input *input)
>  {
> -	struct ddb *dev = output->port->dev;
> +	struct ddb *dev = input->port->dev;
>  
> -	spin_lock_irq(&output->lock);
> -	output->cbuf = 0;
> -	output->coff = 0;
> -	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
> -	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
> -	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
> -	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
> -	ddbwritel((1 << 16) |
> -		  (output->dma_buf_num << 11) |
> -		  (output->dma_buf_size >> 7),
> -		  DMA_BUFFER_SIZE(output->nr + 8));
> -	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
> -
> -	ddbwritel(1, DMA_BASE_READ);
> -	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
> -	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
> -	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
> -	output->running = 1;
> -	spin_unlock_irq(&output->lock);
> +	if (input->dma) {
> +		spin_lock_irq(&input->dma->lock);
> +		input->dma->cbuf = 0;
> +		input->dma->coff = 0;
> +		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
> +	}
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL2(input->nr));
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
> +	ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr));
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
> +
> +	if (input->dma) {
> +		ddbwritel(dev, input->dma->bufreg, DMA_BUFFER_SIZE(input->dma->nr));
> +		ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
> +		ddbwritel(dev, 1, DMA_BASE_WRITE);
> +		ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr));
> +	}
> +	if (dev->info->type == DDB_OCTONET) 
> +		ddbwritel(dev, 0x01, TS_INPUT_CONTROL(input->nr));
> +	else
> +		ddbwritel(dev, 0x09, TS_INPUT_CONTROL(input->nr));
> +	if (input->dma) {
> +		input->dma->running = 1;
> +		spin_unlock_irq(&input->dma->lock);
> +	}
> +	// printk("input_start %d.%d\n", dev->nr, input->nr);
>  }
>  
> -static void ddb_output_stop(struct ddb_output *output)
> +static void ddb_input_start_all(struct ddb_input *input)
>  {
> -	struct ddb *dev = output->port->dev;
> +	struct ddb_input *i = input;
> +	struct ddb_output *o;
> +	
> +	mutex_lock(&redirect_lock);
> +	while (i && (o = i->redo)) {
> +		ddb_output_start(o);
> +		if ((i = o->port->input[0]))
> +			ddb_input_start(i);
> +	}
> +	ddb_input_start(input);
> +	mutex_unlock(&redirect_lock);
> +}
>  
> -	spin_lock_irq(&output->lock);
> -	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
> -	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
> -	output->running = 0;
> -	spin_unlock_irq(&output->lock);
> +static void ddb_input_stop_all(struct ddb_input *input)
> +{
> +	struct ddb_input *i = input;
> +	struct ddb_output *o;
> +	
> +	mutex_lock(&redirect_lock);
> +	ddb_input_stop(input);
> +	while (i && (o = i->redo)) {
> +		ddb_output_stop(o);
> +		if ((i = o->port->input[0]))
> +			ddb_input_stop(i);
> +	}
> +	mutex_unlock(&redirect_lock);
>  }
>  
>  static u32 ddb_output_free(struct ddb_output *output)
>  {
> -	u32 idx, off, stat = output->stat;
> +	u32 idx, off, stat = output->dma->stat;
>  	s32 diff;
>  
>  	idx = (stat >> 11) & 0x1f;
>  	off = (stat & 0x7ff) << 7;
> -
> -	if (output->cbuf != idx) {
> -		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
> -		    (output->dma_buf_size - output->coff <= 188))
> + 
> +	if (output->dma->cbuf != idx) {
> +		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
> +		    (output->dma->size - output->dma->coff <= 188))
>  			return 0;
>  		return 188;
>  	}
> -	diff = off - output->coff;
> +	diff = off - output->dma->coff;
>  	if (diff <= 0 || diff > 188)
>  		return 188;
>  	return 0;
> @@ -443,46 +424,46 @@ static ssize_t ddb_output_write(struct ddb_output *output,
>  				const u8 *buf, size_t count)
>  {
>  	struct ddb *dev = output->port->dev;
> -	u32 idx, off, stat = output->stat;
> +	u32 idx, off, stat = output->dma->stat;
>  	u32 left = count, len;
>  
>  	idx = (stat >> 11) & 0x1f;
>  	off = (stat & 0x7ff) << 7;
>  
>  	while (left) {
> -		len = output->dma_buf_size - output->coff;
> -		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
> +		len = output->dma->size - output->dma->coff;
> +		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
>  		    (off == 0)) {
>  			if (len <= 188)
>  				break;
>  			len -= 188;
>  		}
> -		if (output->cbuf == idx) {
> -			if (off > output->coff) {
> -#if 1
> -				len = off - output->coff;
> +		if (output->dma->cbuf == idx) {
> +			if (off > output->dma->coff) {
> +				len = off - output->dma->coff;
>  				len -= (len % 188);
>  				if (len <= 188)
> -
> -#endif
>  					break;
>  				len -= 188;
>  			}
>  		}
>  		if (len > left)
>  			len = left;
> -		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
> +		if (copy_from_user(output->dma->vbuf[output->dma->cbuf] +
> +				   output->dma->coff,
>  				   buf, len))
>  			return -EIO;
>  		left -= len;
>  		buf += len;
> -		output->coff += len;
> -		if (output->coff == output->dma_buf_size) {
> -			output->coff = 0;
> -			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
> +		output->dma->coff += len;
> +		if (output->dma->coff == output->dma->size) {
> +			output->dma->coff = 0;
> +			output->dma->cbuf = ((output->dma->cbuf + 1) %
> +					     output->dma->num);
>  		}
> -		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
> -			  DMA_BUFFER_ACK(output->nr + 8));
> +		ddbwritel(dev, 
> +			  (output->dma->cbuf << 11) | (output->dma->coff >> 7),
> +			  DMA_BUFFER_ACK(output->dma->nr));
>  	}
>  	return count - left;
>  }
> @@ -490,139 +471,410 @@ static ssize_t ddb_output_write(struct ddb_output *output,
>  static u32 ddb_input_avail(struct ddb_input *input)
>  {
>  	struct ddb *dev = input->port->dev;
> -	u32 idx, off, stat = input->stat;
> -	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
> +	u32 idx, off, stat = input->dma->stat;
> +	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr));
>  
>  	idx = (stat >> 11) & 0x1f;
>  	off = (stat & 0x7ff) << 7;
>  
>  	if (ctrl & 4) {
>  		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
> -		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
> +		ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr));
>  		return 0;
>  	}
> -	if (input->cbuf != idx)
> +	if (input->dma->cbuf != idx || off < input->dma->coff)
>  		return 188;
>  	return 0;
>  }
>  
> -static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
> +static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
>  {
>  	struct ddb *dev = input->port->dev;
>  	u32 left = count;
> -	u32 idx, free, stat = input->stat;
> +	u32 idx, off, free, stat = input->dma->stat;
>  	int ret;
>  
>  	idx = (stat >> 11) & 0x1f;
> +	off = (stat & 0x7ff) << 7;
>  
>  	while (left) {
> -		if (input->cbuf == idx)
> +		if (input->dma->cbuf == idx)
>  			return count - left;
> -		free = input->dma_buf_size - input->coff;
> +		free = input->dma->size - input->dma->coff;
>  		if (free > left)
>  			free = left;
> -		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
> -				   input->coff, free);
> +		ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] +
> +				   input->dma->coff, free);
>  		if (ret)
>  			return -EFAULT;
> -		input->coff += free;
> -		if (input->coff == input->dma_buf_size) {
> -			input->coff = 0;
> -			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
> +		input->dma->coff += free;
> +		if (input->dma->coff == input->dma->size) {
> +			input->dma->coff = 0;
> +			input->dma->cbuf = (input->dma->cbuf + 1) %
> +				input->dma->num;
>  		}
>  		left -= free;
> -		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
> -			  DMA_BUFFER_ACK(input->nr));
> +		ddbwritel(dev, 
> +			  (input->dma->cbuf << 11) | (input->dma->coff >> 7),
> +			  DMA_BUFFER_ACK(input->dma->nr));
>  	}
>  	return count;
>  }
>  
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> +static ssize_t ts_write(struct file *file, const char *buf,
> +			size_t count, loff_t *ppos)
> +{
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb *dev = output->port->dev;
> +	size_t left = count;
> +	int stat;
> +
> +	if (!dev->has_dma)
> +		return -EINVAL;
> +	while (left) {
> +		if (ddb_output_free(output) < 188) {
> +			if (file->f_flags & O_NONBLOCK) 
> +				break;
> +			if (wait_event_interruptible(
> +				    output->dma->wq,
> +				    ddb_output_free(output) >= 188) < 0) 
> +				break;
> +		}
> +		stat = ddb_output_write(output, buf, left);
> +		if (stat < 0)
> +			return stat;
> +		buf += stat;
> +		left -= stat;
> +	}
> +	return (left == count) ? -EAGAIN : (count - left);
> +}
> +
> +static ssize_t ts_read(struct file *file, char *buf,
> +		       size_t count, loff_t *ppos)
> +{
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb_input *input = output->port->input[0];
> +	struct ddb *dev = output->port->dev;
> +	int left, read;
> +
> +	if (!dev->has_dma)
> +		return -EINVAL;
> +	count -= count % 188;
> +	left = count;
> +	while (left) {
> +		if (ddb_input_avail(input) < 188) {
> +			if (file->f_flags & O_NONBLOCK)
> +				break;
> +			if (wait_event_interruptible(
> +				    input->dma->wq, 
> +				    ddb_input_avail(input) >= 188) < 0)
> +				break;
> +		}
> +		read = ddb_input_read(input, buf, left);
> +		left -= read;
> +		buf += read;
> +	}
> +	return (left == count) ? -EAGAIN : (count - left);
> +}
>  
> -#if 0
> -static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
> +static unsigned int ts_poll(struct file *file, poll_table *wait)
>  {
> -	int i;
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb_input *input = output->port->input[0];
> +
> +	unsigned int mask = 0;
> +
> +	poll_wait(file, &input->dma->wq, wait);
> +	poll_wait(file, &output->dma->wq, wait);
> +	if (ddb_input_avail(input) >= 188)
> +		mask |= POLLIN | POLLRDNORM;
> +	if (ddb_output_free(output) >= 188)
> +		mask |= POLLOUT | POLLWRNORM;
> +	return mask;
> +}
> +
> +static int ts_release(struct inode *inode, struct file *file)
> +{
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb_input *input = output->port->input[0];
> +	
> +	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
> +		if (!input)
> +			return -EINVAL;
> +		ddb_input_stop(input);
> +	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
> +		if (!output)
> +			return -EINVAL;
> +		ddb_output_stop(output);
> +	}
> +	return dvb_generic_release(inode, file);
> +}
>  
> -	for (i = 0; i < dev->info->port_num * 2; i++) {
> -		if (dev->input[i].fe == fe)
> -			return &dev->input[i];
> +static int ts_open(struct inode *inode, struct file *file)
> +{
> +	int err;
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	struct ddb_input *input = output->port->input[0];
> +	
> +	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
> +		if (!input)
> +			return -EINVAL;
> +		if (input->redo || input->redi)
> +			return -EBUSY;
> +	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
> +		if (!output)
> +			return -EINVAL;
>  	}
> -	return NULL;
> +	if ((err = dvb_generic_open(inode, file)) < 0)
> +		return err;
> +	if ((file->f_flags & O_ACCMODE) == O_RDONLY) 
> +		ddb_input_start(input);
> +	else if ((file->f_flags & O_ACCMODE) == O_WRONLY) 
> +		ddb_output_start(output);
> +	return err;
>  }
> -#endif
>  
> -static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
> +static int mod_release(struct inode *inode, struct file *file)
> +{
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	
> +	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
> +		if (!output)
> +			return -EINVAL;
> +		ddb_output_stop(output);
> +	}
> +	return dvb_generic_release(inode, file);
> +}
> +
> +static int mod_open(struct inode *inode, struct file *file)
> +{
> +	int err;
> +	struct dvb_device *dvbdev = file->private_data;
> +	struct ddb_output *output = dvbdev->priv;
> +	
> +	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
> +		if (!output)
> +			return -EINVAL;
> +	}
> +	if ((err = dvb_generic_open(inode, file)) < 0)
> +		return err;
> +	if ((file->f_flags & O_ACCMODE) == O_WRONLY) 
> +		ddb_output_start(output);
> +	return err;
> +}
> +static const struct file_operations ci_fops = {
> +	.owner   = THIS_MODULE,
> +	.read    = ts_read,
> +	.write   = ts_write,
> +	.open    = ts_open,
> +	.release = ts_release,
> +	.poll    = ts_poll,
> +	.mmap    = 0,
> +};
> +
> +static struct dvb_device dvbdev_ci = {
> +	.priv    = 0,
> +	.readers = 1,
> +	.writers = 1,
> +	.users   = 2,
> +	.fops    = &ci_fops,
> +};
> +
> +static long mod_ioctl(struct file *file,
> +		      unsigned int cmd, unsigned long arg)
> +{
> +	return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
> +}
> +
> +static const struct file_operations mod_fops = {
> +	.owner   = THIS_MODULE,
> +	.read    = ts_read,
> +	.write   = ts_write,
> +	.open    = mod_open,
> +	.release = mod_release,
> +	.poll    = ts_poll,
> +	.mmap    = 0,
> +	.unlocked_ioctl = mod_ioctl,
> +};
> +
> +static struct dvb_device dvbdev_mod = {
> +	.priv    = 0,
> +	.readers = 1,
> +	.writers = 1,
> +	.users   = 2,
> +	.fops    = &mod_fops,
> +};
> +
> +static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
>  {
>  	struct ddb_input *input = fe->sec_priv;
>  	struct ddb_port *port = input->port;
> +	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
>  	int status;
>  
>  	if (enable) {
>  		mutex_lock(&port->i2c_gate_lock);
> -		status = input->gate_ctrl(fe, 1);
> +		status = dvb->gate_ctrl(fe, 1); 
>  	} else {
> -		status = input->gate_ctrl(fe, 0);
> +		status = dvb->gate_ctrl(fe, 0);
>  		mutex_unlock(&port->i2c_gate_lock);
>  	}
>  	return status;
>  }
>  
> +#ifdef CONFIG_DVB_DRXK
>  static int demod_attach_drxk(struct ddb_input *input)
>  {
>  	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  	struct dvb_frontend *fe;
> -	struct drxk_config config;
>  
> -	memset(&config, 0, sizeof(config));
> -	config.microcode_name = "drxk_a3.mc";
> -	config.qam_demod_parameter_count = 4;
> -	config.adr = 0x29 + (input->nr & 1);
> -
> -	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
> -	if (!input->fe) {
> +	fe = dvb->fe = dvb_attach(drxk_attach,
> +				  i2c, 0x29 + (input->nr&1),
> +				  &dvb->fe2);
> +	if (!fe) {
>  		printk(KERN_ERR "No DRXK found!\n");
>  		return -ENODEV;
>  	}
>  	fe->sec_priv = input;
> -	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
> -	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
> +	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
> +	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
>  	return 0;
>  }
> +#endif
>  
> -static int tuner_attach_tda18271(struct ddb_input *input)
> +struct cxd2843_cfg cxd2843_0 = {
> +	.adr = 0x6c,
> +};
> +
> +struct cxd2843_cfg cxd2843_1 = {
> +	.adr = 0x6d,
> +};
> +
> +static int demod_attach_cxd2843(struct ddb_input *input)
>  {
>  	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  	struct dvb_frontend *fe;
> -
> -	if (input->fe->ops.i2c_gate_ctrl)
> -		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
> -	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
> -	if (!fe) {
> -		printk(KERN_ERR "No TDA18271 found!\n");
> +	
> +	fe = dvb->fe = dvb_attach(cxd2843_attach, i2c,
> +				  (input->nr & 1) ? &cxd2843_1 : &cxd2843_0);
> +	if (!dvb->fe) {
> +		printk(KERN_ERR "No cxd2843 found!\n");
>  		return -ENODEV;
>  	}
> -	if (input->fe->ops.i2c_gate_ctrl)
> -		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
> +	fe->sec_priv = input;
> +	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
> +	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
>  	return 0;
>  }
>  
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> +struct stv0367_cfg stv0367dd_0 = {
> +	.adr = 0x1f,
> +	.xtal = 27000000,
> +};
>  
> -static struct stv090x_config stv0900 = {
> -	.device         = STV0900,
> -	.demod_mode     = STV090x_DUAL,
> -	.clk_mode       = STV090x_CLK_EXT,
> +struct stv0367_cfg stv0367dd_1 = {
> +	.adr = 0x1e,
> +	.xtal = 27000000,
> +};
>  
> -	.xtal           = 27000000,
> -	.address        = 0x69,
> +static int demod_attach_stv0367dd(struct ddb_input *input)
> +{
> +	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
> +	struct dvb_frontend *fe;
>  
> -	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> -	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> +	fe = dvb->fe = dvb_attach(stv0367_attach, i2c,
> +				  (input->nr & 1) ? &stv0367dd_1 : &stv0367dd_0,
> +				  &dvb->fe2);
> +	if (!dvb->fe) {
> +		printk(KERN_ERR "No stv0367 found!\n");
> +		return -ENODEV;
> +	}
> +	fe->sec_priv = input;
> +	dvb->gate_ctrl = fe->ops.i2c_gate_ctrl;
> +	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
> +	return 0;
> +}
> +
> +#ifdef CONFIG_DVB_DRXK
> +static int tuner_attach_tda18271(struct ddb_input *input)
> +{
> +	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
> +	struct dvb_frontend *fe;
> +
> +	if (dvb->fe->ops.i2c_gate_ctrl)
> +		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1);
> +	fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60);
> +	if (dvb->fe->ops.i2c_gate_ctrl)
> +		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0);
> +	if (!fe) {
> +		printk(KERN_ERR "No TDA18271 found!\n");
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +#endif
> +
> +static int tuner_attach_tda18212dd(struct ddb_input *input)
> +{
> +	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
> +	struct dvb_frontend *fe;
> +
> +	fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c,
> +			(input->nr & 1) ? 0x63 : 0x60);
> +	if (!fe) {
> +		printk(KERN_ERR "No TDA18212 found!\n");
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +
> +#ifdef CONFIG_DVB_TDA18212
> +struct tda18212_config tda18212_0 = {
> +	.i2c_address = 0x60,
> +};
> +
> +struct tda18212_config tda18212_1 = {
> +	.i2c_address = 0x63,
> +};
> +
> +static int tuner_attach_tda18212(struct ddb_input *input)
> +{
> +	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
> +	struct dvb_frontend *fe;
> +	struct tda18212_config *cfg;
> +
> +	cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0;
> +	fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg);
> +	if (!fe) {
> +		printk(KERN_ERR "No TDA18212 found!\n");
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +#endif
> +
> +static struct stv090x_config stv0900 = {
> +	.device         = STV0900,
> +	.demod_mode     = STV090x_DUAL,
> +	.clk_mode       = STV090x_CLK_EXT,
> +
> +	.xtal           = 27000000,
> +	.address        = 0x69,
> +
> +	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> +	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
>  
>  	.repeater_level = STV090x_RPTLEVEL_16,
>  
> @@ -667,15 +919,16 @@ static int demod_attach_stv0900(struct ddb_input *input, int type)
>  {
>  	struct i2c_adapter *i2c = &input->port->i2c->adap;
>  	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  
> -	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
> -			       (input->nr & 1) ? STV090x_DEMODULATOR_1
> -			       : STV090x_DEMODULATOR_0);
> -	if (!input->fe) {
> +	dvb->fe = dvb_attach(stv090x_attach, feconf, i2c,
> +			     (input->nr & 1) ? STV090x_DEMODULATOR_1
> +			     : STV090x_DEMODULATOR_0);
> +	if (!dvb->fe) {
>  		printk(KERN_ERR "No STV0900 found!\n");
>  		return -ENODEV;
>  	}
> -	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
> +	if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0,
>  			0, (input->nr & 1) ?
>  			(0x09 - type) : (0x0b - type))) {
>  		printk(KERN_ERR "No LNBH24 found!\n");
> @@ -687,18 +940,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type)
>  static int tuner_attach_stv6110(struct ddb_input *input, int type)
>  {
>  	struct i2c_adapter *i2c = &input->port->i2c->adap;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
>  	struct stv6110x_config *tunerconf = (input->nr & 1) ?
>  		&stv6110b : &stv6110a;
>  	struct stv6110x_devctl *ctl;
>  
> -	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
> +	ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c);
>  	if (!ctl) {
>  		printk(KERN_ERR "No STV6110X found!\n");
>  		return -ENODEV;
>  	}
>  	printk(KERN_INFO "attach tuner input %d adr %02x\n",
> -			 input->nr, tunerconf->addr);
> +	       input->nr, tunerconf->addr);
>  
>  	feconf->tuner_init          = ctl->tuner_init;
>  	feconf->tuner_sleep         = ctl->tuner_sleep;
> @@ -716,9 +970,9 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type)
>  }
>  
>  static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
> -			    int (*start_feed)(struct dvb_demux_feed *),
> -			    int (*stop_feed)(struct dvb_demux_feed *),
> -			    void *priv)
> +				   int (*start_feed)(struct dvb_demux_feed *),
> +				   int (*stop_feed)(struct dvb_demux_feed *),
> +				   void *priv)
>  {
>  	dvbdemux->priv = priv;
>  
> @@ -734,10 +988,10 @@ static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
>  }
>  
>  static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
> -			       struct dvb_demux *dvbdemux,
> -			       struct dmx_frontend *hw_frontend,
> -			       struct dmx_frontend *mem_frontend,
> -			       struct dvb_adapter *dvb_adapter)
> +				      struct dvb_demux *dvbdemux,
> +				      struct dmx_frontend *hw_frontend,
> +				      struct dmx_frontend *mem_frontend,
> +				      struct dvb_adapter *dvb_adapter)
>  {
>  	int ret;
>  
> @@ -759,318 +1013,610 @@ static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
>  {
>  	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
>  	struct ddb_input *input = dvbdmx->priv;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  
> -	if (!input->users)
> -		ddb_input_start(input);
> +	if (!dvb->users)
> +		ddb_input_start_all(input);
>  
> -	return ++input->users;
> +	return ++dvb->users;
>  }
>  
>  static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
>  {
>  	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
>  	struct ddb_input *input = dvbdmx->priv;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  
> -	if (--input->users)
> -		return input->users;
> +	if (--dvb->users)
> +		return dvb->users;
>  
> -	ddb_input_stop(input);
> +	ddb_input_stop_all(input);
>  	return 0;
>  }
>  
> -
>  static void dvb_input_detach(struct ddb_input *input)
>  {
> -	struct dvb_adapter *adap = &input->adap;
> -	struct dvb_demux *dvbdemux = &input->demux;
> -
> -	switch (input->attached) {
> -	case 5:
> -		if (input->fe2)
> -			dvb_unregister_frontend(input->fe2);
> -		if (input->fe) {
> -			dvb_unregister_frontend(input->fe);
> -			dvb_frontend_detach(input->fe);
> -			input->fe = NULL;
> -		}
> -	case 4:
> -		dvb_net_release(&input->dvbnet);
> -
> -	case 3:
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
> +	struct dvb_demux *dvbdemux = &dvb->demux;
> +
> +	switch (dvb->attached) {
> +	case 0x31:
> +		if (dvb->fe2)
> +			dvb_unregister_frontend(dvb->fe2);
> +		if (dvb->fe)
> +			dvb_unregister_frontend(dvb->fe);
> +	case 0x30:
> +		dvb_frontend_detach(dvb->fe);
> +		dvb->fe = dvb->fe2 = NULL;
> +	case 0x20:
> +		dvb_net_release(&dvb->dvbnet);
> +	case 0x11:
>  		dvbdemux->dmx.close(&dvbdemux->dmx);
>  		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
> -					      &input->hw_frontend);
> +					      &dvb->hw_frontend);
>  		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
> -					      &input->mem_frontend);
> -		dvb_dmxdev_release(&input->dmxdev);
> +					      &dvb->mem_frontend);
> +		dvb_dmxdev_release(&dvb->dmxdev);
> +	case 0x10:
> +		dvb_dmx_release(&dvb->demux);
> +	case 0x01:
> +		break;
> +	}
> +	dvb->attached = 0x00;
> +}
> +
> +static int dvb_register_adapters(struct ddb *dev)
> +{
> +	int i, ret = 0;
> +	struct ddb_port *port;
> +	struct dvb_adapter *adap;
> +
> +	if (adapter_alloc == 3 || dev->info->type == DDB_MOD) {
> +		port = &dev->port[0];
> +		adap = port->dvb[0].adap;
> +		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
> +					   port->dev->dev,
> +					   adapter_nr);
> +		if (ret < 0)
> +			return ret;
> +		port->dvb[0].adap_registered = 1;
> +		for (i = 0; i < dev->info->port_num; i++) {
> +			port = &dev->port[i];
> +			port->dvb[0].adap = adap;
> +			port->dvb[1].adap = adap;
> +		}
> +		return 0;
> +	}
> +
> +	for (i = 0; i < dev->info->port_num; i++) {
> +		port = &dev->port[i];
> +		switch (port->class) {
> +		case DDB_PORT_TUNER:
> +			adap = port->dvb[0].adap;
> +			ret = dvb_register_adapter(adap, "DDBridge", 
> +						   THIS_MODULE,
> +						   port->dev->dev,
> +						   adapter_nr);
> +			if (ret < 0)
> +				return ret;
> +			port->dvb[0].adap_registered = 1;
> +
> +			if (adapter_alloc > 0) {
> +				port->dvb[1].adap = port->dvb[0].adap;
> +				break;
> +			}
> +			adap = port->dvb[1].adap;
> +			ret = dvb_register_adapter(adap, "DDBridge", 
> +						   THIS_MODULE,
> +						   port->dev->dev,
> +						   adapter_nr);
> +			if (ret < 0)
> +				return ret;
> +			port->dvb[1].adap_registered = 1;
> +			break;
> +
> +		case DDB_PORT_CI:
> +		case DDB_PORT_LOOP:
> +			adap = port->dvb[0].adap;
> +			ret = dvb_register_adapter(adap, "DDBridge",
> +						   THIS_MODULE,
> +						   port->dev->dev,
> +						   adapter_nr);
> +			if (ret < 0)
> +				return ret;
> +			port->dvb[0].adap_registered = 1;
> +			break;
> +		default:
> +			if (adapter_alloc < 2)
> +				break;
> +			adap = port->dvb[0].adap;
> +			ret = dvb_register_adapter(adap, "DDBridge",
> +						   THIS_MODULE,
> +						   port->dev->dev,
> +						   adapter_nr);
> +			if (ret < 0)
> +				return ret;
> +			port->dvb[0].adap_registered = 1;
> +			break;
> +		}
> +	}
> +	return ret;
> +}
> +
> +static void dvb_unregister_adapters(struct ddb *dev)
> +{
> +	int i;
> +	struct ddb_port *port;
> +	struct ddb_dvb *dvb;
>  
> -	case 2:
> -		dvb_dmx_release(&input->demux);
> +	for (i = 0; i < dev->info->port_num; i++) {
> +		port = &dev->port[i];
>  
> -	case 1:
> -		dvb_unregister_adapter(adap);
> +		dvb = &port->dvb[0];
> +		if (dvb->adap_registered)
> +			dvb_unregister_adapter(dvb->adap);
> +		dvb->adap_registered = 0;
> +		
> +		dvb = &port->dvb[1];
> +		if (dvb->adap_registered)
> +			dvb_unregister_adapter(dvb->adap);
> +		dvb->adap_registered = 0;
>  	}
> -	input->attached = 0;
>  }
>  
>  static int dvb_input_attach(struct ddb_input *input)
>  {
> -	int ret;
> +	int ret = 0;
> +	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
>  	struct ddb_port *port = input->port;
> -	struct dvb_adapter *adap = &input->adap;
> -	struct dvb_demux *dvbdemux = &input->demux;
> -
> -	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
> -				   &input->port->dev->pdev->dev,
> -				   adapter_nr);
> -	if (ret < 0) {
> -		printk(KERN_ERR "ddbridge: Could not register adapter."
> -		       "Check if you enabled enough adapters in dvb-core!\n");
> -		return ret;
> -	}
> -	input->attached = 1;
> +	struct dvb_adapter *adap = dvb->adap;
> +	struct dvb_demux *dvbdemux = &dvb->demux;
> +
> +	dvb->attached = 0x01;
>  
>  	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
>  				      start_feed,
>  				      stop_feed, input);
>  	if (ret < 0)
>  		return ret;
> -	input->attached = 2;
> +	dvb->attached = 0x10;
>  
> -	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
> -					 &input->hw_frontend,
> -					 &input->mem_frontend, adap);
> +	ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev,
> +					 &dvb->demux,
> +					 &dvb->hw_frontend,
> +					 &dvb->mem_frontend, adap);
>  	if (ret < 0)
>  		return ret;
> -	input->attached = 3;
> +	dvb->attached = 0x11;
>  
> -	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
> +	ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux);
>  	if (ret < 0)
>  		return ret;
> -	input->attached = 4;
> +	dvb->attached = 0x20;
>  
> -	input->fe = 0;
> +	dvb->fe = dvb->fe2 = 0;
>  	switch (port->type) {
>  	case DDB_TUNER_DVBS_ST:
>  		if (demod_attach_stv0900(input, 0) < 0)
>  			return -ENODEV;
>  		if (tuner_attach_stv6110(input, 0) < 0)
>  			return -ENODEV;
> -		if (input->fe) {
> -			if (dvb_register_frontend(adap, input->fe) < 0)
> -				return -ENODEV;
> -		}
>  		break;
>  	case DDB_TUNER_DVBS_ST_AA:
>  		if (demod_attach_stv0900(input, 1) < 0)
>  			return -ENODEV;
>  		if (tuner_attach_stv6110(input, 1) < 0)
>  			return -ENODEV;
> -		if (input->fe) {
> -			if (dvb_register_frontend(adap, input->fe) < 0)
> -				return -ENODEV;
> -		}
>  		break;
> +#ifdef CONFIG_DVB_DRXK
>  	case DDB_TUNER_DVBCT_TR:
>  		if (demod_attach_drxk(input) < 0)
>  			return -ENODEV;
>  		if (tuner_attach_tda18271(input) < 0)
>  			return -ENODEV;
> -		if (input->fe) {
> -			if (dvb_register_frontend(adap, input->fe) < 0)
> -				return -ENODEV;
> -		}
> -		if (input->fe2) {
> -			if (dvb_register_frontend(adap, input->fe2) < 0)
> -				return -ENODEV;
> -			input->fe2->tuner_priv = input->fe->tuner_priv;
> -			memcpy(&input->fe2->ops.tuner_ops,
> -			       &input->fe->ops.tuner_ops,
> -			       sizeof(struct dvb_tuner_ops));
> -		}
>  		break;
> +#endif
> +	case DDB_TUNER_DVBCT_ST:
> +		if (demod_attach_stv0367dd(input) < 0)
> +			return -ENODEV;
> +		if (tuner_attach_tda18212dd(input) < 0)
> +			return -ENODEV;
> +		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_tda18212dd(input) < 0)
> +			return -ENODEV;
> +		break;
> +	default:
> +		return 0;
> +	}
> +	dvb->attached = 0x30;
> +	if (dvb->fe) {
> +		if (dvb_register_frontend(adap, dvb->fe) < 0)
> +			return -ENODEV;
> +	}
> +	if (dvb->fe2) {
> +		if (dvb_register_frontend(adap, dvb->fe2) < 0)
> +			return -ENODEV;
> +		dvb->fe2->tuner_priv = dvb->fe->tuner_priv;
> +		memcpy(&dvb->fe2->ops.tuner_ops,
> +		       &dvb->fe->ops.tuner_ops,
> +		       sizeof(struct dvb_tuner_ops));
>  	}
> -	input->attached = 5;
> +	dvb->attached = 0x31;
>  	return 0;
>  }
>  
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static ssize_t ts_write(struct file *file, const char *buf,
> -			size_t count, loff_t *ppos)
> +static int port_has_encti(struct ddb_port *port)
>  {
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	size_t left = count;
> -	int stat;
> +	u8 val;
> +	int ret = ddb_i2c_read_reg(&port->i2c->adap, 0x20, 0, &val);
>  
> -	while (left) {
> -		if (ddb_output_free(output) < 188) {
> -			if (file->f_flags & O_NONBLOCK)
> -				break;
> -			if (wait_event_interruptible(
> -				    output->wq, ddb_output_free(output) >= 188) < 0)
> -				break;
> -		}
> -		stat = ddb_output_write(output, buf, left);
> -		if (stat < 0)
> -			break;
> -		buf += stat;
> -		left -= stat;
> -	}
> -	return (left == count) ? -EAGAIN : (count - left);
> +	if (!ret) 
> +		printk("[0x20]=0x%02x\n", val);
> +
> +	return ret ? 0 : 1;
>  }
>  
> -static ssize_t ts_read(struct file *file, char *buf,
> -		       size_t count, loff_t *ppos)
> +static int port_has_cxd(struct ddb_port *port)
>  {
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	struct ddb_input *input = output->port->input[0];
> -	int left, read;
> +	u8 val;
> +	u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; 
> +	struct i2c_msg msgs[2] = {{ .addr = 0x40,  .flags = 0,
> +				    .buf  = probe, .len   = 4 },
> +				  { .addr = 0x40,  .flags = I2C_M_RD,
> +				    .buf  = data,  .len   = 4 }};
> +	val = i2c_transfer(&port->i2c->adap, msgs, 2);
> +	if (val != 2)
> +		return 0;
>  
> -	count -= count % 188;
> -	left = count;
> -	while (left) {
> -		if (ddb_input_avail(input) < 188) {
> -			if (file->f_flags & O_NONBLOCK)
> -				break;
> -			if (wait_event_interruptible(
> -				    input->wq, ddb_input_avail(input) >= 188) < 0)
> -				break;
> -		}
> -		read = ddb_input_read(input, buf, left);
> -		if (read < 0)
> -			return read;
> -		left -= read;
> -		buf += read;
> -	}
> -	return (left == count) ? -EAGAIN : (count - left);
> +	if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43)
> +		return 2;
> +	return 1;
>  }
>  
> -static unsigned int ts_poll(struct file *file, poll_table *wait)
> +static int port_has_mach(struct ddb_port *port, u8 *id)
>  {
> -	/*
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	struct ddb_input *input = output->port->input[0];
> -	*/
> -	unsigned int mask = 0;
> +	u8 val;
> +	u8 probe[1] = { 0x00 }, data[4]; 
> +	struct i2c_msg msgs[2] = {{ .addr = 0x10,  .flags = 0,
> +				    .buf  = probe, .len   = 1 },
> +				  { .addr = 0x10,  .flags = I2C_M_RD,
> +				    .buf  = data,  .len   = 4 }};
> +	val = i2c_transfer(&port->i2c->adap, msgs, 2);
> +	if (val != 2)
> +		return 0;
> +	
> +	if (data[0] != 'D' || data[1] != 'F')
> +		return 0;
>  
> -#if 0
> -	if (data_avail_to_read)
> -		mask |= POLLIN | POLLRDNORM;
> -	if (data_avail_to_write)
> -		mask |= POLLOUT | POLLWRNORM;
> +	*id = data[2];
> +	return 1;
> +}
>  
> -	poll_wait(file, &read_queue, wait);
> -	poll_wait(file, &write_queue, wait);
> -#endif
> -	return mask;
> +static int port_has_stv0900(struct ddb_port *port)
> +{
> +	u8 val;
> +	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
> +		return 0;
> +	return 1;
>  }
>  
> -static const struct file_operations ci_fops = {
> -	.owner   = THIS_MODULE,
> -	.read    = ts_read,
> -	.write   = ts_write,
> -	.open    = dvb_generic_open,
> -	.release = dvb_generic_release,
> -	.poll    = ts_poll,
> -	.mmap    = 0,
> -};
> +static int port_has_stv0900_aa(struct ddb_port *port)
> +{
> +	u8 val;
> +	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
> +		return 0;
> +	return 1;
> +}
>  
> -static struct dvb_device dvbdev_ci = {
> -	.priv    = 0,
> -	.readers = -1,
> -	.writers = -1,
> -	.users   = -1,
> -	.fops    = &ci_fops,
> -};
> +static int port_has_drxks(struct ddb_port *port)
> +{
> +	u8 val;
> +	if (ddb_i2c_read(&port->i2c->adap, 0x29, &val) < 0)
> +		return 0;
> +	if (ddb_i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
> +		return 0;
> +	return 1;
> +}
>  
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> +static int port_has_stv0367(struct ddb_port *port)
> +{
> +	u8 val;
> +
> +	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0)
> +		return 0;
> +	if (val != 0x60)
> +		return 0;
> +	if (ddb_i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0)
> +		return 0;
> +	if (val != 0x60)
> +		return 0;
> +	return 1;
> +}
>  
> -static void input_tasklet(unsigned long data)
> +static int init_xo2(struct ddb_port *port)
>  {
> -	struct ddb_input *input = (struct ddb_input *) data;
> -	struct ddb *dev = input->port->dev;
> +	struct i2c_adapter *i2c =&port->i2c->adap;
> +	u8 val, data[2];
> +	int res;
> +	
> +	res = ddb_i2c_read_regs(i2c, 0x10, 0x04, data, 2);
> +	if (res < 0)
> +		return res;
>  
> -	spin_lock(&input->lock);
> -	if (!input->running) {
> -		spin_unlock(&input->lock);
> -		return;
> +	if (data[0] != 0x01)  {
> +		printk(KERN_INFO "Port %d: invalid XO2\n", port->nr);
> +		return -1;
>  	}
> -	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
>  
> -	if (input->port->class == DDB_PORT_TUNER) {
> -		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
> -			printk(KERN_ERR "Overflow input %d\n", input->nr);
> -		while (input->cbuf != ((input->stat >> 11) & 0x1f)
> -		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
> -			dvb_dmx_swfilter_packets(&input->demux,
> -						 input->vbuf[input->cbuf],
> -						 input->dma_buf_size / 188);
> -
> -			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
> -			ddbwritel((input->cbuf << 11),
> -				  DMA_BUFFER_ACK(input->nr));
> -			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
> -		       }
> +	ddb_i2c_read_reg(i2c, 0x10, 0x08, &val);
> +	if (val != 0) {
> +		ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x00); 
> +		msleep(100);
>  	}
> -	if (input->port->class == DDB_PORT_CI)
> -		wake_up(&input->wq);
> -	spin_unlock(&input->lock);
> +        /* Enable tuner power, disable pll, reset demods */
> +	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x04); 
> +	msleep(2);
> +        /* Release demod resets */
> +	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x07); 
> +	msleep(2);
> +
> +        /* Start XO2 PLL */
> +	ddb_i2c_write_reg(i2c, 0x10, 0x08, 0x87); 
> +
> +	return 0;
>  }
>  
> -static void output_tasklet(unsigned long data)
> +static void ddb_port_probe(struct ddb_port *port)
>  {
> -	struct ddb_output *output = (struct ddb_output *) data;
> -	struct ddb *dev = output->port->dev;
> +	struct ddb *dev = port->dev;
> +	char *modname = "NO MODULE";
> +	int val;
> +	u8 id;
> +
> +	port->class = DDB_PORT_NONE;
>  
> -	spin_lock(&output->lock);
> -	if (!output->running) {
> -		spin_unlock(&output->lock);
> +	if (dev->info->type == DDB_MOD) {
> +		modname = "MOD";
> +		port->class = DDB_PORT_MOD;
> +		printk(KERN_INFO "Port %d: MOD\n", port->nr);
>  		return;
>  	}
> -	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
> -	wake_up(&output->wq);
> -	spin_unlock(&output->lock);
> -}
>  
> +	if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) {
> +		modname = "CI internal";
> +		port->class = DDB_PORT_CI;
> +		port->type = DDB_CI_INTERNAL;
> +	} else if ((val = port_has_cxd(port)) > 0) {
> +		if (val == 1) {
> +			modname = "CI";
> +			port->class = DDB_PORT_CI;
> +			port->type = DDB_CI_EXTERNAL_SONY;
> +			ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> +		} else {
> +			printk(KERN_INFO "Port %d: Uninitialized DuoFlex\n", port->nr);
> +			return;
> +		}
> +	} else if (port_has_mach(port, &id)) {
> +		char *xo2names[] = { "DUAL DVB-S2", "DUAL DVB-C/T/T2", "DUAL DVB-ISDBT",
> +		                     "DUAL DVB-C/C2/T/T2", "DUAL ATSC", "DUAL DVB-C/C2/T/T2" };
> +
> +		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> +		id >>= 2;
> +		if (id > 5) {
> +			modname = "unknown XO2 DuoFlex";
> +		} else {
> +			port->class = DDB_PORT_TUNER;
> +			port->type = DDB_TUNER_XO2 + id;
> +			modname = xo2names[id];
> +			init_xo2(port);
> +		}
> +	} else if (port_has_stv0900(port)) {
> +		modname = "DUAL DVB-S2";
> +		port->class = DDB_PORT_TUNER;
> +		port->type = DDB_TUNER_DVBS_ST;
> +		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
> +	} else if (port_has_stv0900_aa(port)) {
> +		modname = "DUAL DVB-S2";
> +		port->class = DDB_PORT_TUNER;
> +		port->type = DDB_TUNER_DVBS_ST_AA;
> +		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
> +	} else if (port_has_drxks(port)) {
> +		modname = "DUAL DVB-C/T";
> +		port->class = DDB_PORT_TUNER;
> +		port->type = DDB_TUNER_DVBCT_TR;
> +		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> +	} else if (port_has_stv0367(port)) {
> +		modname = "DUAL DVB-C/T";
> +		port->class = DDB_PORT_TUNER;
> +		port->type = DDB_TUNER_DVBCT_ST;
> +		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
> +	} else if (port_has_encti(port)) {
> +		modname = "ENCTI";
> +		port->class = DDB_PORT_LOOP;
> +	} else if (port->nr == ts_loop) {
> +		modname = "TS LOOP";
> +		port->class = DDB_PORT_LOOP;
> +	}
> +	printk(KERN_INFO "Port %d (TAB %d): %s\n", port->nr, port->nr + 1, modname);
> +}
>  
> -struct cxd2099_cfg cxd_cfg = {
> -	.bitrate =  62000,
> -	.adr     =  0x40,
> -	.polarity = 1,
> -	.clock_mode = 1,
> -};
> +static int wait_ci_ready(struct ddb_ci *ci)
> +{
> +	u32 count = 10;
> +	
> +	ndelay(500);
> +	do {
> +		if (ddbreadl(ci->port->dev, 
> +			     CI_CONTROL(ci->nr)) & CI_READY)
> +			break;
> +		usleep_range(1, 2);
> +		if ((--count) == 0)
> +			return -1;
> +	} while (1);
> +	return 0;
> +}
>  
> -static int ddb_ci_attach(struct ddb_port *port)
> +static int read_attribute_mem(struct dvb_ca_en50221 *ca,
> +			      int slot, int address)
>  {
> -	int ret;
> +	struct ddb_ci *ci = ca->data;
> +	u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1);
>  
> -	ret = dvb_register_adapter(&port->output->adap,
> -				   "DDBridge",
> -				   THIS_MODULE,
> -				   &port->dev->pdev->dev,
> -				   adapter_nr);
> -	if (ret < 0)
> -		return ret;
> -	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
> -	if (!port->en) {
> -		dvb_unregister_adapter(&port->output->adap);
> -		return -ENODEV;
> +	if (address > CI_BUFFER_SIZE)
> +		return -1;
> +	ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
> +		  CI_DO_READ_ATTRIBUTES(ci->nr));
> +	wait_ci_ready(ci);
> +	val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
> +	return val;
> +}
> +
> +static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
> +			       int address, u8 value)
> +{
> +	struct ddb_ci *ci = ca->data;
> +
> +	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
> +		  CI_DO_ATTRIBUTE_RW(ci->nr));
> +	wait_ci_ready(ci);
> +	return 0;
> +}
> +
> +static int read_cam_control(struct dvb_ca_en50221 *ca,
> +			    int slot, u8 address)
> +{
> +	u32 count = 100;
> +	struct ddb_ci *ci = ca->data;
> +	u32 res;
> +
> +	ddbwritel(ci->port->dev, CI_READ_CMD | address,
> +		  CI_DO_IO_RW(ci->nr));
> +	ndelay(500);
> +	do {
> +		res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
> +		if (res & CI_READY)
> +			break;
> +		usleep_range(1, 2);
> +		if ((--count) == 0)
> +			return -1;
> +	} while (1);
> +	return (0xff & res);
> +}
> +
> +static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
> +			     u8 address, u8 value)
> +{
> +	struct ddb_ci *ci = ca->data;
> +
> +	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
> +		  CI_DO_IO_RW(ci->nr));
> +	wait_ci_ready(ci);
> +	return 0;
> +}
> +
> +static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
> +{
> +	struct ddb_ci *ci = ca->data;
> +
> +	ddbwritel(ci->port->dev, CI_POWER_ON,
> +		  CI_CONTROL(ci->nr));
> +	msleep(100);
> +	ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
> +		  CI_CONTROL(ci->nr));
> +	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
> +		  CI_CONTROL(ci->nr));
> +	udelay(20);
> +	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
> +		  CI_CONTROL(ci->nr));
> +	return 0;
> +}
> +
> +static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
> +{
> +	struct ddb_ci *ci = ca->data;
> +
> +	ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
> +	msleep(300);
> +	return 0;
> +}
> +
> +static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
> +{
> +	struct ddb_ci *ci = ca->data;
> +	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
> +
> +	ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
> +		  CI_CONTROL(ci->nr));
> +	return 0;
> +}
> +
> +static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
> +{
> +	struct ddb_ci *ci = ca->data;
> +	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
> +	int stat = 0;
> +	
> +	if (val & CI_CAM_DETECT)
> +		stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
> +	if (val & CI_CAM_READY)
> +		stat |= DVB_CA_EN50221_POLL_CAM_READY;
> +	return stat;
> +}
> +
> +static struct dvb_ca_en50221 en_templ = {
> +	.read_attribute_mem  = read_attribute_mem,
> +	.write_attribute_mem = write_attribute_mem,
> +	.read_cam_control    = read_cam_control,
> +	.write_cam_control   = write_cam_control,
> +	.slot_reset          = slot_reset,
> +	.slot_shutdown       = slot_shutdown,
> +	.slot_ts_enable      = slot_ts_enable,
> +	.poll_slot_status    = poll_slot_status,
> +};
> +
> +static void ci_attach(struct ddb_port *port)
> +{
> +	struct ddb_ci *ci = 0;
> +
> +	ci = kzalloc(sizeof(*ci), GFP_KERNEL);
> +	if (!ci)
> +		return;
> +	memcpy(&ci->en, &en_templ, sizeof(en_templ));
> +	ci->en.data = ci;
> +	port->en = &ci->en;
> +	ci->port = port;
> +	ci->nr = port->nr - 2;
> +}
> +
> +struct cxd2099_cfg cxd_cfg = {
> +	.bitrate =  72000,
> +	.adr     =  0x40,
> +	.polarity = 1,
> +	.clock_mode = 1, // 2,
> +};
> +
> +static int ddb_ci_attach(struct ddb_port *port)
> +{
> +	if (port->type == DDB_CI_EXTERNAL_SONY) {
> +		cxd_cfg.bitrate = ci_bitrate;
> +		port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
> +		if (!port->en) 
> +			return -ENODEV;
> +		dvb_ca_en50221_init(port->dvb[0].adap,
> +				    port->en, 0, 1);
>  	}
> -	ddb_input_start(port->input[0]);
> -	ddb_output_start(port->output);
> -	dvb_ca_en50221_init(&port->output->adap,
> -			    port->en, 0, 1);
> -	ret = dvb_register_device(&port->output->adap, &port->output->dev,
> -				  &dvbdev_ci, (void *) port->output,
> -				  DVB_DEVICE_SEC);
> -	return ret;
> +	if (port->type == DDB_CI_INTERNAL) {
> +		ci_attach(port);
> +		if (!port->en) 
> +			return -ENODEV;
> +		dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
> +	}
> +	return 0;
>  }
>  
>  static int ddb_port_attach(struct ddb_port *port)
> @@ -1083,9 +1629,26 @@ static int ddb_port_attach(struct ddb_port *port)
>  		if (ret < 0)
>  			break;
>  		ret = dvb_input_attach(port->input[1]);
> +		if (ret < 0)
> +			break;
> +		port->input[0]->redi = port->input[0];
> +		port->input[1]->redi = port->input[1];
>  		break;
>  	case DDB_PORT_CI:
>  		ret = ddb_ci_attach(port);
> +		if (ret < 0)
> +			break;
> +	case DDB_PORT_LOOP:
> +		ret = dvb_register_device(port->dvb[0].adap,
> +					  &port->dvb[0].dev,
> +					  &dvbdev_ci, (void *) port->output,
> +					  DVB_DEVICE_CI);
> +		break;
> +	case DDB_PORT_MOD:
> +		ret = dvb_register_device(port->dvb[0].adap,
> +					  &port->dvb[0].dev,
> +					  &dvbdev_mod, (void *) port->output,
> +					  DVB_DEVICE_MOD);
>  		break;
>  	default:
>  		break;
> @@ -1100,6 +1663,11 @@ static int ddb_ports_attach(struct ddb *dev)
>  	int i, ret = 0;
>  	struct ddb_port *port;
>  
> +	if (dev->info->port_num) {
> +		ret = dvb_register_adapters(dev);
> +		if (ret < 0)
> +			return ret;
> +	}
>  	for (i = 0; i < dev->info->port_num; i++) {
>  		port = &dev->port[i];
>  		ret = ddb_port_attach(port);
> @@ -1116,125 +1684,210 @@ static void ddb_ports_detach(struct ddb *dev)
>  
>  	for (i = 0; i < dev->info->port_num; i++) {
>  		port = &dev->port[i];
> +	
>  		switch (port->class) {
>  		case DDB_PORT_TUNER:
>  			dvb_input_detach(port->input[0]);
>  			dvb_input_detach(port->input[1]);
>  			break;
>  		case DDB_PORT_CI:
> -			if (port->output->dev)
> -				dvb_unregister_device(port->output->dev);
> +		case DDB_PORT_LOOP:
> +			if (port->dvb[0].dev)
> +				dvb_unregister_device(port->dvb[0].dev);
>  			if (port->en) {
> -				ddb_input_stop(port->input[0]);
> -				ddb_output_stop(port->output);
>  				dvb_ca_en50221_release(port->en);
>  				kfree(port->en);
>  				port->en = 0;
> -				dvb_unregister_adapter(&port->output->adap);
>  			}
>  			break;
> +		case DDB_PORT_MOD:
> +			if (port->dvb[0].dev)
> +				dvb_unregister_device(port->dvb[0].dev);
> +			break;
>  		}
>  	}
> +	dvb_unregister_adapters(dev);
>  }
>  
> -/****************************************************************************/
> -/****************************************************************************/
> +/* Copy input DMA pointers to output DMA and ACK. */
> +static void input_write_output(struct ddb_input *input,
> +			       struct ddb_output *output)
> +{
> +	ddbwritel(output->port->dev,
> +		  input->dma->stat, DMA_BUFFER_ACK(output->dma->nr));
> +	output->dma->cbuf = (input->dma->stat >> 11) & 0x1f;
> +	output->dma->coff = (input->dma->stat & 0x7ff) << 7;
> +}
>  
> -static int port_has_ci(struct ddb_port *port)
> +static void output_ack_input(struct ddb_output *output,
> +			     struct ddb_input *input)
>  {
> -	u8 val;
> -	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
> +	ddbwritel(input->port->dev,
> +		  output->dma->stat, DMA_BUFFER_ACK(input->dma->nr));
>  }
>  
> -static int port_has_stv0900(struct ddb_port *port)
> +static void input_write_dvb(struct ddb_input *input, 
> +			    struct ddb_input *input2)
>  {
> -	u8 val;
> -	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
> -		return 0;
> -	return 1;
> +	struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1];
> +	struct ddb_dma *dma, *dma2;
> +	struct ddb *dev = input->port->dev;
> +	int noack = 0;
> +
> +	dma = dma2 = input->dma;
> +	/* if there also is an output connected, do not ACK. 
> +	   input_write_output will ACK. */
> +	if (input->redo) {
> +		dma2 = input->redo->dma;
> +		noack = 1;
> +	}
> +	while (dma->cbuf != ((dma->stat >> 11) & 0x1f)
> +	       || (4 & dma->ctrl)) {
> +		if (4 & dma->ctrl) {
> +			// printk(KERN_ERR "Overflow dma %d\n", dma->nr);
> +			if (noack) 
> +				noack = 0;
> +		}
> +		dvb_dmx_swfilter_packets(&dvb->demux,
> +					 dma2->vbuf[dma->cbuf],
> +					 dma2->size / 188);
> +		dma->cbuf = (dma->cbuf + 1) % dma2->num;
> +		if (!noack)
> +			ddbwritel(dev, (dma->cbuf << 11),  
> +				  DMA_BUFFER_ACK(dma->nr));
> +		dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
> +		dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
> +	}
>  }
>  
> -static int port_has_stv0900_aa(struct ddb_port *port)
> +static void input_work(struct work_struct *work)
>  {
> -	u8 val;
> -	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
> -		return 0;
> -	return 1;
> +	struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
> +	struct ddb_input *input = (struct ddb_input *) dma->io;
> +	struct ddb *dev = input->port->dev;
> +
> +	spin_lock(&dma->lock);
> +	if (!dma->running) {
> +		spin_unlock(&dma->lock);
> +		return;
> +	}
> +	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
> +	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
> +
> +	if (input->redi)
> +		input_write_dvb(input, input->redi);
> +	if (input->redo)
> +		input_write_output(input, input->redo);	
> +	wake_up(&dma->wq);
> +	spin_unlock(&dma->lock);
>  }
>  
> -static int port_has_drxks(struct ddb_port *port)
> +static void input_handler(unsigned long data)
>  {
> -	u8 val;
> -	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
> -		return 0;
> -	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
> -		return 0;
> -	return 1;
> +	struct ddb_input *input = (struct ddb_input *) data;
> +	struct ddb_dma *dma = input->dma;
> +
> +	/* If there is no input connected, input_tasklet() will
> +           just copy pointers and ACK. So, there is no need to go 
> +	   through the tasklet scheduler. */
> +	if (input->redi)
> +		queue_work(ddb_wq, &dma->work);
> +	else
> +		input_work(&dma->work);
>  }
>  
> -static void ddb_port_probe(struct ddb_port *port)
> +/* TODO: hmm, don't really need this anymore. 
> +   The output IRQ just copies some pointers, acks and wakes. */
> +static void output_work(struct work_struct *work)
>  {
> -	struct ddb *dev = port->dev;
> -	char *modname = "NO MODULE";
> +}
>  
> -	port->class = DDB_PORT_NONE;
> +static void output_handler(unsigned long data)
> +{
> +	struct ddb_output *output = (struct ddb_output *) data;
> +	struct ddb_dma *dma = output->dma;
> +	struct ddb *dev = output->port->dev;
>  
> -	if (port_has_ci(port)) {
> -		modname = "CI";
> -		port->class = DDB_PORT_CI;
> -		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> -	} else if (port_has_stv0900(port)) {
> -		modname = "DUAL DVB-S2";
> -		port->class = DDB_PORT_TUNER;
> -		port->type = DDB_TUNER_DVBS_ST;
> -		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
> -	} else if (port_has_stv0900_aa(port)) {
> -		modname = "DUAL DVB-S2";
> -		port->class = DDB_PORT_TUNER;
> -		port->type = DDB_TUNER_DVBS_ST_AA;
> -		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
> -	} else if (port_has_drxks(port)) {
> -		modname = "DUAL DVB-C/T";
> -		port->class = DDB_PORT_TUNER;
> -		port->type = DDB_TUNER_DVBCT_TR;
> -		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> +	spin_lock(&dma->lock);
> +	if (!dma->running) {
> +		spin_unlock(&dma->lock);
> +		return;
> +	}
> +	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
> +	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
> +	if (output->redi) 
> +		output_ack_input(output, output->redi);
> +	wake_up(&dma->wq);
> +	spin_unlock(&dma->lock);
> +}
> +
> +static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out)
> +{
> +	dma->io = io;
> +	dma->nr = nr;
> +	spin_lock_init(&dma->lock);
> +	init_waitqueue_head(&dma->wq);
> +	if (out) {
> +		INIT_WORK(&dma->work, output_work);
> +		dma->num = OUTPUT_DMA_BUFS;
> +		dma->size = OUTPUT_DMA_SIZE;
> +		dma->div = OUTPUT_DMA_IRQ_DIV;
> +	} else {
> +		INIT_WORK(&dma->work, input_work);
> +		dma->num = INPUT_DMA_BUFS;
> +		dma->size = INPUT_DMA_SIZE;
> +		dma->div = INPUT_DMA_IRQ_DIV;
>  	}
> -	printk(KERN_INFO "Port %d (TAB %d): %s\n",
> -			 port->nr, port->nr+1, modname);
>  }
>  
> -static void ddb_input_init(struct ddb_port *port, int nr)
> +static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int dma_nr)
>  {
>  	struct ddb *dev = port->dev;
>  	struct ddb_input *input = &dev->input[nr];
>  
> +	if (dev->has_dma) {
> +		dev->handler[dma_nr + 8] = input_handler;
> +		dev->handler_data[dma_nr + 8] = (unsigned long) input;
> +	}
> +	port->input[pnr] = input;
>  	input->nr = nr;
>  	input->port = port;
> -	input->dma_buf_num = INPUT_DMA_BUFS;
> -	input->dma_buf_size = INPUT_DMA_SIZE;
> -	ddbwritel(0, TS_INPUT_CONTROL(nr));
> -	ddbwritel(2, TS_INPUT_CONTROL(nr));
> -	ddbwritel(0, TS_INPUT_CONTROL(nr));
> -	ddbwritel(0, DMA_BUFFER_ACK(nr));
> -	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
> -	spin_lock_init(&input->lock);
> -	init_waitqueue_head(&input->wq);
> +	if (dev->has_dma) {
> +		input->dma = &dev->dma[dma_nr];
> +		ddb_dma_init(input->dma, dma_nr, (void *) input, 0);
> +	}
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
> +	ddbwritel(dev, 2, TS_INPUT_CONTROL(nr));
> +	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
> +	if (dev->has_dma) 
> +		ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
>  }
>  
> -static void ddb_output_init(struct ddb_port *port, int nr)
> +static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr)
>  {
>  	struct ddb *dev = port->dev;
>  	struct ddb_output *output = &dev->output[nr];
> +
> +	if (dev->has_dma) {
> +		dev->handler[dma_nr + 8] = output_handler;
> +		dev->handler_data[dma_nr + 8] = (unsigned long) output;
> +	}
> +	port->output = output;
>  	output->nr = nr;
>  	output->port = port;
> -	output->dma_buf_num = OUTPUT_DMA_BUFS;
> -	output->dma_buf_size = OUTPUT_DMA_SIZE;
> -
> -	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
> -	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
> -	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
> -	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
> -	init_waitqueue_head(&output->wq);
> +	if (dev->has_dma) {
> +		output->dma = &dev->dma[dma_nr];
> +		ddb_dma_init(output->dma, dma_nr, (void *) output, 1);
> +	}
> +	if (output->port->class == DDB_PORT_MOD) {
> +		// ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));
> +	} else {
> +		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
> +		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr));
> +		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
> +	}
> +	if (dev->has_dma) 
> +		ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
>  }
>  
>  static void ddb_ports_init(struct ddb *dev)
> @@ -1247,15 +1900,31 @@ static void ddb_ports_init(struct ddb *dev)
>  		port->dev = dev;
>  		port->nr = i;
>  		port->i2c = &dev->i2c[i];
> -		port->input[0] = &dev->input[2 * i];
> -		port->input[1] = &dev->input[2 * i + 1];
> -		port->output = &dev->output[i];
> -
> +		port->gap = 4;
> +		port->obr = ci_bitrate;
>  		mutex_init(&port->i2c_gate_lock);
>  		ddb_port_probe(port);
> -		ddb_input_init(port, 2 * i);
> -		ddb_input_init(port, 2 * i + 1);
> -		ddb_output_init(port, i);
> +		port->dvb[0].adap = &dev->adap[2 * i];
> +		port->dvb[1].adap = &dev->adap[2 * i + 1];
> +
> +		if ((dev->info->type == DDB_OCTOPUS_CI) || 
> +		    (dev->info->type == DDB_OCTONET) ||
> +		    (dev->info->type == DDB_OCTOPUS)) {
> +			if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) {
> +				ddb_input_init(port, 2 + i, 0, 2 + i);
> +				ddb_input_init(port, 4 + i, 1, 4 + i);
> +			} else {
> +				ddb_input_init(port, 2 * i, 0, 2 * i);
> +				ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
> +			}
> +			ddb_output_init(port, i, i + 8);
> +		} 
> +		if (dev->info->type == DDB_MOD) {
> +			ddb_output_init(port, i, i);
> +			dev->handler[i + 18] = ddbridge_mod_rate_handler;
> +			dev->handler_data[i + 18] = 
> +				(unsigned long) &dev->output[i];
> +		}
>  	}
>  }
>  
> @@ -1266,101 +1935,130 @@ static void ddb_ports_release(struct ddb *dev)
>  
>  	for (i = 0; i < dev->info->port_num; i++) {
>  		port = &dev->port[i];
> -		port->dev = dev;
> -		tasklet_kill(&port->input[0]->tasklet);
> -		tasklet_kill(&port->input[1]->tasklet);
> -		tasklet_kill(&port->output->tasklet);
> +		if (port->input[0])
> +			cancel_work_sync(&port->input[0]->dma->work);
> +		if (port->input[1])
> +			cancel_work_sync(&port->input[1]->dma->work);
> +		if (port->output)
> +			cancel_work_sync(&port->output->dma->work);
>  	}
>  }
>  
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> +#define IRQ_HANDLE(_nr) if ((s & (1UL << _nr)) && dev->handler[_nr]) \
> +		dev->handler[_nr](dev->handler_data[_nr]);
> +
> +static void irq_handle_msg(struct ddb *dev, u32 s)
> +{
> +	dev->i2c_irq++;
> +	IRQ_HANDLE(0);
> +	IRQ_HANDLE(1);
> +	IRQ_HANDLE(2);
> +	IRQ_HANDLE(3);
> +}
> +
> +static void irq_handle_io(struct ddb *dev, u32 s)
> +{
> +	dev->ts_irq++;
> +	IRQ_HANDLE(8);
> +	IRQ_HANDLE(9);
> +	IRQ_HANDLE(10);
> +	IRQ_HANDLE(11);
> +	IRQ_HANDLE(12);
> +	IRQ_HANDLE(13);
> +	IRQ_HANDLE(14);
> +	IRQ_HANDLE(15);
> +	IRQ_HANDLE(16);
> +	IRQ_HANDLE(17);
> +	IRQ_HANDLE(18);
> +	IRQ_HANDLE(19);
> +	if (dev->info->type != DDB_MOD)
> +		return;
> +	IRQ_HANDLE(20);
> +	IRQ_HANDLE(21);
> +	IRQ_HANDLE(22);
> +	IRQ_HANDLE(23);
> +	IRQ_HANDLE(24);
> +	IRQ_HANDLE(25);
> +	IRQ_HANDLE(26);
> +	IRQ_HANDLE(27);
> +}
> +
> +static irqreturn_t irq_handler0(int irq, void *dev_id)
> +{
> +	struct ddb *dev = (struct ddb *) dev_id;
> +	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
> +
> +	do {
> +		if (s & 0x80000000)
> +			return IRQ_NONE;
> +		if (!(s & 0xfff00))
> +			return IRQ_NONE;
> +		ddbwritel(dev, s, INTERRUPT_ACK);
> +		irq_handle_io(dev, s);
> +	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
> +	
> +	return IRQ_HANDLED;
> +}
>  
> -static void irq_handle_i2c(struct ddb *dev, int n)
> +static irqreturn_t irq_handler1(int irq, void *dev_id)
>  {
> -	struct ddb_i2c *i2c = &dev->i2c[n];
> +	struct ddb *dev = (struct ddb *) dev_id;
> +	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
>  
> -	i2c->done = 1;
> -	wake_up(&i2c->wq);
> +	do {
> +		if (s & 0x80000000)
> +			return IRQ_NONE;
> +		if (!(s & 0x0000f))
> +			return IRQ_NONE;
> +		ddbwritel(dev, s, INTERRUPT_ACK);
> +		irq_handle_msg(dev, s);
> +	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
> +	
> +	return IRQ_HANDLED;
>  }
>  
>  static irqreturn_t irq_handler(int irq, void *dev_id)
>  {
>  	struct ddb *dev = (struct ddb *) dev_id;
> -	u32 s = ddbreadl(INTERRUPT_STATUS);
> +	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
> +	int ret = IRQ_HANDLED;
>  
>  	if (!s)
>  		return IRQ_NONE;
> -
>  	do {
> -		ddbwritel(s, INTERRUPT_ACK);
> -
> -		if (s & 0x00000001)
> -			irq_handle_i2c(dev, 0);
> -		if (s & 0x00000002)
> -			irq_handle_i2c(dev, 1);
> -		if (s & 0x00000004)
> -			irq_handle_i2c(dev, 2);
> -		if (s & 0x00000008)
> -			irq_handle_i2c(dev, 3);
> -
> -		if (s & 0x00000100)
> -			tasklet_schedule(&dev->input[0].tasklet);
> -		if (s & 0x00000200)
> -			tasklet_schedule(&dev->input[1].tasklet);
> -		if (s & 0x00000400)
> -			tasklet_schedule(&dev->input[2].tasklet);
> -		if (s & 0x00000800)
> -			tasklet_schedule(&dev->input[3].tasklet);
> -		if (s & 0x00001000)
> -			tasklet_schedule(&dev->input[4].tasklet);
> -		if (s & 0x00002000)
> -			tasklet_schedule(&dev->input[5].tasklet);
> -		if (s & 0x00004000)
> -			tasklet_schedule(&dev->input[6].tasklet);
> -		if (s & 0x00008000)
> -			tasklet_schedule(&dev->input[7].tasklet);
> -
> -		if (s & 0x00010000)
> -			tasklet_schedule(&dev->output[0].tasklet);
> -		if (s & 0x00020000)
> -			tasklet_schedule(&dev->output[1].tasklet);
> -		if (s & 0x00040000)
> -			tasklet_schedule(&dev->output[2].tasklet);
> -		if (s & 0x00080000)
> -			tasklet_schedule(&dev->output[3].tasklet);
> -
> -		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
> -	} while ((s = ddbreadl(INTERRUPT_STATUS)));
> -
> -	return IRQ_HANDLED;
> +		if (s & 0x80000000)
> +			return IRQ_NONE;
> +		ddbwritel(dev, s, INTERRUPT_ACK);
> +		
> +		if (s & 0x0000000f)
> +			irq_handle_msg(dev, s);
> +		if (s & 0x0fffff00)
> +			irq_handle_io(dev, s);
> +	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
> +	
> +	return ret;
>  }
>  
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
>  static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
>  {
>  	u32 data, shift;
>  
>  	if (wlen > 4)
> -		ddbwritel(1, SPI_CONTROL);
> +		ddbwritel(dev, 1, SPI_CONTROL);
>  	while (wlen > 4) {
>  		/* FIXME: check for big-endian */
>  		data = swab32(*(u32 *)wbuf);
>  		wbuf += 4;
>  		wlen -= 4;
> -		ddbwritel(data, SPI_DATA);
> -		while (ddbreadl(SPI_CONTROL) & 0x0004)
> +		ddbwritel(dev, data, SPI_DATA);
> +		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
>  			;
>  	}
>  
>  	if (rlen)
> -		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
> +		ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
>  	else
> -		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
> +		ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
>  
>  	data = 0;
>  	shift = ((4 - wlen) * 8);
> @@ -1372,33 +2070,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
>  	}
>  	if (shift)
>  		data <<= shift;
> -	ddbwritel(data, SPI_DATA);
> -	while (ddbreadl(SPI_CONTROL) & 0x0004)
> +	ddbwritel(dev, data, SPI_DATA);
> +	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
>  		;
>  
>  	if (!rlen) {
> -		ddbwritel(0, SPI_CONTROL);
> +		ddbwritel(dev, 0, SPI_CONTROL);
>  		return 0;
>  	}
>  	if (rlen > 4)
> -		ddbwritel(1, SPI_CONTROL);
> +		ddbwritel(dev, 1, SPI_CONTROL);
>  
>  	while (rlen > 4) {
> -		ddbwritel(0xffffffff, SPI_DATA);
> -		while (ddbreadl(SPI_CONTROL) & 0x0004)
> +		ddbwritel(dev, 0xffffffff, SPI_DATA);
> +		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
>  			;
> -		data = ddbreadl(SPI_DATA);
> +		data = ddbreadl(dev, SPI_DATA);
>  		*(u32 *) rbuf = swab32(data);
>  		rbuf += 4;
>  		rlen -= 4;
>  	}
> -	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
> -	ddbwritel(0xffffffff, SPI_DATA);
> -	while (ddbreadl(SPI_CONTROL) & 0x0004)
> +	ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
> +	ddbwritel(dev, 0xffffffff, SPI_DATA);
> +	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
>  		;
>  
> -	data = ddbreadl(SPI_DATA);
> -	ddbwritel(0, SPI_CONTROL);
> +	data = ddbreadl(dev, SPI_DATA);
> +	ddbwritel(dev, 0, SPI_CONTROL);
>  
>  	if (rlen < 4)
>  		data <<= ((4 - rlen) * 8);
> @@ -1412,6 +2110,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
>  	return 0;
>  }
>  
> +int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len)
> +{
> +	u8 cmd[4] = {0x03, (addr >> 16) & 0xff, 
> +		     (addr >> 8) & 0xff, addr & 0xff};
> +	
> +	return flashio(dev, cmd, 4, buf, len);
> +}
> +
> +static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val)
> +{
> +	ddbwritel(dev, adr, MDIO_ADR);
> +	ddbwritel(dev, reg, MDIO_REG);
> +	ddbwritel(dev, val, MDIO_VAL);
> +	ddbwritel(dev, 0x03, MDIO_CTRL);
> +	while (ddbreadl(dev, MDIO_CTRL) & 0x02);
> +	return 0;
> +}
> +
> +static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg)
> +{
> +	ddbwritel(dev, adr, MDIO_ADR);
> +	ddbwritel(dev, reg, MDIO_REG);
> +	ddbwritel(dev, 0x07, MDIO_CTRL);
> +	while (ddbreadl(dev, MDIO_CTRL) & 0x02);
> +	return ddbreadl(dev, MDIO_VAL);
> +}
> +
>  #define DDB_MAGIC 'd'
>  
>  struct ddb_flashio {
> @@ -1421,19 +2146,69 @@ struct ddb_flashio {
>  	__u32 read_len;
>  };
>  
> -#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
> +struct ddb_gpio {
> +	__u32 mask;
> +	__u32 data;
> +};
> +
> +struct ddb_id {
> +	__u16 vendor;
> +	__u16 device;
> +	__u16 subvendor;
> +	__u16 subdevice;
> +	__u32 hw;
> +	__u32 regmap;
> +};
> +
> +struct ddb_reg {
> +	__u32 reg;
> +	__u32 val;
> +};
> +
> +struct ddb_mem {
> +	__u32  off;
> +	__u8  *buf;
> +	__u32  len;
> +};
> +
> +struct ddb_mdio {
> +	__u8   adr;
> +	__u8   reg;
> +	__u16  val;
> +};
> +
> +#define IOCTL_DDB_FLASHIO    _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
> +#define IOCTL_DDB_GPIO_IN    _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
> +#define IOCTL_DDB_GPIO_OUT   _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
> +#define IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id)
> +#define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
> +#define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
> +#define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
> +#define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
> +#define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
> +#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
>  
>  #define DDB_NAME "ddbridge"
>  
>  static u32 ddb_num;
> -static struct ddb *ddbs[32];
> -static struct class *ddb_class;
>  static int ddb_major;
> +static DEFINE_MUTEX(ddb_mutex);
> +
> +static int ddb_release(struct inode *inode, struct file *file)
> +{
> +	struct ddb *dev = file->private_data;
> +	
> +	dev->ddb_dev_users--;
> +	return 0;
> +}
>  
>  static int ddb_open(struct inode *inode, struct file *file)
>  {
>  	struct ddb *dev = ddbs[iminor(inode)];
>  
> +	if (dev->ddb_dev_users)
> +		return -EBUSY;
> +	dev->ddb_dev_users++;
>  	file->private_data = dev;
>  	return 0;
>  }
> @@ -1470,6 +2245,103 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>  			return -EFAULT;
>  		break;
>  	}
> +	case IOCTL_DDB_GPIO_OUT:
> +	{
> +		struct ddb_gpio gpio;
> +		if (copy_from_user(&gpio, parg, sizeof(gpio))) 
> +			return -EFAULT;
> +		ddbwritel(dev, gpio.mask, GPIO_DIRECTION);
> +		ddbwritel(dev, gpio.data, GPIO_OUTPUT);
> +		break;
> +	}
> +	case IOCTL_DDB_ID:
> +	{
> +		struct ddb_id ddbid;
> +		
> +		ddbid.vendor = dev->id->vendor;
> +		ddbid.device = dev->id->device;
> +		ddbid.subvendor = dev->id->subvendor;
> +		ddbid.subdevice = dev->id->subdevice;
> +		ddbid.hw = ddbreadl(dev, 0);
> +		ddbid.regmap = ddbreadl(dev, 4);
> +		if (copy_to_user(parg, &ddbid, sizeof(ddbid))) 
> +			return -EFAULT;
> +		break;
> +	}
> +	case IOCTL_DDB_READ_REG:
> +	{
> +		struct ddb_reg reg;
> +		
> +		if (copy_from_user(&reg, parg, sizeof(reg))) 
> +			return -EFAULT;
> +		if (reg.reg >= dev->regs_len)
> +			return -EINVAL;
> +		reg.val = ddbreadl(dev, reg.reg);
> +		if (copy_to_user(parg, &reg, sizeof(reg))) 
> +			return -EFAULT;
> +		break;
> +	}
> +	case IOCTL_DDB_WRITE_REG:
> +	{
> +		struct ddb_reg reg;
> +		
> +		if (copy_from_user(&reg, parg, sizeof(reg))) 
> +			return -EFAULT;
> +		if (reg.reg >= dev->regs_len)
> +			return -EINVAL;
> +		ddbwritel(dev, reg.val, reg.reg);
> +		break;
> +	}
> +	case IOCTL_DDB_READ_MDIO:
> +	{
> +		struct ddb_mdio mdio;
> +		
> +		if (copy_from_user(&mdio, parg, sizeof(mdio))) 
> +			return -EFAULT;
> +		mdio.val = mdio_read(dev, mdio.adr, mdio.reg);
> +		if (copy_to_user(parg, &mdio, sizeof(mdio))) 
> +			return -EFAULT;
> +		break;
> +	}
> +	case IOCTL_DDB_WRITE_MDIO:
> +	{
> +		struct ddb_mdio mdio;
> +		
> +		if (copy_from_user(&mdio, parg, sizeof(mdio))) 
> +			return -EFAULT;
> +		mdio_write(dev, mdio.adr, mdio.reg, mdio.val);
> +		break;
> +	}
> +	case IOCTL_DDB_READ_MEM:
> +	{
> +		struct ddb_mem mem;
> +		u8 *buf = &dev->iobuf[0];
> +
> +		if (copy_from_user(&mem, parg, sizeof(mem)))
> +			return -EFAULT;
> +		if ((mem.len + mem.off > dev->regs_len) ||
> +		    mem.len > 1024)
> +			return -EINVAL;
> +		ddbcpyfrom(dev, buf, mem.off, mem.len);
> +		if (copy_to_user(mem.buf, buf, mem.len))
> +			return -EFAULT;
> +		break;
> +	}
> +	case IOCTL_DDB_WRITE_MEM:
> +	{
> +		struct ddb_mem mem;
> +		u8 *buf = &dev->iobuf[0];
> +		
> +		if (copy_from_user(&mem, parg, sizeof(mem)))
> +			return -EFAULT;
> +		if ((mem.len + mem.off > dev->regs_len) ||
> +		    mem.len > 1024)
> +			return -EINVAL;
> +		if (copy_from_user(buf, mem.buf, mem.len))
> +			return -EFAULT;
> +		ddbcpyto(dev, mem.off, buf, mem.len);
> +		break;
> +	}
>  	default:
>  		return -ENOTTY;
>  	}
> @@ -1479,61 +2351,425 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>  static const struct file_operations ddb_fops = {
>  	.unlocked_ioctl = ddb_ioctl,
>  	.open           = ddb_open,
> +	.release        = ddb_release,
>  };
>  
> +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
> +static char *ddb_devnode(struct device *device, mode_t *mode)
> +#else
>  static char *ddb_devnode(struct device *device, umode_t *mode)
> +#endif
>  {
>  	struct ddb *dev = dev_get_drvdata(device);
>  
>  	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
>  }
>  
> +#define __ATTR_MRO(_name, _show) {				\
> +	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
> +	.show	= _show,					\
> +}
> +
> +#define __ATTR_MWO(_name, _store) {				\
> +	.attr	= { .name = __stringify(_name), .mode = 0222 },	\
> +	.store	= _store,					\
> +}
> +
> +static ssize_t ports_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +
> +	return sprintf(buf, "%d\n", dev->info->port_num);
> +}
> +
> +static ssize_t ts_irq_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +
> +	return sprintf(buf, "%d\n", dev->ts_irq);
> +}
> +
> +static ssize_t i2c_irq_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +
> +	return sprintf(buf, "%d\n", dev->i2c_irq);
> +}
> +
> +static char *class_name[] = {
> +	"NONE", "CI", "TUNER", "LOOP"
> +};
> +
> +static char *type_name[] = {
> +	"NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", "DVBCT_ST", "INTERNAL", "CXD2099", 
> +};
> +
> +static ssize_t fan_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	u32 val;
> +
> +	val = ddbreadl(dev, GPIO_OUTPUT) & 1;
> +	return sprintf(buf, "%d\n", val);
> +}
> +
> +static ssize_t fan_store(struct device *device, struct device_attribute *d,
> +			 const char *buf, size_t count)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	unsigned val;
> +
> +	if (sscanf(buf, "%u\n", &val) != 1)
> +		return -EINVAL;
> +	ddbwritel(dev, 1, GPIO_DIRECTION);
> +	ddbwritel(dev, val & 1, GPIO_OUTPUT);
> +	return count;
> +}
> +
> +static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	struct i2c_adapter *adap;
> +	int temp, temp2;
> +	u8 tmp[2];
> +
> +	if (dev->info->type == DDB_MOD) {
> +		ddbwritel(dev, 1, TEMPMON_CONTROL);
> +		msleep(5);
> +		temp = ddbreadl(dev, TEMPMON_SENSOR1);
> +		temp2 = ddbreadl(dev, TEMPMON_SENSOR2);
> +		temp = (temp * 1000) >> 8;
> +		temp2 = (temp2 * 1000) >> 8;
> +		return sprintf(buf, "%d %d\n", temp, temp2);
> +	}
> +	if (!dev->info->temp_num)
> +		return sprintf(buf, "no sensor\n");
> +	adap = &dev->i2c[dev->info->temp_bus].adap;
> +	if (ddb_i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0)
> +		return sprintf(buf, "read_error\n");
> +	temp = (tmp[0] << 3) | (tmp[1] >> 5);
> +	temp *= 125;
> +	if (dev->info->temp_num == 2) {
> +		if (ddb_i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0)
> +			return sprintf(buf, "read_error\n");
> +		temp2 = (tmp[0] << 3) | (tmp[1] >> 5);
> +		temp2 *= 125;
> +		return sprintf(buf, "%d %d\n", temp, temp2);
> +	}
> +	return sprintf(buf, "%d\n", temp);
> +}
> +
> +static ssize_t mod_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	int num = attr->attr.name[3] - 0x30;
> +
> +	return sprintf(buf, "%s:%s\n",
> +		       class_name[dev->port[num].class],
> +		       type_name[dev->port[num].type]);
> +}
> +
> +static ssize_t led_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	int num = attr->attr.name[3] - 0x30;
> +
> +	return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0);
> +}
> +
> +static void ddb_set_led(struct ddb *dev, int num, int val)
> +{
> +	if (!dev->info->led_num)
> +		return;
> +	switch (dev->port[num].class) {
> +	case DDB_PORT_TUNER:
> +		switch (dev->port[num].type) {
> +		case DDB_TUNER_DVBS_ST:
> +			ddb_i2c_write_reg16(&dev->i2c[num].adap,
> +					0x69, 0xf14c, val ? 2 : 0);
> +			break;
> +		case DDB_TUNER_DVBCT_ST:
> +			ddb_i2c_write_reg16(&dev->i2c[num].adap, 
> +					0x1f, 0xf00e, 0);
> +			ddb_i2c_write_reg16(&dev->i2c[num].adap, 
> +					0x1f, 0xf00f, val ? 1 : 0);
> +			break;
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static ssize_t led_store(struct device *device, struct device_attribute *attr,
> +			 const char *buf, size_t count)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	int num = attr->attr.name[3] - 0x30;
> +	unsigned val;
> +
> +	if (sscanf(buf, "%u\n", &val) != 1)
> +		return -EINVAL;
> +	if (val)
> +		dev->leds |= (1 << num);
> +	else
> +		dev->leds &= ~(1 << num);
> +	ddb_set_led(dev, num, val);
> +	return count;
> +}
> +
> +static ssize_t snr_show(struct device *device, struct device_attribute *attr, char *buf) 
> +{
> +	struct ddb *dev = dev_get_drvdata(device); 
> +	char snr[32];
> +	int num = attr->attr.name[3] - 0x30;
> +	
> +	/* serial number at 0x100-0x11f */
> +	if (ddb_i2c_read_regs16(&dev->i2c[num].adap, 0x50, 0x100, snr, 32) < 0)
> +		if (ddb_i2c_read_regs16(&dev->i2c[num].adap, 0x57, 0x100, snr, 32) < 0)
> +			return sprintf(buf, "NO SNR\n");
> +	snr[31]=0; /* in case it is not terminated on EEPROM */
> +	return sprintf(buf, "%s\n", snr); 
> +}
> +
> +static ssize_t snr_store(struct device *device, struct device_attribute *attr,
> +			 const char *buf, size_t count)
> +{
> +	struct ddb *dev = dev_get_drvdata(device); 
> +	int num = attr->attr.name[3] - 0x30;
> +	u8 snr[34] = { 0x01, 0x00 };
> +	
> +	if (count > 31)
> +		return -EINVAL;
> +	memcpy(snr + 2, buf, count);
> +	ddb_i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
> +	ddb_i2c_write(&dev->i2c[num].adap, 0x50, snr, 34);
> +	return count;
> +}
> +
> +static ssize_t bsnr_show(struct device *device, struct device_attribute *attr, char *buf) 
> +{
> +	struct ddb *dev = dev_get_drvdata(device); 
> +	char snr[16];
> +
> +	ddbridge_flashread(dev, snr, 0x10, 15);
> +	snr[15]=0; /* in case it is not terminated on EEPROM */
> +	return sprintf(buf, "%s\n", snr); 
> +}
> +
> +static ssize_t redirect_show(struct device *device, struct device_attribute *attr, char *buf) 
> +{
> +	return 0;
> +}
> +
> +static ssize_t redirect_store(struct device *device, struct device_attribute *attr,
> +			 const char *buf, size_t count)
> +{
> +	unsigned int i, p;
> +	int res;
> +	
> +	if (sscanf(buf, "%x %x\n", &i, &p) != 2)
> +		return -EINVAL;
> +	res = ddb_redirect(i, p);
> +	if (res < 0)
> +		return res;
> +	printk(KERN_INFO "redirect: %02x, %02x\n", i, p);
> +	return count;
> +}
> +
> +static ssize_t gap_show(struct device *device, struct device_attribute *attr, char *buf) 
> +{
> +	struct ddb *dev = dev_get_drvdata(device); 
> +	int num = attr->attr.name[3] - 0x30;
> +	
> +	return sprintf(buf, "%d\n", dev->port[num].gap);
> +
> +}
> +static ssize_t gap_store(struct device *device, struct device_attribute *attr,
> +			 const char *buf, size_t count)
> +{
> +	struct ddb *dev = dev_get_drvdata(device); 
> +	int num = attr->attr.name[3] - 0x30;
> +	unsigned int val;
> +	
> +	if (sscanf(buf, "%u\n", &val) != 1)
> +		return -EINVAL;
> +	if (val > 20)
> +		return -EINVAL;
> +	dev->port[num].gap = val;
> +	return count;
> +}
> +
> +static ssize_t version_show(struct device *device, struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	
> +	return sprintf(buf, "%08x %08x\n", ddbreadl(dev, 0), ddbreadl(dev, 4));
> +}
> +
> +static ssize_t hwid_show(struct device *device,
> +			 struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +
> +	return sprintf(buf, "0x%08X\n", dev->hwid);
> +}
> +
> +static ssize_t regmap_show(struct device *device, 
> +			   struct device_attribute *attr, char *buf)
> +{
> +	struct ddb *dev = dev_get_drvdata(device);
> +	
> +	return sprintf(buf, "0x%08X\n", dev->regmapid);
> +}
> +
> +static struct device_attribute ddb_attrs[] = {
> +	__ATTR_RO(version),
> +	__ATTR_RO(ports),
> +	__ATTR_RO(ts_irq),
> +	__ATTR_RO(i2c_irq),
> +	__ATTR(gap0, 0666, gap_show, gap_store),
> +	__ATTR(gap1, 0666, gap_show, gap_store),
> +	__ATTR(gap2, 0666, gap_show, gap_store),
> +	__ATTR(gap3, 0666, gap_show, gap_store),
> +	__ATTR_RO(hwid),
> +	__ATTR_RO(regmap),
> +	__ATTR(redirect, 0666, redirect_show, redirect_store),
> +	__ATTR_MRO(snr,  bsnr_show),
> +	__ATTR_NULL,
> +};
> +
> +static struct device_attribute ddb_attrs_temp[] = {
> +	__ATTR_RO(temp),
> +};
> +
> +static struct device_attribute ddb_attrs_mod[] = {
> +	__ATTR_MRO(mod0, mod_show),
> +	__ATTR_MRO(mod1, mod_show),
> +	__ATTR_MRO(mod2, mod_show),
> +	__ATTR_MRO(mod3, mod_show),
> +};
> +
> +static struct device_attribute ddb_attrs_fan[] = {
> +	__ATTR(fan, 0666, fan_show, fan_store),
> +};
> +
> +static struct device_attribute ddb_attrs_snr[] = {
> +	__ATTR(snr0, 0666, snr_show, snr_store),
> +	__ATTR(snr1, 0666, snr_show, snr_store),
> +	__ATTR(snr2, 0666, snr_show, snr_store),
> +	__ATTR(snr3, 0666, snr_show, snr_store),
> +};
> +
> +static struct device_attribute ddb_attrs_led[] = {
> +	__ATTR(led0, 0666, led_show, led_store),
> +	__ATTR(led1, 0666, led_show, led_store),
> +	__ATTR(led2, 0666, led_show, led_store),
> +	__ATTR(led3, 0666, led_show, led_store),
> +};
> +
> +static struct class ddb_class = {
> +	.name		= "ddbridge",
> +	.owner          = THIS_MODULE,
> +	.dev_attrs	= ddb_attrs,
> +	.devnode        = ddb_devnode,
> +};
> +
>  static int ddb_class_create(void)
>  {
>  	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
>  	if (ddb_major < 0)
>  		return ddb_major;
> -
> -	ddb_class = class_create(THIS_MODULE, DDB_NAME);
> -	if (IS_ERR(ddb_class)) {
> -		unregister_chrdev(ddb_major, DDB_NAME);
> -		return PTR_ERR(ddb_class);
> -	}
> -	ddb_class->devnode = ddb_devnode;
> +	if (class_register(&ddb_class) < 0)
> +		return -1;
>  	return 0;
>  }
>  
>  static void ddb_class_destroy(void)
>  {
> -	class_destroy(ddb_class);
> +	class_unregister(&ddb_class);
>  	unregister_chrdev(ddb_major, DDB_NAME);
>  }
>  
> +static void ddb_device_attrs_del(struct ddb *dev)
> +{
> +	int i;
> +
> +	for (i = 0; i < dev->info->temp_num; i++)
> +		device_remove_file(dev->ddb_dev, &ddb_attrs_temp[0]);
> +	for (i = 0; i < dev->info->port_num; i++)
> +		device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]);
> +	for (i = 0; i < dev->info->fan_num; i++)
> +		device_remove_file(dev->ddb_dev, &ddb_attrs_fan[0]);
> +	for (i = 0; i < dev->info->i2c_num; i++) {
> +		if (dev->info->led_num)
> +			device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]);
> +		device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]);
> +	}
> +}
> +
> +static int ddb_device_attrs_add(struct ddb *dev)
> +{
> +	int i, res = 0;
> +	
> +	for (i = 0; i < dev->info->temp_num; i++)
> +		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_temp[0])))
> +			goto fail;
> +	for (i = 0; i < dev->info->port_num; i++)
> +		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])))
> +			goto fail;
> +	for (i = 0; i < dev->info->fan_num; i++)
> +		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_fan[0])))
> +			goto fail;
> +	for (i = 0; i < dev->info->i2c_num; i++) {
> +		if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])))
> +			goto fail;
> +		if (dev->info->led_num)
> +			if ((res = device_create_file(dev->ddb_dev, &ddb_attrs_led[i])))
> +				goto fail;
> +	}
> +fail:
> +	return res;
> +}
> +
>  static int ddb_device_create(struct ddb *dev)
>  {
> -	dev->nr = ddb_num++;
> -	dev->ddb_dev = device_create(ddb_class, NULL,
> +	int res = 0;
> +
> +	if (ddb_num == DDB_MAX_ADAPTER)
> +		return -ENOMEM;
> +	mutex_lock(&ddb_mutex);
> +	dev->nr = ddb_num;
> +	ddbs[dev->nr] = dev;
> +	dev->ddb_dev = device_create(&ddb_class, dev->dev,
>  				     MKDEV(ddb_major, dev->nr),
>  				     dev, "ddbridge%d", dev->nr);
> -	ddbs[dev->nr] = dev;
> -	if (IS_ERR(dev->ddb_dev))
> -		return -1;
> -	return 0;
> +	if (IS_ERR(dev->ddb_dev)) {
> +		res = PTR_ERR(dev->ddb_dev);
> +		printk(KERN_INFO "Could not create ddbridge%d\n", dev->nr); 
> +		goto fail;
> +	}
> +	res = ddb_device_attrs_add(dev);
> +	if (res) {
> +		ddb_device_attrs_del(dev);
> +		device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
> +		ddbs[dev->nr] = 0;
> +		dev->ddb_dev = ERR_PTR(-ENODEV);
> +	} else
> +		ddb_num++;
> +fail:
> +	mutex_unlock(&ddb_mutex);
> +	return res;
>  }
>  
>  static void ddb_device_destroy(struct ddb *dev)
>  {
> -	ddb_num--;
>  	if (IS_ERR(dev->ddb_dev))
>  		return;
> -	device_destroy(ddb_class, MKDEV(ddb_major, 0));
> +	ddb_device_attrs_del(dev);
> +	device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
>  }
>  
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> -
>  static void ddb_unmap(struct ddb *dev)
>  {
>  	if (dev->regs)
> @@ -1541,20 +2777,20 @@ static void ddb_unmap(struct ddb *dev)
>  	vfree(dev);
>  }
>  
> -
> -static void ddb_remove(struct pci_dev *pdev)
> +static void __devexit ddb_remove(struct pci_dev *pdev)
>  {
> -	struct ddb *dev = pci_get_drvdata(pdev);
> +	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
>  
>  	ddb_ports_detach(dev);
>  	ddb_i2c_release(dev);
>  
> -	ddbwritel(0, INTERRUPT_ENABLE);
> +	ddbwritel(dev, 0, INTERRUPT_ENABLE);
> +	ddbwritel(dev, 0, MSI1_ENABLE);
> +	if (dev->msi == 2)
> +		free_irq(dev->pdev->irq + 1, dev);
>  	free_irq(dev->pdev->irq, dev);
> -#ifdef CONFIG_PCI_MSI
>  	if (dev->msi)
>  		pci_disable_msi(dev->pdev);
> -#endif
>  	ddb_ports_release(dev);
>  	ddb_buffers_free(dev);
>  	ddb_device_destroy(dev);
> @@ -1564,8 +2800,13 @@ static void ddb_remove(struct pci_dev *pdev)
>  	pci_disable_device(pdev);
>  }
>  
> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
> +#define __devinit 
> +#define __devinitdata 
> +#endif 
>  
> -static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +static int __devinit ddb_probe(struct pci_dev *pdev,
> +			       const struct pci_device_id *id)
>  {
>  	struct ddb *dev;
>  	int stat = 0;
> @@ -1574,44 +2815,91 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	if (pci_enable_device(pdev) < 0)
>  		return -ENODEV;
>  
> -	dev = vmalloc(sizeof(struct ddb));
> +	dev = vzalloc(sizeof(struct ddb));
>  	if (dev == NULL)
>  		return -ENOMEM;
> -	memset(dev, 0, sizeof(struct ddb));
>  
> +	dev->has_dma = 1;
>  	dev->pdev = pdev;
> +	dev->dev = &pdev->dev;
>  	pci_set_drvdata(pdev, dev);
> +	dev->id = id;
>  	dev->info = (struct ddb_info *) id->driver_data;
>  	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
>  
> +	dev->regs_len = pci_resource_len(dev->pdev, 0);
>  	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
>  			    pci_resource_len(dev->pdev, 0));
>  	if (!dev->regs) {
> +		printk("DDBridge: not enough memory for register map\n");
>  		stat = -ENOMEM;
>  		goto fail;
>  	}
> -	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
> +	if (ddbreadl(dev, 0) == 0xffffffff) {
> +		printk("DDBridge: cannot read registers\n");
> +		stat = -ENODEV;
> +		goto fail;
> +	}
>  
> -#ifdef CONFIG_PCI_MSI
> -	if (pci_msi_enabled())
> -		stat = pci_enable_msi(dev->pdev);
> -	if (stat) {
> -		printk(KERN_INFO ": MSI not available.\n");
> +	dev->hwid = ddbreadl(dev, 0);
> +	dev->regmapid = ddbreadl(dev, 4);
> +	
> +	printk(KERN_INFO "HW %08x REGMAP %08x\n",
> +	       dev->hwid, dev->regmapid);
> +	
> +	ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI1_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI2_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI3_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI4_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI5_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI6_ENABLE);
> +	ddbwritel(dev, 0x00000000, MSI7_ENABLE);
> +
> +	if (pci_msi_enabled()) {
> +		stat = pci_enable_msi_block(dev->pdev, 2);
> +		if (stat == 0) {
> +			dev->msi = 1;
> +			printk("DDBrige using 2 MSI interrupts\n");
> +		}
> +		if (stat == 1) 
> +			stat = pci_enable_msi(dev->pdev);
> +		if (stat < 0) {
> +			printk(KERN_INFO ": MSI not available.\n");
> +		} else {
> +			irq_flag = 0;
> +			dev->msi++;
> +		}
> +	}
> +	if (dev->msi == 2) {
> +		stat = request_irq(dev->pdev->irq, irq_handler0,
> +				   irq_flag, "ddbridge", (void *) dev);
> +		if (stat < 0)
> +			goto fail0;
> +		stat = request_irq(dev->pdev->irq + 1, irq_handler1,
> +				   irq_flag, "ddbridge", (void *) dev);
> +		if (stat < 0) {
> +			free_irq(dev->pdev->irq, dev);
> +			goto fail0;
> +		} 
>  	} else {
> -		irq_flag = 0;
> -		dev->msi = 1;
> +		stat = request_irq(dev->pdev->irq, irq_handler, 
> +				   irq_flag, "ddbridge", (void *) dev);
> +		if (stat < 0)
> +			goto fail0;
> +	}
> +	ddbwritel(dev, 0, DMA_BASE_READ);
> +	if (dev->info->type != DDB_MOD)
> +		ddbwritel(dev, 0, DMA_BASE_WRITE);
> +	
> +	// ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);
> +	if (dev->msi == 2) {
> +		ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
> +		ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
> +	} else {
> +		ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
> +		ddbwritel(dev, 0x00000000, MSI1_ENABLE);
>  	}
> -#endif
> -	stat = request_irq(dev->pdev->irq, irq_handler,
> -			   irq_flag, "DDBridge", (void *) dev);
> -	if (stat < 0)
> -		goto fail1;
> -	ddbwritel(0, DMA_BASE_WRITE);
> -	ddbwritel(0, DMA_BASE_READ);
> -	ddbwritel(0xffffffff, INTERRUPT_ACK);
> -	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
> -	ddbwritel(0, MSI1_ENABLE);
> -
>  	if (ddb_i2c_init(dev) < 0)
>  		goto fail1;
>  	ddb_ports_init(dev);
> @@ -1621,7 +2909,17 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	}
>  	if (ddb_ports_attach(dev) < 0)
>  		goto fail3;
> +
> +	/* ignore if this fails */
>  	ddb_device_create(dev);
> +
> +	if (dev->info->fan_num)	{
> +		ddbwritel(dev, 1, GPIO_DIRECTION);
> +		ddbwritel(dev, 1, GPIO_OUTPUT);
> +	}
> +	if (dev->info->type == DDB_MOD)
> +		ddbridge_mod_init(dev);
> +
>  	return 0;
>  
>  fail3:
> @@ -1631,11 +2929,18 @@ fail3:
>  fail2:
>  	printk(KERN_ERR "fail2\n");
>  	ddb_buffers_free(dev);
> +	ddb_i2c_release(dev);
>  fail1:
>  	printk(KERN_ERR "fail1\n");
> +	ddbwritel(dev, 0, INTERRUPT_ENABLE);
> +	ddbwritel(dev, 0, MSI1_ENABLE);
> +	free_irq(dev->pdev->irq, dev);
> +	if (dev->msi == 2) 
> +		free_irq(dev->pdev->irq + 1, dev);
> +fail0:
> +	printk(KERN_ERR "fail0\n");
>  	if (dev->msi)
>  		pci_disable_msi(dev->pdev);
> -	free_irq(dev->pdev->irq, dev);
>  fail:
>  	printk(KERN_ERR "fail\n");
>  	ddb_unmap(dev);
> @@ -1644,55 +2949,130 @@ fail:
>  	return -1;
>  }
>  
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
>  static struct ddb_info ddb_none = {
>  	.type     = DDB_NONE,
> -	.name     = "Digital Devices PCIe bridge",
> +	.name     = "unknown Digital Devices PCIe card, install newer driver",
>  };
>  
>  static struct ddb_info ddb_octopus = {
>  	.type     = DDB_OCTOPUS,
>  	.name     = "Digital Devices Octopus DVB adapter",
>  	.port_num = 4,
> +	.i2c_num  = 4,
> +};
> +
> +static struct ddb_info ddb_octopusv3 = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Digital Devices Octopus V3 DVB adapter",
> +	.port_num = 4,
> +	.i2c_num  = 4,
>  };
>  
>  static struct ddb_info ddb_octopus_le = {
>  	.type     = DDB_OCTOPUS,
>  	.name     = "Digital Devices Octopus LE DVB adapter",
>  	.port_num = 2,
> +	.i2c_num  = 2,
> +};
> +
> +static struct ddb_info ddb_octopus_oem = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Digital Devices Octopus OEM",
> +	.port_num = 4,
> +	.i2c_num  = 4,
> +	.led_num  = 1,
> +	.fan_num  = 1,
> +	.temp_num = 1,
> +	.temp_bus = 0,
> +};
> +
> +static struct ddb_info ddb_octopus_mini = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Digital Devices Octopus Mini",
> +	.port_num = 4,
> +	.i2c_num  = 4,
>  };
>  
>  static struct ddb_info ddb_v6 = {
>  	.type     = DDB_OCTOPUS,
>  	.name     = "Digital Devices Cine S2 V6 DVB adapter",
>  	.port_num = 3,
> +	.i2c_num  = 3,
> +};
> +
> +static struct ddb_info ddb_v6_5 = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
> +	.port_num = 4,
> +	.i2c_num  = 4,
> +};
> +
> +static struct ddb_info ddb_satixS2v3 = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
> +	.port_num = 3,
> +	.i2c_num  = 3,
> +};
> +
> +static struct ddb_info ddb_ci = {
> +	.type     = DDB_OCTOPUS_CI,
> +	.name     = "Digital Devices Octopus CI",
> +	.port_num = 4,
> +	.i2c_num  = 2,
> +};
> +
> +static struct ddb_info ddb_cis = {
> +	.type     = DDB_OCTOPUS_CI,
> +	.name     = "Digital Devices Octopus CI single",
> +	.port_num = 3,
> +	.i2c_num  = 2,
> +};
> +
> +static struct ddb_info ddb_dvbct = {
> +	.type     = DDB_OCTOPUS,
> +	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
> +	.port_num = 3,
> +	.i2c_num  = 3,
> +};
> +
> +static struct ddb_info ddb_mod = {
> +	.type     = DDB_MOD,
> +	.name     = "Digital Devices DVB-C modulator",
> +	.port_num = 10,
> +	.temp_num = 1,
>  };
>  
>  #define DDVID 0xdd01 /* Digital Devices Vendor ID */
>  
> -#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
> +#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
>  	.vendor      = _vend,    .device    = _dev, \
>  	.subvendor   = _subvend, .subdevice = _subdev, \
>  	.driver_data = (unsigned long)&_driverdata }
>  
> -static const struct pci_device_id ddb_id_tbl[] = {
> +static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
>  	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
>  	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
> +	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
>  	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
> -	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
> +	DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem),
> +	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
>  	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
> +	DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
> +	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
> +	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
> +	DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
> +	DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
> +	DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
>  	/* in case sub-ids got deleted in flash */
>  	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
> +	DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
> +	DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
>  	{0}
>  };
>  MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
>  
> -
>  static struct pci_driver ddb_pci_driver = {
> -	.name        = "DDBridge",
> +	.name        = "ddbridge",
>  	.id_table    = ddb_id_tbl,
>  	.probe       = ddb_probe,
>  	.remove      = ddb_remove,
> @@ -1700,23 +3080,30 @@ static struct pci_driver ddb_pci_driver = {
>  
>  static __init int module_init_ddbridge(void)
>  {
> -	int ret;
> -
> -	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
> -	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
> +	int stat = -1;
>  
> -	ret = ddb_class_create();
> -	if (ret < 0)
> -		return ret;
> -	ret = pci_register_driver(&ddb_pci_driver);
> -	if (ret < 0)
> -		ddb_class_destroy();
> -	return ret;
> +	printk(KERN_INFO "Digital Devices PCIE bridge driver 0.9.9, "
> +	       "Copyright (C) 2010-13 Digital Devices GmbH\n");
> +	if (ddb_class_create() < 0)
> +		return -1;
> +	ddb_wq = create_workqueue("ddbridge");
> +	if (ddb_wq == NULL)
> +		goto exit1;
> +	stat = pci_register_driver(&ddb_pci_driver);
> +	if (stat < 0)
> +		goto exit2;
> +	return stat;
> +exit2:
> +	destroy_workqueue(ddb_wq);
> +exit1:
> +	ddb_class_destroy();
> +	return stat;
>  }
>  
>  static __exit void module_exit_ddbridge(void)
>  {
>  	pci_unregister_driver(&ddb_pci_driver);
> +	destroy_workqueue(ddb_wq);
>  	ddb_class_destroy();
>  }
>  
> @@ -1724,6 +3111,6 @@ module_init(module_init_ddbridge);
>  module_exit(module_exit_ddbridge);
>  
>  MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
> -MODULE_AUTHOR("Ralph Metzler");
> +MODULE_AUTHOR("Ralph Metzler, Metzler Brothers Systementwicklung");
>  MODULE_LICENSE("GPL");
> -MODULE_VERSION("0.5");
> +MODULE_VERSION("0.9.10");


-- 

Cheers,
Mauro

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

* Re: [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes
  2013-11-03  0:45 ` [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes Maik Broemme
@ 2013-11-03 10:50   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:50 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:45:31 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Updated ddbridge header for 0.9.10 changes.

Those changes should not be on a separate patch, as it will for sure
break compilation.

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/pci/ddbridge/ddbridge.h | 408 ++++++++++++++++++++++++++++------
>  1 file changed, 343 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
> index 8b1b41d..f35a5b4 100644
> --- a/drivers/media/pci/ddbridge/ddbridge.h
> +++ b/drivers/media/pci/ddbridge/ddbridge.h
> @@ -1,38 +1,69 @@
>  /*
> - * ddbridge.h: Digital Devices PCIe bridge driver
> + *  ddbridge.h: Digital Devices PCIe bridge driver
>   *
> - * Copyright (C) 2010-2011 Digital Devices GmbH
> + *  Copyright (C) 2010-2013 Digital Devices GmbH
> + *  Copyright (C) 2013 Maik Broemme <mbroemme@parallels.com>
>   *
> - * 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 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.
>   *
> - * 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
> + *  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
>   */
>  
>  #ifndef _DDBRIDGE_H_
>  #define _DDBRIDGE_H_
>  
> +#include <linux/version.h>
> +
> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
> +#define __devexit
> +#define __devinit
> +#endif
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/poll.h>
> +#include <linux/io.h>
> +#include <linux/pci.h>
> +#include <linux/pci_ids.h>
> +#include <linux/timer.h>
> +#include <linux/i2c.h>
> +#include <linux/swab.h>
> +#include <linux/vmalloc.h>
> +#include <linux/workqueue.h>
> +#include <linux/kthread.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/spi/spi.h>
> +#include <linux/gpio.h>
> +#include <linux/completion.h>
> +
>  #include <linux/types.h>
>  #include <linux/sched.h>
>  #include <linux/interrupt.h>
>  #include <linux/i2c.h>
>  #include <linux/mutex.h>
>  #include <asm/dma.h>
> -#include <linux/dvb/frontend.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/uaccess.h>
> +
>  #include <linux/dvb/ca.h>
>  #include <linux/socket.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
>  
>  #include "dmxdev.h"
>  #include "dvbdev.h"
> @@ -44,51 +75,83 @@
>  #include "cxd2099.h"
>  
>  #define DDB_MAX_I2C     4
> -#define DDB_MAX_PORT    4
> +#define DDB_MAX_PORT   10
>  #define DDB_MAX_INPUT   8
> -#define DDB_MAX_OUTPUT  4
> +#define DDB_MAX_OUTPUT 10
> +
> +struct ddb_regset {
> +	uint32_t base;
> +	uint32_t num;
> +	uint32_t size;
> +};
> +
> +struct ddb_regmap {
> +	struct ddb_regset i2c;
> +	struct ddb_regset i2c_buf;
> +	struct ddb_regset dma;
> +	struct ddb_regset dma_buf;
> +	struct ddb_regset input;
> +	struct ddb_regset output;
> +	struct ddb_regset channel;
> +	struct ddb_regset ci;
> +	struct ddb_regset pid_filter;
> +};
>  
>  struct ddb_info {
>  	int   type;
>  #define DDB_NONE         0
>  #define DDB_OCTOPUS      1
> +#define DDB_OCTOPUS_CI   2
> +#define DDB_MOD          3
> +#define DDB_OCTONET      4
>  	char *name;
>  	int   port_num;
> -	u32   port_type[DDB_MAX_PORT];
> +	int   i2c_num;
> +	int   led_num;
> +	int   fan_num;
> +	int   temp_num;
> +	int   temp_bus;
> +	struct ddb_regmap regmap;
>  };
>  
> -/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
> +/* DMA_SIZE MUST be smaller than 256k and 
> +   MUST be divisible by 188 and 128 !!! */
> +
> +#define DMA_MAX_BUFS 32      /* hardware table limit */
>  
> -#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
>  #define INPUT_DMA_BUFS 8
>  #define INPUT_DMA_SIZE (128*47*21)
> +#define INPUT_DMA_IRQ_DIV 1
>  
> -#define OUTPUT_DMA_MAX_BUFS 32
>  #define OUTPUT_DMA_BUFS 8
>  #define OUTPUT_DMA_SIZE (128*47*21)
> +#define OUTPUT_DMA_IRQ_DIV 1
>  
>  struct ddb;
>  struct ddb_port;
>  
> -struct ddb_input {
> -	struct ddb_port       *port;
> +struct ddb_dma {
> +	void                  *io;
>  	u32                    nr;
> -	int                    attached;
> -
> -	dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
> -	u8                    *vbuf[INPUT_DMA_MAX_BUFS];
> -	u32                    dma_buf_num;
> -	u32                    dma_buf_size;
> -
> -	struct tasklet_struct  tasklet;
> +	dma_addr_t             pbuf[DMA_MAX_BUFS];
> +	u8                    *vbuf[DMA_MAX_BUFS];
> +	u32                    num;
> +	u32                    size;
> +	u32                    div;
> +	u32                    bufreg;
> +	struct work_struct     work;
>  	spinlock_t             lock;
>  	wait_queue_head_t      wq;
>  	int                    running;
>  	u32                    stat;
> +	u32                    ctrl;
>  	u32                    cbuf;
>  	u32                    coff;
> +};
>  
> -	struct dvb_adapter     adap;
> +struct ddb_dvb {
> +	struct dvb_adapter    *adap;
> +	int                    adap_registered;
>  	struct dvb_device     *dev;
>  	struct dvb_frontend   *fe;
>  	struct dvb_frontend   *fe2;
> @@ -99,37 +162,35 @@ struct ddb_input {
>  	struct dmx_frontend    mem_frontend;
>  	int                    users;
>  	int (*gate_ctrl)(struct dvb_frontend *, int);
> +	int                    attached;
>  };
>  
> -struct ddb_output {
> +struct ddb_ci {
> +	struct dvb_ca_en50221  en;
>  	struct ddb_port       *port;
>  	u32                    nr;
> -	dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
> -	u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
> -	u32                    dma_buf_num;
> -	u32                    dma_buf_size;
> -	struct tasklet_struct  tasklet;
> -	spinlock_t             lock;
> -	wait_queue_head_t      wq;
> -	int                    running;
> -	u32                    stat;
> -	u32                    cbuf;
> -	u32                    coff;
> +	struct mutex           lock;
> +};
>  
> -	struct dvb_adapter     adap;
> -	struct dvb_device     *dev;
> +struct ddb_io {
> +	struct ddb_port       *port;
> +	u32                    nr;
> +	struct ddb_dma        *dma;
> +	struct ddb_io         *redo;
> +	struct ddb_io         *redi;
>  };
>  
> +#define ddb_output ddb_io
> +#define ddb_input ddb_io
> +
>  struct ddb_i2c {
>  	struct ddb            *dev;
>  	u32                    nr;
>  	struct i2c_adapter     adap;
> -	struct i2c_adapter     adap2;
>  	u32                    regs;
>  	u32                    rbuf;
>  	u32                    wbuf;
> -	int                    done;
> -	wait_queue_head_t      wq;
> +	struct completion      completion;
>  };
>  
>  struct ddb_port {
> @@ -141,45 +202,262 @@ struct ddb_port {
>  #define DDB_PORT_NONE           0
>  #define DDB_PORT_CI             1
>  #define DDB_PORT_TUNER          2
> +#define DDB_PORT_LOOP           3
> +#define DDB_PORT_MOD            4
>  	u32                    type;
>  #define DDB_TUNER_NONE          0
>  #define DDB_TUNER_DVBS_ST       1
>  #define DDB_TUNER_DVBS_ST_AA    2
> -#define DDB_TUNER_DVBCT_TR     16
> -#define DDB_TUNER_DVBCT_ST     17
> +#define DDB_TUNER_DVBCT_TR      3
> +#define DDB_TUNER_DVBCT_ST      4
> +#define DDB_CI_INTERNAL         5
> +#define DDB_CI_EXTERNAL_SONY    6
> +#define DDB_TUNER_XO2           16
> +#define DDB_TUNER_DVBS          16
> +#define DDB_TUNER_DVBCT2_SONY   17
> +#define DDB_TUNER_ISDBT_SONY    18
> +#define DDB_TUNER_DVBC2T2_SONY  19
> +#define DDB_TUNER_ATSC_ST       20
> +#define DDB_TUNER_DVBC2T2_ST    21
> +
>  	u32                    adr;
>  
>  	struct ddb_input      *input[2];
>  	struct ddb_output     *output;
>  	struct dvb_ca_en50221 *en;
> +	struct ddb_dvb         dvb[2];
> +	u32                    gap;
> +	u32                    obr;
> +};
> +
> +struct mod_base {
> +	u32                    frequency;
> +
> +	u32                    flat_start;
> +	u32                    flat_end;
> +};
> +
> +struct mod_state {
> +	u32                    modulation;
> +
> +	u32                    do_handle;
> +
> +	u32                    rate_inc;
> +	u32                    Control;
> +	u32                    State;
> +	u32                    StateCounter;
> +	s32                    LastPCRAdjust;
> +	s32                    PCRAdjustSum;
> +	s32                    InPacketsSum;
> +	s32                    OutPacketsSum;
> +	s64                    PCRIncrement;
> +	s64                    PCRDecrement;
> +	s32                    PCRRunningCorr;
> +	u32                    OutOverflowPacketCount;
> +	u32                    InOverflowPacketCount;
> +	u32                    LastOutPacketCount;
> +	u32                    LastInPacketCount;
> +	u64                    LastOutPackets;
> +	u64                    LastInPackets;
> +	u32                    MinInputPackets;
> +};
> +
> +#define CM_STARTUP_DELAY 2
> +#define CM_AVERAGE  20
> +#define CM_GAIN     10
> +
> +#define HW_LSB_SHIFT    12
> +#define HW_LSB_MASK     0x1000
> +
> +#define CM_IDLE    0
> +#define CM_STARTUP 1
> +#define CM_ADJUST  2
> +
> +#define TS_CAPTURE_LEN  (21*188)
> +
> +/* net streaming hardware block */
> +#define DDB_NS_MAX 15
> +
> +struct ddb_ns {
> +	struct ddb_input      *input; 
> +	int                    nr;
> +	int                    fe;
> +	u32                    rtcp_udplen;
> +	u32                    rtcp_len;
> +	u32                    ts_offset;
> +	u32                    udplen;
> +	u8                     p[512];
>  };
>  
>  struct ddb {
>  	struct pci_dev        *pdev;
> +	struct platform_device *pfdev;
> +	struct device         *dev;
> +	const struct pci_device_id *id;
> +	struct ddb_info       *info;
> +	int                    msi;
> +	struct workqueue_struct *wq;
> +	u32                    has_dma;
> +	u32                    has_ns;
> +
> +	struct ddb_regmap      regmap;
>  	unsigned char         *regs;
> +	u32                    regs_len;
>  	struct ddb_port        port[DDB_MAX_PORT];
>  	struct ddb_i2c         i2c[DDB_MAX_I2C];
>  	struct ddb_input       input[DDB_MAX_INPUT];
>  	struct ddb_output      output[DDB_MAX_OUTPUT];
> +	struct dvb_adapter     adap[DDB_MAX_INPUT];
> +	struct ddb_dma         dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT];
> +
> +	void                   (*handler[32])(unsigned long);
> +	unsigned long          handler_data[32];
>  
>  	struct device         *ddb_dev;
> -	int                    nr;
> +	u32                    ddb_dev_users;
> +	u32                    nr;
>  	u8                     iobuf[1028];
>  
> -	struct ddb_info       *info;
> -	int                    msi;
> +	u8                     leds;
> +	u32                    ts_irq;
> +	u32                    i2c_irq;
> +
> +	u32                    hwid;
> +	u32                    regmapid;
> +	u32                    mac;
> +	u32                    devid;
> +
> +	int                    ns_num;
> +	struct ddb_ns          ns[DDB_NS_MAX];
> +	struct mutex           mutex;
> +
> +	struct dvb_device     *nsd_dev;
> +	u8                     tsbuf[TS_CAPTURE_LEN];
> +
> +	struct mod_base        mod_base;
> +	struct mod_state       mod[10];
> +};
> +
> +static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
> +{
> +	writeb(val, (char *) (dev->regs+(adr)));
> +}
> +
> +static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr)
> +{
> +	writel(val, (char *) (dev->regs+(adr)));
> +}
> +
> +static inline void ddbwritew(struct ddb *dev, u16 val, u32 adr)
> +{
> +	writew(val, (char *) (dev->regs+(adr)));
> +}
> +
> +static inline u32 ddbreadl(struct ddb *dev, u32 adr)
> +{
> +	return readl((char *) (dev->regs+(adr)));
> +}
> +
> +static inline u32 ddbreadb(struct ddb *dev, u32 adr)
> +{
> +	return readb((char *) (dev->regs+(adr)));
> +}
> +
> +#define ddbcpyto(_dev, _adr, _src, _count) \
> +	memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count))
> +
> +#define ddbcpyfrom(_dev, _dst, _adr, _count) \
> +	memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count))
> +
> +#define ddbmemset(_dev, _adr, _val, _count) \
> +	memset_io((char *) (_dev->regs + (_adr)), (_val), (_count))
> +
> +#define dd_uint8    u8
> +#define dd_uint16   u16
> +#define dd_int16    s16
> +#define dd_uint32   u32
> +#define dd_int32    s32
> +#define dd_uint64   u64
> +#define dd_int64    s64
> +
> +#define DDMOD_FLASH_START  0x1000
> +
> +struct DDMOD_FLASH_DS {
> +	dd_uint32   Symbolrate;             /* kSymbols/s */
> +	dd_uint32   DACFrequency;           /* kHz        */
> +	dd_uint16   FrequencyResolution;    /* kHz        */
> +	dd_uint16   IQTableLength;
> +	dd_uint16   FrequencyFactor;
> +	dd_int16    PhaseCorr;              /* TBD        */
> +	dd_uint32   Control2;
> +	dd_uint16   PostScaleI;   
> +	dd_uint16   PostScaleQ;
> +	dd_uint16   PreScale;
> +	dd_int16    EQTap[11];
> +	dd_uint16   FlatStart;   
> +	dd_uint16   FlatEnd;
> +	dd_uint32   FlashOffsetPrecalculatedIQTables;       /* 0 = none */
> +	dd_uint8    Reserved[28];
> +
> +};
> +
> +struct DDMOD_FLASH {
> +	dd_uint32   Magic;
> +	dd_uint16   Version;
> +	dd_uint16   DataSets;
> +	
> +	dd_uint16   VCORefFrequency;    /* MHz */
> +	dd_uint16   VCO1Frequency;      /* MHz */
> +	dd_uint16   VCO2Frequency;      /* MHz */
> +	
> +	dd_uint16   DACAux1;    /* TBD */
> +	dd_uint16   DACAux2;    /* TBD */
> +	
> +	dd_uint8    Reserved1[238];
> +	
> +	struct DDMOD_FLASH_DS DataSet[1];
> +};
> +
> +#define DDMOD_FLASH_MAGIC   0x5F564d5F
> +
> +struct dvb_mod_params {
> +	__u32 base_frequency;
> +	__u32 attenuator;
>  };
>  
> -/****************************************************************************/
> +struct dvb_mod_channel_params {
> +	enum fe_modulation modulation;
> +	__u32 rate_increment;
> +};
> +
> +#define DVB_MOD_SET		_IOW('o', 208, struct dvb_mod_params)
> +#define DVB_MOD_CHANNEL_SET	_IOW('o', 209, struct dvb_mod_channel_params)
> +
> +/* DDBridge flash functions (ddbridge-core.c) */
> +int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len);
>  
> -#define ddbwritel(_val, _adr)        writel((_val), \
> -				     (char *) (dev->regs+(_adr)))
> -#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
> -#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)	\
> -				     (dev->regs+(_adr)), (_src), (_count))
> -#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
> -				       (dev->regs+(_adr)), (_count))
> +/* DDBridge DVB-C modulator functions (ddbridge-mod.c) */
> +int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
> +int ddbridge_mod_init(struct ddb *dev);
> +void ddbridge_mod_output_stop(struct ddb_output *output);
> +void ddbridge_mod_output_start(struct ddb_output *output);
> +void ddbridge_mod_rate_handler(unsigned long data);
>  
> -/****************************************************************************/
> +/* DDBrigde I2C functions (ddbridge-i2c.c) */
> +int ddb_i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len);
> +int ddb_i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val);
> +int ddb_i2c_read_regs(struct i2c_adapter *adapter,
> + 		 u8 adr, u8 reg, u8 *val, u8 len);
> +int ddb_i2c_read_regs16(struct i2c_adapter *adapter, 
> + 		   u8 adr, u16 reg, u8 *val, u8 len);
> +int ddb_i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val);
> +int ddb_i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
> + 		  u16 reg, u8 *val);
> +int ddb_i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
> + 		   u16 reg, u8 val);
> +int ddb_i2c_write_reg(struct i2c_adapter *adap, u8 adr,
> + 		  u8 reg, u8 val);
> +void ddb_i2c_release(struct ddb *dev);
> +int ddb_i2c_init(struct ddb *dev);
>  
>  #endif


-- 

Cheers,
Mauro

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

* Re: [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge
  2013-11-03  0:46 ` [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge Maik Broemme
@ 2013-11-03 10:51   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:51 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:46:12 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Fixed Kconfig and Makefile to build latest version off ddbridge. It
> adds support for the following devices:
> 
>   - Octopus DVB adapter
>   - Octopus V3 DVB adapter
>   - Octopus LE DVB adapter
>   - Octopus OEM
>   - Octopus Mini
>   - Cine S2 V6 DVB adapter
>   - Cine S2 V6.5 DVB adapter
>   - Octopus CI
>   - Octopus CI single
>   - DVBCT V6.1 DVB adapter
>   - DVB-C modulator
>   - SaTiX-S2 V3 DVB adapter

Again, this won't work, as it would break compilation.

> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> ---
>  drivers/media/pci/ddbridge/Kconfig  | 21 +++++++++++++++------
>  drivers/media/pci/ddbridge/Makefile |  2 +-
>  2 files changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig
> index 44e5dc1..a30848f 100644
> --- a/drivers/media/pci/ddbridge/Kconfig
> +++ b/drivers/media/pci/ddbridge/Kconfig
> @@ -6,13 +6,22 @@ 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_STV0367DD if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT
>  	---help---
>  	  Support for cards with the Digital Devices PCI express bridge:
> -	  - Octopus PCIe Bridge
> -	  - Octopus mini PCIe Bridge
> -	  - Octopus LE
> -	  - DuoFlex S2 Octopus
> -	  - DuoFlex CT Octopus
> -	  - cineS2(v6)
> +	  - Octopus DVB adapter
> +	  - Octopus V3 DVB adapter
> +	  - Octopus LE DVB adapter
> +	  - Octopus OEM
> +	  - Octopus Mini
> +	  - Cine S2 V6 DVB adapter
> +	  - Cine S2 V6.5 DVB adapter
> +	  - Octopus CI
> +	  - Octopus CI single
> +	  - DVBCT V6.1 DVB adapter
> +	  - DVB-C modulator
> +	  - SaTiX-S2 V3 DVB adapter
>  
>  	  Say Y if you own such a card and want to use it.
> diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile
> index 7446c8b..c274b81 100644
> --- a/drivers/media/pci/ddbridge/Makefile
> +++ b/drivers/media/pci/ddbridge/Makefile
> @@ -2,7 +2,7 @@
>  # Makefile for the ddbridge device driver
>  #
>  
> -ddbridge-objs := ddbridge-core.o
> +ddbridge-objs := ddbridge-core.o ddbridge-i2c.o ddbridge-mod.o
>  
>  obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
>  


-- 

Cheers,
Mauro

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

* Re: [PATCH 00/12] DDBridge 0.9.10 driver updates
  2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
                   ` (11 preceding siblings ...)
  2013-11-03  0:46 ` [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge Maik Broemme
@ 2013-11-03 10:58 ` Mauro Carvalho Chehab
  2013-11-03 12:46   ` Maik Broemme
  12 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 10:58 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 01:22:35 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> I've updated the current DDBridge to latest version 0.9.10 from Ralph
> Metzler available at:
> 
> http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2
> 
> I've merged the driver to work with current v4l/dvb tree and I will
> maintain the driver for v4l/dvb in future. 

Works for me.

> The coming patch series is
> the first version and I explicitly want to get feedback and hints if
> some parts are merged at wrong places, etc... The following changes
> were made:
> 
>   - MSI enabled by default (some issues left with i2c timeouts)
>   - no support for Digital Devices Octonet
>   - no support for DVB Netstream
>   - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
>   - removed unused registers to cleanup code (might be added later again
>     if needed)

Be sure to not remove any feature that are currently needed for the
already supported devices to work.
> 
> The following devices are supported by the driver update:
> 
>   - Octopus DVB adapter
>   - Octopus V3 DVB adapter
>   - Octopus LE DVB adapter
>   - Octopus OEM
>   - Octopus Mini
>   - Cine S2 V6 DVB adapter
>   - Cine S2 V6.5 DVB adapter
>   - Octopus CI
>   - Octopus CI single
>   - DVBCT V6.1 DVB adapter
>   - DVB-C modulator
>   - SaTiX-S2 V3 DVB adapter
> 
> I might merge the Octonet and DVB Netstream drivers from Ralphs source
> later once the current committed DDBridge driver updates are merged in
> mainline.
> 
> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> 
> Maik Broemme (12):
>   dvb-frontends: Support for DVB-C2 to DVB frontends
>   tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
>   stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
>   tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
>   cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
>   dvb-core: export dvb_usercopy and new DVB device constants
>   ddbridge: Updated ddbridge registers
>   ddbridge: Moved i2c interfaces into separate file
>   ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
>   ddbridge: Update ddbridge driver to version 0.9.10
>   ddbridge: Update ddbridge header for 0.9.10 changes
>   ddbridge: Kconfig and Makefile fixes to build latest ddbridge
> 
>  drivers/media/dvb-core/dvbdev.c              |    1 
>  drivers/media/dvb-core/dvbdev.h              |    2 
>  drivers/media/dvb-frontends/Kconfig          |   31 
>  drivers/media/dvb-frontends/Makefile         |    3 
>  drivers/media/dvb-frontends/cxd2843.c        | 1647 ++++++++++++
>  drivers/media/dvb-frontends/cxd2843.h        |   47 
>  drivers/media/dvb-frontends/stv0367dd.c      | 2329 ++++++++++++++++++
>  drivers/media/dvb-frontends/stv0367dd.h      |   48 
>  drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 +++++++++++++++++++++++++++
>  drivers/media/dvb-frontends/tda18212dd.c     |  934 +++++++
>  drivers/media/dvb-frontends/tda18212dd.h     |   37 
>  drivers/media/pci/ddbridge/Kconfig           |   21 
>  drivers/media/pci/ddbridge/Makefile          |    2 
>  drivers/media/pci/ddbridge/ddbridge-core.c   | 3085 +++++++++++++++++-------
>  drivers/media/pci/ddbridge/ddbridge-i2c.c    |  239 +
>  drivers/media/pci/ddbridge/ddbridge-mod.c    | 1033 ++++++++
>  drivers/media/pci/ddbridge/ddbridge-regs.h   |  273 +-
>  drivers/media/pci/ddbridge/ddbridge.h        |  408 ++-
>  include/uapi/linux/dvb/frontend.h            |    1 
>  19 files changed, 12555 insertions(+), 1028 deletions(-)
> 
> --Maik
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks for your submission.

I'm seeing this entire patch series as an RFC. There are simply too much
changes required for us to be able to do a more detailed review on it.

Please do the pointed changes, in special:

	- Don't let any patch to break compilation;

	- Please verify the Documentation/CodingStyle and check it with
		./scripts/checkpatch.pl;

	- Please discuss on a separate thread the API changes for CI,
	  modulator and DVB-C2;

	- Please try to break the ddbridge changes into one change per
	  patch. If not possible, please try to at least break them more,
	  to help us to review the changes;

	- Please don't duplicate existing drivers without a very very good
	  reason.

Thanks!
Mauro

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

* Re: [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends
  2013-11-03 10:47     ` Ralph Metzler
@ 2013-11-03 11:22       ` Mauro Carvalho Chehab
  2013-11-03 12:20       ` Maik Broemme
  1 sibling, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-03 11:22 UTC (permalink / raw)
  To: Ralph Metzler; +Cc: Linux Media Mailing List

Em Sun, 3 Nov 2013 11:47:52 +0100
Ralph Metzler <rjkm@metzlerbros.de> escreveu:

> Mauro Carvalho Chehab writes:
>  > Em Sun, 3 Nov 2013 01:24:25 +0100
>  > Maik Broemme <mbroemme@parallels.com> escreveu:
>  > 
>  > > Added support for DVB-C2 to DVB frontends. It will be required
>  > > by cxd2843 and tda18212dd (Digital Devices) frontends.
>  > > 
>  > > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
>  > > ---
>  > >  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 */
>  > 
>  > Please update also the documentation, at Documentation/DocBook/media/dvb.
>  > 
>  > Doesn't DVB-C2 provide any newer property? If so, please add it there as
>  > well, and at frontend.h.
>  > 
> 
> I asked about this on linux-media a week or so ago. 

Oh! Well, several developers were out last week, as we had the media workshop
on Oct, 23. So, we likely missed it.

> The main question was
> concerning STREAM_ID. I asked if it would be fine to combine PLP and
> slice id (each 8 bit) into stream_id or if there should be a separate 
> new property. And for which one, PLP or slice id? 
> Probably slice id, because stream_id is also used for PLP in T2?
> I combined them into stream_id for now (but that was after the 0.9.10 version
> of the dddvb package).
> 
> There are also many new qam types, etc. but, as I said back then, it was not  
> urgent for me to add those because the Sony demod does not allow setting those.
> At least it is not documented how to do it.

Ok, let me answer to that thread, in order to have all the discussions on
a single one.

Regards,
Mauro
-- 

Cheers,
Mauro

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

* Re: [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
  2013-11-03  9:27   ` Mauro Carvalho Chehab
@ 2013-11-03 12:17     ` Maik Broemme
  2013-11-04 12:13       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-03 12:17 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: Linux Media Mailing List

Hi Mauro,

Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
> Em Sun, 3 Nov 2013 01:25:23 +0100
> Maik Broemme <mbroemme@parallels.com> escreveu:
> 
> > Added (DD) to NXP TDA18271C2 silicon tuner as this tuner was
> > specifically added for Digital Devices ddbridge driver.
> > 
> > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> > ---
> >  drivers/media/dvb-frontends/Kconfig | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> > index bddbab4..6f99eb8 100644
> > --- a/drivers/media/dvb-frontends/Kconfig
> > +++ b/drivers/media/dvb-frontends/Kconfig
> > @@ -48,11 +48,11 @@ config DVB_DRXK
> >  	  Say Y when you want to support this frontend.
> >  
> >  config DVB_TDA18271C2DD
> > -	tristate "NXP TDA18271C2 silicon tuner"
> > +	tristate "NXP TDA18271C2 silicon tuner (DD)"
> >  	depends on DVB_CORE && I2C
> >  	default m if !MEDIA_SUBDRV_AUTOSELECT
> >  	help
> > -	  NXP TDA18271 silicon tuner.
> > +	  NXP TDA18271 silicon tuner (Digital Devices driver).
> >  
> >  	  Say Y when you want to support this tuner.
> >  
> 
> The better is to use the other tda18271 driver. This one was added as a
> temporary alternative, as the more complete one were lacking some
> features, and were not working with DRX-K. Well, those got fixed already,
> and we now want to get rid of this duplicated driver.
> 

Agree. Probably the tda18271 will need some extensions to work with
ddbridge and I will see what I can do the next days to get it working.

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

--Maik

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

* Re: [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends
  2013-11-03 10:47     ` Ralph Metzler
  2013-11-03 11:22       ` Mauro Carvalho Chehab
@ 2013-11-03 12:20       ` Maik Broemme
  1 sibling, 0 replies; 39+ messages in thread
From: Maik Broemme @ 2013-11-03 12:20 UTC (permalink / raw)
  To: Ralph Metzler; +Cc: Linux Media Mailing List

Hi Ralph,

Ralph Metzler <rjkm@metzlerbros.de> wrote:
> Mauro Carvalho Chehab writes:
>  > Em Sun, 3 Nov 2013 01:24:25 +0100
>  > Maik Broemme <mbroemme@parallels.com> escreveu:
>  > 
>  > > Added support for DVB-C2 to DVB frontends. It will be required
>  > > by cxd2843 and tda18212dd (Digital Devices) frontends.
>  > > 
>  > > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
>  > > ---
>  > >  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 */
>  > 
>  > Please update also the documentation, at Documentation/DocBook/media/dvb.
>  > 
>  > Doesn't DVB-C2 provide any newer property? If so, please add it there as
>  > well, and at frontend.h.
>  > 
> 
> I asked about this on linux-media a week or so ago. The main question was
> concerning STREAM_ID. I asked if it would be fine to combine PLP and
> slice id (each 8 bit) into stream_id or if there should be a separate 
> new property. And for which one, PLP or slice id? 
> Probably slice id, because stream_id is also used for PLP in T2?
> I combined them into stream_id for now (but that was after the 0.9.10 version
> of the dddvb package).
> 

Do you have a patch ready at this time? I'm asking because CXD2843ER
depends on DVB-C2 changes.

> There are also many new qam types, etc. but, as I said back then, it was not  
> urgent for me to add those because the Sony demod does not allow setting those.
> At least it is not documented how to do it.
> 
> 
> Regards,
> Ralph
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--Maik

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

* Re: [PATCH 00/12] DDBridge 0.9.10 driver updates
  2013-11-03 10:58 ` [PATCH 00/12] DDBridge 0.9.10 driver updates Mauro Carvalho Chehab
@ 2013-11-03 12:46   ` Maik Broemme
  2013-11-03 13:11     ` Ralph Metzler
  2013-11-04 12:19     ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 39+ messages in thread
From: Maik Broemme @ 2013-11-03 12:46 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: Linux Media Mailing List

Hi Mauro,

Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
> Em Sun, 3 Nov 2013 01:22:35 +0100
> Maik Broemme <mbroemme@parallels.com> escreveu:
> 
> > I've updated the current DDBridge to latest version 0.9.10 from Ralph
> > Metzler available at:
> > 
> > http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2
> > 
> > I've merged the driver to work with current v4l/dvb tree and I will
> > maintain the driver for v4l/dvb in future. 
> 
> Works for me.
> 
> > The coming patch series is
> > the first version and I explicitly want to get feedback and hints if
> > some parts are merged at wrong places, etc... The following changes
> > were made:
> > 
> >   - MSI enabled by default (some issues left with i2c timeouts)
> >   - no support for Digital Devices Octonet
> >   - no support for DVB Netstream
> >   - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
> >   - removed unused registers to cleanup code (might be added later again
> >     if needed)
> 
> Be sure to not remove any feature that are currently needed for the
> already supported devices to work.

Of course I won't do. The Octonet and DVB Netstream weren't supported in
current driver. MSI is already supported but was not enabled by default
because the old 0.5 version currently in kernel had some problems with
it. However new one works fine with MSI - at least for me I'm using the
patchset myself already - but needs some further testing.

> > 
> > The following devices are supported by the driver update:
> > 
> >   - Octopus DVB adapter
> >   - Octopus V3 DVB adapter
> >   - Octopus LE DVB adapter
> >   - Octopus OEM
> >   - Octopus Mini
> >   - Cine S2 V6 DVB adapter
> >   - Cine S2 V6.5 DVB adapter
> >   - Octopus CI
> >   - Octopus CI single
> >   - DVBCT V6.1 DVB adapter
> >   - DVB-C modulator
> >   - SaTiX-S2 V3 DVB adapter
> > 
> > I might merge the Octonet and DVB Netstream drivers from Ralphs source
> > later once the current committed DDBridge driver updates are merged in
> > mainline.
> > 
> > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> > 
> > Maik Broemme (12):
> >   dvb-frontends: Support for DVB-C2 to DVB frontends
> >   tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
> >   stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
> >   tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
> >   cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
> >   dvb-core: export dvb_usercopy and new DVB device constants
> >   ddbridge: Updated ddbridge registers
> >   ddbridge: Moved i2c interfaces into separate file
> >   ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
> >   ddbridge: Update ddbridge driver to version 0.9.10
> >   ddbridge: Update ddbridge header for 0.9.10 changes
> >   ddbridge: Kconfig and Makefile fixes to build latest ddbridge
> > 
> >  drivers/media/dvb-core/dvbdev.c              |    1 
> >  drivers/media/dvb-core/dvbdev.h              |    2 
> >  drivers/media/dvb-frontends/Kconfig          |   31 
> >  drivers/media/dvb-frontends/Makefile         |    3 
> >  drivers/media/dvb-frontends/cxd2843.c        | 1647 ++++++++++++
> >  drivers/media/dvb-frontends/cxd2843.h        |   47 
> >  drivers/media/dvb-frontends/stv0367dd.c      | 2329 ++++++++++++++++++
> >  drivers/media/dvb-frontends/stv0367dd.h      |   48 
> >  drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 +++++++++++++++++++++++++++
> >  drivers/media/dvb-frontends/tda18212dd.c     |  934 +++++++
> >  drivers/media/dvb-frontends/tda18212dd.h     |   37 
> >  drivers/media/pci/ddbridge/Kconfig           |   21 
> >  drivers/media/pci/ddbridge/Makefile          |    2 
> >  drivers/media/pci/ddbridge/ddbridge-core.c   | 3085 +++++++++++++++++-------
> >  drivers/media/pci/ddbridge/ddbridge-i2c.c    |  239 +
> >  drivers/media/pci/ddbridge/ddbridge-mod.c    | 1033 ++++++++
> >  drivers/media/pci/ddbridge/ddbridge-regs.h   |  273 +-
> >  drivers/media/pci/ddbridge/ddbridge.h        |  408 ++-
> >  include/uapi/linux/dvb/frontend.h            |    1 
> >  19 files changed, 12555 insertions(+), 1028 deletions(-)
> > 
> > --Maik
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> Thanks for your submission.
> 
> I'm seeing this entire patch series as an RFC. There are simply too much
> changes required for us to be able to do a more detailed review on it.
> 

Many thanks for the feedback.

> Please do the pointed changes, in special:
> 
> 	- Don't let any patch to break compilation;
> 
> 	- Please verify the Documentation/CodingStyle and check it with
> 		./scripts/checkpatch.pl;
> 
> 	- Please discuss on a separate thread the API changes for CI,
> 	  modulator and DVB-C2;
> 
> 	- Please try to break the ddbridge changes into one change per
> 	  patch. If not possible, please try to at least break them more,
> 	  to help us to review the changes;
> 
> 	- Please don't duplicate existing drivers without a very very good
> 	  reason.
> 

I will address the concerns with re-submission of the patches. Most
probably it is worth to split the patchset a bit. The CXD2843
demodulator can also be used by other drivers so I will address your
feedback on this driver first and re-submit. Once it is fine I will
re-send changes for ddbridge. Hope it is a good approach. :)

> Thanks!
> Mauro

--Maik

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

* Re: [PATCH 00/12] DDBridge 0.9.10 driver updates
  2013-11-03 12:46   ` Maik Broemme
@ 2013-11-03 13:11     ` Ralph Metzler
  2013-11-03 13:19       ` Maik Broemme
  2013-11-04 12:19     ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 39+ messages in thread
From: Ralph Metzler @ 2013-11-03 13:11 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Maik Broemme writes:
 > Hi Mauro,
 > 
 > Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
 > > Em Sun, 3 Nov 2013 01:22:35 +0100
 > > Maik Broemme <mbroemme@parallels.com> escreveu:
 > > 
 > > > I've updated the current DDBridge to latest version 0.9.10 from Ralph
 > > > Metzler available at:
 > > > 
 > > > http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2
 > > > 
 > > > I've merged the driver to work with current v4l/dvb tree and I will
 > > > maintain the driver for v4l/dvb in future. 
 > > 
 > > Works for me.
 > > 
 > > > The coming patch series is
 > > > the first version and I explicitly want to get feedback and hints if
 > > > some parts are merged at wrong places, etc... The following changes
 > > > were made:
 > > > 
 > > >   - MSI enabled by default (some issues left with i2c timeouts)
 > > >   - no support for Digital Devices Octonet
 > > >   - no support for DVB Netstream
 > > >   - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
 > > >   - removed unused registers to cleanup code (might be added later again
 > > >     if needed)
 > > 
 > > Be sure to not remove any feature that are currently needed for the
 > > already supported devices to work.
 > 
 > Of course I won't do. The Octonet and DVB Netstream weren't supported in
 > current driver. MSI is already supported but was not enabled by default
 > because the old 0.5 version currently in kernel had some problems with
 > it. However new one works fine with MSI - at least for me I'm using the
 > patchset myself already - but needs some further testing.

Some people still have problems with MSI. I am not sure if it depends on the 
board type and/or BIOS version, etc. 


Regards,
Ralph

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

* Re: [PATCH 00/12] DDBridge 0.9.10 driver updates
  2013-11-03 13:11     ` Ralph Metzler
@ 2013-11-03 13:19       ` Maik Broemme
  0 siblings, 0 replies; 39+ messages in thread
From: Maik Broemme @ 2013-11-03 13:19 UTC (permalink / raw)
  To: Ralph Metzler; +Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Hi Ralph,

Ralph Metzler <rjkm@metzlerbros.de> wrote:
> Maik Broemme writes:
>  > Hi Mauro,
>  > 
>  > Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
>  > > Em Sun, 3 Nov 2013 01:22:35 +0100
>  > > Maik Broemme <mbroemme@parallels.com> escreveu:
>  > > 
>  > > > I've updated the current DDBridge to latest version 0.9.10 from Ralph
>  > > > Metzler available at:
>  > > > 
>  > > > http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2
>  > > > 
>  > > > I've merged the driver to work with current v4l/dvb tree and I will
>  > > > maintain the driver for v4l/dvb in future. 
>  > > 
>  > > Works for me.
>  > > 
>  > > > The coming patch series is
>  > > > the first version and I explicitly want to get feedback and hints if
>  > > > some parts are merged at wrong places, etc... The following changes
>  > > > were made:
>  > > > 
>  > > >   - MSI enabled by default (some issues left with i2c timeouts)
>  > > >   - no support for Digital Devices Octonet
>  > > >   - no support for DVB Netstream
>  > > >   - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
>  > > >   - removed unused registers to cleanup code (might be added later again
>  > > >     if needed)
>  > > 
>  > > Be sure to not remove any feature that are currently needed for the
>  > > already supported devices to work.
>  > 
>  > Of course I won't do. The Octonet and DVB Netstream weren't supported in
>  > current driver. MSI is already supported but was not enabled by default
>  > because the old 0.5 version currently in kernel had some problems with
>  > it. However new one works fine with MSI - at least for me I'm using the
>  > patchset myself already - but needs some further testing.
> 
> Some people still have problems with MSI. I am not sure if it depends on the 
> board type and/or BIOS version, etc. 
> 

Then I will add a module option to enable/disable it and make non-MSI
configuration default.

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

--Maik

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

* Re: [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-03  9:56   ` Mauro Carvalho Chehab
@ 2013-11-03 17:00     ` Antti Palosaari
  2013-11-04 12:12       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 39+ messages in thread
From: Antti Palosaari @ 2013-11-03 17:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Maik Broemme; +Cc: Linux Media Mailing List

On 03.11.2013 11:56, Mauro Carvalho Chehab wrote:
> Hi Maik,
>
> Em Sun, 3 Nov 2013 01:31:04 +0100
> Maik Broemme <mbroemme@parallels.com> escreveu:
>
>> Added support for the NXP TDA18212 silicon tuner used by recent
>> Digital Devices hardware. This will allow update of ddbridge driver
>> to support newer devices.
>>
>> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
>> ---
>>   drivers/media/dvb-frontends/Kconfig      |   9 +
>>   drivers/media/dvb-frontends/Makefile     |   1 +
>>   drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
>>   drivers/media/dvb-frontends/tda18212dd.h |  37 ++
>
> I'm not sure if support for this tuner is not provided already by one of
> the existing drivers. If not, it is ok to submit a driver for it, but you
> should just call it as tda18212.
>
> I'm c/c Antti, as he worked on some NXP drivers recently, and may be aware
> if a driver already supports TDA18212.

Existing tda18212 driver I made is reverse-engineered and it is used 
only for Anysee devices, which I am also responsible. That new tuner 
driver is much more complete than what I have made and single driver is 
naturally the correct approach.

But one thing which annoys nowadays is that endless talking of 
regressions, which has led to situation it is very hard to make changes 
drivers that are used for multiple devices and you don't have all those 
devices to test. It is also OK to remove my old driver and use that, but 
then I likely lose my possibility to make changes, as I am much 
dependent on new driver maintainer. That is one existing problem which 
is seen multiple times during recent years... So I am perfectly happy 
with two drivers too.

regards
Antti


-- 
http://palosaari.fi/

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

* Re: [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-03 17:00     ` Antti Palosaari
@ 2013-11-04 12:12       ` Mauro Carvalho Chehab
  2013-11-04 12:49         ` Maik Broemme
  0 siblings, 1 reply; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-04 12:12 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: Maik Broemme, Linux Media Mailing List

Em Sun, 03 Nov 2013 19:00:22 +0200
Antti Palosaari <crope@iki.fi> escreveu:

> On 03.11.2013 11:56, Mauro Carvalho Chehab wrote:
> > Hi Maik,
> >
> > Em Sun, 3 Nov 2013 01:31:04 +0100
> > Maik Broemme <mbroemme@parallels.com> escreveu:
> >
> >> Added support for the NXP TDA18212 silicon tuner used by recent
> >> Digital Devices hardware. This will allow update of ddbridge driver
> >> to support newer devices.
> >>
> >> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> >> ---
> >>   drivers/media/dvb-frontends/Kconfig      |   9 +
> >>   drivers/media/dvb-frontends/Makefile     |   1 +
> >>   drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
> >>   drivers/media/dvb-frontends/tda18212dd.h |  37 ++
> >
> > I'm not sure if support for this tuner is not provided already by one of
> > the existing drivers. If not, it is ok to submit a driver for it, but you
> > should just call it as tda18212.
> >
> > I'm c/c Antti, as he worked on some NXP drivers recently, and may be aware
> > if a driver already supports TDA18212.
> 
> Existing tda18212 driver I made is reverse-engineered and it is used 
> only for Anysee devices, which I am also responsible. That new tuner 
> driver is much more complete than what I have made and single driver is 
> naturally the correct approach.
> 
> But one thing which annoys nowadays is that endless talking of 
> regressions, which has led to situation it is very hard to make changes 
> drivers that are used for multiple devices and you don't have all those 
> devices to test. It is also OK to remove my old driver and use that, but 
> then I likely lose my possibility to make changes, as I am much 
> dependent on new driver maintainer. That is one existing problem which 
> is seen multiple times during recent years... So I am perfectly happy 
> with two drivers too.

I really prefer to have just one driver for each hardware component. That
makes life easier at long term. Of course, the driver needs to be properly
maintained.

Regards,
Mauro

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

* Re: [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
  2013-11-03 12:17     ` Maik Broemme
@ 2013-11-04 12:13       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-04 12:13 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 03 Nov 2013 13:17:02 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Hi Mauro,
> 
> Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
> > Em Sun, 3 Nov 2013 01:25:23 +0100
> > Maik Broemme <mbroemme@parallels.com> escreveu:
> > 
> > > Added (DD) to NXP TDA18271C2 silicon tuner as this tuner was
> > > specifically added for Digital Devices ddbridge driver.
> > > 
> > > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> > > ---
> > >  drivers/media/dvb-frontends/Kconfig | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
> > > index bddbab4..6f99eb8 100644
> > > --- a/drivers/media/dvb-frontends/Kconfig
> > > +++ b/drivers/media/dvb-frontends/Kconfig
> > > @@ -48,11 +48,11 @@ config DVB_DRXK
> > >  	  Say Y when you want to support this frontend.
> > >  
> > >  config DVB_TDA18271C2DD
> > > -	tristate "NXP TDA18271C2 silicon tuner"
> > > +	tristate "NXP TDA18271C2 silicon tuner (DD)"
> > >  	depends on DVB_CORE && I2C
> > >  	default m if !MEDIA_SUBDRV_AUTOSELECT
> > >  	help
> > > -	  NXP TDA18271 silicon tuner.
> > > +	  NXP TDA18271 silicon tuner (Digital Devices driver).
> > >  
> > >  	  Say Y when you want to support this tuner.
> > >  
> > 
> > The better is to use the other tda18271 driver. This one was added as a
> > temporary alternative, as the more complete one were lacking some
> > features, and were not working with DRX-K. Well, those got fixed already,
> > and we now want to get rid of this duplicated driver.
> > 
> 
> Agree. Probably the tda18271 will need some extensions to work with
> ddbridge and I will see what I can do the next days to get it working.

Maybe not, but feel free to propose changes there if needed.

> 
> > Regards,
> > Mauro
> > -- 
> > 
> > Cheers,
> > Mauro
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --Maik


-- 

Cheers,
Mauro

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

* Re: [PATCH 00/12] DDBridge 0.9.10 driver updates
  2013-11-03 12:46   ` Maik Broemme
  2013-11-03 13:11     ` Ralph Metzler
@ 2013-11-04 12:19     ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 39+ messages in thread
From: Mauro Carvalho Chehab @ 2013-11-04 12:19 UTC (permalink / raw)
  To: Maik Broemme; +Cc: Linux Media Mailing List

Em Sun, 03 Nov 2013 13:46:01 +0100
Maik Broemme <mbroemme@parallels.com> escreveu:

> Hi Mauro,
> 
> Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
> > Em Sun, 3 Nov 2013 01:22:35 +0100
> > Maik Broemme <mbroemme@parallels.com> escreveu:
> > 
> > > I've updated the current DDBridge to latest version 0.9.10 from Ralph
> > > Metzler available at:
> > > 
> > > http://www.metzlerbros.de/dddvb/dddvb-0.9.10.tar.bz2
> > > 
> > > I've merged the driver to work with current v4l/dvb tree and I will
> > > maintain the driver for v4l/dvb in future. 
> > 
> > Works for me.
> > 
> > > The coming patch series is
> > > the first version and I explicitly want to get feedback and hints if
> > > some parts are merged at wrong places, etc... The following changes
> > > were made:
> > > 
> > >   - MSI enabled by default (some issues left with i2c timeouts)
> > >   - no support for Digital Devices Octonet
> > >   - no support for DVB Netstream
> > >   - removed unused module parameters 'tt' and 'vlan' (used by Octonet)
> > >   - removed unused registers to cleanup code (might be added later again
> > >     if needed)
> > 
> > Be sure to not remove any feature that are currently needed for the
> > already supported devices to work.
> 
> Of course I won't do. The Octonet and DVB Netstream weren't supported in
> current driver. MSI is already supported but was not enabled by default
> because the old 0.5 version currently in kernel had some problems with
> it. However new one works fine with MSI - at least for me I'm using the
> patchset myself already - but needs some further testing.

Ok. From the above, it sounded that some features got disabled. Please
make it clearer on the next patchset (and move/copy this kind of
description to the ddbridge patches).

With regards to MSI, we may use a quirk to disable (or enable) support
for it, on devices where this is know to have troubles.

> 
> > > 
> > > The following devices are supported by the driver update:
> > > 
> > >   - Octopus DVB adapter
> > >   - Octopus V3 DVB adapter
> > >   - Octopus LE DVB adapter
> > >   - Octopus OEM
> > >   - Octopus Mini
> > >   - Cine S2 V6 DVB adapter
> > >   - Cine S2 V6.5 DVB adapter
> > >   - Octopus CI
> > >   - Octopus CI single
> > >   - DVBCT V6.1 DVB adapter
> > >   - DVB-C modulator
> > >   - SaTiX-S2 V3 DVB adapter
> > > 
> > > I might merge the Octonet and DVB Netstream drivers from Ralphs source
> > > later once the current committed DDBridge driver updates are merged in
> > > mainline.
> > > 
> > > Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> > > 
> > > Maik Broemme (12):
> > >   dvb-frontends: Support for DVB-C2 to DVB frontends
> > >   tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner
> > >   stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator
> > >   tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
> > >   cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2
> > >   dvb-core: export dvb_usercopy and new DVB device constants
> > >   ddbridge: Updated ddbridge registers
> > >   ddbridge: Moved i2c interfaces into separate file
> > >   ddbridge: Support for the Digital Devices Resi DVB-C Modulator card
> > >   ddbridge: Update ddbridge driver to version 0.9.10
> > >   ddbridge: Update ddbridge header for 0.9.10 changes
> > >   ddbridge: Kconfig and Makefile fixes to build latest ddbridge
> > > 
> > >  drivers/media/dvb-core/dvbdev.c              |    1 
> > >  drivers/media/dvb-core/dvbdev.h              |    2 
> > >  drivers/media/dvb-frontends/Kconfig          |   31 
> > >  drivers/media/dvb-frontends/Makefile         |    3 
> > >  drivers/media/dvb-frontends/cxd2843.c        | 1647 ++++++++++++
> > >  drivers/media/dvb-frontends/cxd2843.h        |   47 
> > >  drivers/media/dvb-frontends/stv0367dd.c      | 2329 ++++++++++++++++++
> > >  drivers/media/dvb-frontends/stv0367dd.h      |   48 
> > >  drivers/media/dvb-frontends/stv0367dd_regs.h | 3442 +++++++++++++++++++++++++++
> > >  drivers/media/dvb-frontends/tda18212dd.c     |  934 +++++++
> > >  drivers/media/dvb-frontends/tda18212dd.h     |   37 
> > >  drivers/media/pci/ddbridge/Kconfig           |   21 
> > >  drivers/media/pci/ddbridge/Makefile          |    2 
> > >  drivers/media/pci/ddbridge/ddbridge-core.c   | 3085 +++++++++++++++++-------
> > >  drivers/media/pci/ddbridge/ddbridge-i2c.c    |  239 +
> > >  drivers/media/pci/ddbridge/ddbridge-mod.c    | 1033 ++++++++
> > >  drivers/media/pci/ddbridge/ddbridge-regs.h   |  273 +-
> > >  drivers/media/pci/ddbridge/ddbridge.h        |  408 ++-
> > >  include/uapi/linux/dvb/frontend.h            |    1 
> > >  19 files changed, 12555 insertions(+), 1028 deletions(-)
> > > 
> > > --Maik
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > Thanks for your submission.
> > 
> > I'm seeing this entire patch series as an RFC. There are simply too much
> > changes required for us to be able to do a more detailed review on it.
> > 
> 
> Many thanks for the feedback.
> 
> > Please do the pointed changes, in special:
> > 
> > 	- Don't let any patch to break compilation;
> > 
> > 	- Please verify the Documentation/CodingStyle and check it with
> > 		./scripts/checkpatch.pl;
> > 
> > 	- Please discuss on a separate thread the API changes for CI,
> > 	  modulator and DVB-C2;
> > 
> > 	- Please try to break the ddbridge changes into one change per
> > 	  patch. If not possible, please try to at least break them more,
> > 	  to help us to review the changes;
> > 
> > 	- Please don't duplicate existing drivers without a very very good
> > 	  reason.
> > 
> 
> I will address the concerns with re-submission of the patches. Most
> probably it is worth to split the patchset a bit. The CXD2843
> demodulator can also be used by other drivers so I will address your
> feedback on this driver first and re-submit. Once it is fine I will
> re-send changes for ddbridge. Hope it is a good approach. :)

Works for me.
> 
> > Thanks!
> > Mauro
> 
> --Maik


-- 

Cheers,
Mauro

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

* Re: [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-04 12:12       ` Mauro Carvalho Chehab
@ 2013-11-04 12:49         ` Maik Broemme
  2013-11-04 13:04           ` Antti Palosaari
  0 siblings, 1 reply; 39+ messages in thread
From: Maik Broemme @ 2013-11-04 12:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: Antti Palosaari, Linux Media Mailing List

Hi Mauro,

Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
> Em Sun, 03 Nov 2013 19:00:22 +0200
> Antti Palosaari <crope@iki.fi> escreveu:
> 
> > On 03.11.2013 11:56, Mauro Carvalho Chehab wrote:
> > > Hi Maik,
> > >
> > > Em Sun, 3 Nov 2013 01:31:04 +0100
> > > Maik Broemme <mbroemme@parallels.com> escreveu:
> > >
> > >> Added support for the NXP TDA18212 silicon tuner used by recent
> > >> Digital Devices hardware. This will allow update of ddbridge driver
> > >> to support newer devices.
> > >>
> > >> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
> > >> ---
> > >>   drivers/media/dvb-frontends/Kconfig      |   9 +
> > >>   drivers/media/dvb-frontends/Makefile     |   1 +
> > >>   drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
> > >>   drivers/media/dvb-frontends/tda18212dd.h |  37 ++
> > >
> > > I'm not sure if support for this tuner is not provided already by one of
> > > the existing drivers. If not, it is ok to submit a driver for it, but you
> > > should just call it as tda18212.
> > >
> > > I'm c/c Antti, as he worked on some NXP drivers recently, and may be aware
> > > if a driver already supports TDA18212.
> > 
> > Existing tda18212 driver I made is reverse-engineered and it is used 
> > only for Anysee devices, which I am also responsible. That new tuner 
> > driver is much more complete than what I have made and single driver is 
> > naturally the correct approach.
> > 
> > But one thing which annoys nowadays is that endless talking of 
> > regressions, which has led to situation it is very hard to make changes 
> > drivers that are used for multiple devices and you don't have all those 
> > devices to test. It is also OK to remove my old driver and use that, but 
> > then I likely lose my possibility to make changes, as I am much 
> > dependent on new driver maintainer. That is one existing problem which 
> > is seen multiple times during recent years... So I am perfectly happy 
> > with two drivers too.
> 
> I really prefer to have just one driver for each hardware component. That
> makes life easier at long term. Of course, the driver needs to be properly
> maintained.
> 

I agree. Antti do you know which Anysee device you've used for reverse
engineering?

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

--Maik

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

* Re: [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner
  2013-11-04 12:49         ` Maik Broemme
@ 2013-11-04 13:04           ` Antti Palosaari
  0 siblings, 0 replies; 39+ messages in thread
From: Antti Palosaari @ 2013-11-04 13:04 UTC (permalink / raw)
  To: Maik Broemme, Mauro Carvalho Chehab; +Cc: Linux Media Mailing List

On 04.11.2013 14:49, Maik Broemme wrote:
> Hi Mauro,
>
> Mauro Carvalho Chehab <m.chehab@samsung.com> wrote:
>> Em Sun, 03 Nov 2013 19:00:22 +0200
>> Antti Palosaari <crope@iki.fi> escreveu:
>>
>>> On 03.11.2013 11:56, Mauro Carvalho Chehab wrote:
>>>> Hi Maik,
>>>>
>>>> Em Sun, 3 Nov 2013 01:31:04 +0100
>>>> Maik Broemme <mbroemme@parallels.com> escreveu:
>>>>
>>>>> Added support for the NXP TDA18212 silicon tuner used by recent
>>>>> Digital Devices hardware. This will allow update of ddbridge driver
>>>>> to support newer devices.
>>>>>
>>>>> Signed-off-by: Maik Broemme <mbroemme@parallels.com>
>>>>> ---
>>>>>    drivers/media/dvb-frontends/Kconfig      |   9 +
>>>>>    drivers/media/dvb-frontends/Makefile     |   1 +
>>>>>    drivers/media/dvb-frontends/tda18212dd.c | 934 +++++++++++++++++++++++++++++++
>>>>>    drivers/media/dvb-frontends/tda18212dd.h |  37 ++
>>>>
>>>> I'm not sure if support for this tuner is not provided already by one of
>>>> the existing drivers. If not, it is ok to submit a driver for it, but you
>>>> should just call it as tda18212.
>>>>
>>>> I'm c/c Antti, as he worked on some NXP drivers recently, and may be aware
>>>> if a driver already supports TDA18212.
>>>
>>> Existing tda18212 driver I made is reverse-engineered and it is used
>>> only for Anysee devices, which I am also responsible. That new tuner
>>> driver is much more complete than what I have made and single driver is
>>> naturally the correct approach.
>>>
>>> But one thing which annoys nowadays is that endless talking of
>>> regressions, which has led to situation it is very hard to make changes
>>> drivers that are used for multiple devices and you don't have all those
>>> devices to test. It is also OK to remove my old driver and use that, but
>>> then I likely lose my possibility to make changes, as I am much
>>> dependent on new driver maintainer. That is one existing problem which
>>> is seen multiple times during recent years... So I am perfectly happy
>>> with two drivers too.
>>
>> I really prefer to have just one driver for each hardware component. That
>> makes life easier at long term. Of course, the driver needs to be properly
>> maintained.
>>
>
> I agree. Antti do you know which Anysee device you've used for reverse
> engineering?

All those Anysee models are documented very well in driver file:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/media/usb/dvb-usb-v2/anysee.c?id=refs/tags/v3.12

There seems to be 3 different Anysee models:
"anysee-E7TC(LP)" PCB: 508TC (rev0.6)
"anysee-E7T2C(LP)" PCB: 508T2C (rev0.3)
"anysee-E7PTC(LP)" PCB: 508PTC (rev0.5)

E7TC and E7PTC has TDA18212 inside tuner module DNOD44CDH086A. E7T2C has 
TDA18212 inside of DNOQ44QCH106A NIM.

E7TC and E7PTC are basically same device, just different form. Other is 
external USB and another internal USB. E7T2C is different device. So if 
you are going to buy these, then I recommended to order E7T2C and E7TC.

regards
Antti

-- 
http://palosaari.fi/

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

end of thread, other threads:[~2013-11-04 13:04 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-03  0:22 [PATCH 00/12] DDBridge 0.9.10 driver updates Maik Broemme
2013-11-03  0:24 ` [PATCH 01/12] dvb-frontends: Support for DVB-C2 to DVB frontends Maik Broemme
2013-11-03  9:23   ` Mauro Carvalho Chehab
2013-11-03 10:47     ` Ralph Metzler
2013-11-03 11:22       ` Mauro Carvalho Chehab
2013-11-03 12:20       ` Maik Broemme
2013-11-03  0:25 ` [PATCH 02/12] tda18271c2dd: Fix description of NXP TDA18271C2 silicon tuner Maik Broemme
2013-11-03  9:27   ` Mauro Carvalho Chehab
2013-11-03 12:17     ` Maik Broemme
2013-11-04 12:13       ` Mauro Carvalho Chehab
2013-11-03  0:28 ` [PATCH 03/12] stv0367dd: Support for STV 0367 DVB-C/T (DD) demodulator Maik Broemme
2013-11-03  9:29   ` Mauro Carvalho Chehab
2013-11-03  0:31 ` [PATCH 04/12] tda18212dd: Support for NXP TDA18212 (DD) silicon tuner Maik Broemme
2013-11-03  9:56   ` Mauro Carvalho Chehab
2013-11-03 17:00     ` Antti Palosaari
2013-11-04 12:12       ` Mauro Carvalho Chehab
2013-11-04 12:49         ` Maik Broemme
2013-11-04 13:04           ` Antti Palosaari
2013-11-03  0:32 ` [PATCH 05/12] cxd2843: Support for CXD2843ER demodulator for DVB-T/T2/C/C2 Maik Broemme
2013-11-03 10:11   ` Mauro Carvalho Chehab
2013-11-03  0:33 ` [PATCH 06/12] dvb-core: export dvb_usercopy and new DVB device constants Maik Broemme
2013-11-03 10:16   ` Mauro Carvalho Chehab
2013-11-03  0:35 ` [PATCH 07/12] ddbridge: Updated ddbridge registers Maik Broemme
2013-11-03 10:17   ` Mauro Carvalho Chehab
2013-11-03  0:40 ` [PATCH 08/12] ddbridge: Moved i2c interfaces into separate file Maik Broemme
2013-11-03 10:23   ` Mauro Carvalho Chehab
2013-11-03  0:41 ` [PATCH 09/12] ddbridge: Support for the Digital Devices Resi DVB-C Modulator card Maik Broemme
2013-11-03 10:44   ` Mauro Carvalho Chehab
2013-11-03  0:44 ` [PATCH 10/12] ddbridge: Update ddbridge driver to version 0.9.10 Maik Broemme
2013-11-03 10:49   ` Mauro Carvalho Chehab
2013-11-03  0:45 ` [PATCH 11/12] ddbridge: Update ddbridge header for 0.9.10 changes Maik Broemme
2013-11-03 10:50   ` Mauro Carvalho Chehab
2013-11-03  0:46 ` [PATCH 12/12] ddbridge: Kconfig and Makefile fixes to build latest ddbridge Maik Broemme
2013-11-03 10:51   ` Mauro Carvalho Chehab
2013-11-03 10:58 ` [PATCH 00/12] DDBridge 0.9.10 driver updates Mauro Carvalho Chehab
2013-11-03 12:46   ` Maik Broemme
2013-11-03 13:11     ` Ralph Metzler
2013-11-03 13:19       ` Maik Broemme
2013-11-04 12:19     ` Mauro Carvalho Chehab

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).