mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2023-10-10 13:37:43 +02:00
2119 lines
60 KiB
C
2119 lines
60 KiB
C
/*
|
|
* stv0367dd: STV0367 DVB-C/T demodulator driver
|
|
*
|
|
* Copyright (C) 2011 Digital Devices GmbH
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 only, as published by the Free Software Foundation.
|
|
*
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA
|
|
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/init.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/version.h>
|
|
#include <asm/div64.h>
|
|
|
|
#include "dvb_math.h"
|
|
#include "dvb_frontend.h"
|
|
#include "stv0367dd.h"
|
|
#include "stv0367dd_regs.h"
|
|
|
|
#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24))
|
|
|
|
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 {
|
|
struct dvb_frontend frontend;
|
|
fe_modulation_t modulation;
|
|
u32 symbol_rate;
|
|
u32 bandwidth;
|
|
struct device *dev;
|
|
|
|
struct i2c_adapter *i2c;
|
|
u8 adr;
|
|
u8 cont_clock;
|
|
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 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 = INTLOG10X100((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);
|
|
|
|
if (state->cont_clock)
|
|
writereg(state, R367_OFDM_TSCFGH, 0xf0);
|
|
else
|
|
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;
|
|
}
|
|
|
|
static void release(struct dvb_frontend* fe)
|
|
{
|
|
struct stv_state *state=fe->demodulator_priv;
|
|
printk("%s\n", __FUNCTION__);
|
|
kfree(state);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
#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
|
|
|
|
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,
|
|
};
|
|
|
|
|
|
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;
|
|
state->cont_clock = cfg->cont_clock;
|
|
|
|
mutex_init(&state->mutex);
|
|
mutex_init(&state->ctlock);
|
|
|
|
memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops));
|
|
state->frontend.demodulator_priv = state;
|
|
|
|
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;
|
|
return &state->frontend;
|
|
|
|
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);
|
|
|
|
|
|
|