* [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, ®, 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 = ®, .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 = ®, .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 = ®, .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(®, parg, sizeof(reg)))
+ return -EFAULT;
+ if (reg.reg >= dev->regs_len)
+ return -EINVAL;
+ reg.val = ddbreadl(dev, reg.reg);
+ if (copy_to_user(parg, ®, sizeof(reg)))
+ return -EFAULT;
+ break;
+ }
+ case IOCTL_DDB_WRITE_REG:
+ {
+ struct ddb_reg reg;
+
+ if (copy_from_user(®, 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, ®, 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 = ®, .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 = ®, .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 = ®, .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(®, parg, sizeof(reg)))
> + return -EFAULT;
> + if (reg.reg >= dev->regs_len)
> + return -EINVAL;
> + reg.val = ddbreadl(dev, reg.reg);
> + if (copy_to_user(parg, ®, sizeof(reg)))
> + return -EFAULT;
> + break;
> + }
> + case IOCTL_DDB_WRITE_REG:
> + {
> + struct ddb_reg reg;
> +
> + if (copy_from_user(®, 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).