162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2003-2007 Micronas 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/moduleparam.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/firmware.h> 1462306a36Sopenharmony_ci#include <linux/i2c.h> 1562306a36Sopenharmony_ci#include <asm/div64.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <media/dvb_frontend.h> 1862306a36Sopenharmony_ci#include "drxd.h" 1962306a36Sopenharmony_ci#include "drxd_firm.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw" 2262306a36Sopenharmony_ci#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define CHUNK_SIZE 48 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define DRX_I2C_RMW 0x10 2762306a36Sopenharmony_ci#define DRX_I2C_BROADCAST 0x20 2862306a36Sopenharmony_ci#define DRX_I2C_CLEARCRC 0x80 2962306a36Sopenharmony_ci#define DRX_I2C_SINGLE_MASTER 0xC0 3062306a36Sopenharmony_ci#define DRX_I2C_MODEFLAGS 0xC0 3162306a36Sopenharmony_ci#define DRX_I2C_FLAGS 0xF0 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define DEFAULT_LOCK_TIMEOUT 1100 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define DRX_CHANNEL_AUTO 0 3662306a36Sopenharmony_ci#define DRX_CHANNEL_HIGH 1 3762306a36Sopenharmony_ci#define DRX_CHANNEL_LOW 2 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define DRX_LOCK_MPEG 1 4062306a36Sopenharmony_ci#define DRX_LOCK_FEC 2 4162306a36Sopenharmony_ci#define DRX_LOCK_DEMOD 4 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/****************************************************************************/ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cienum CSCDState { 4662306a36Sopenharmony_ci CSCD_INIT = 0, 4762306a36Sopenharmony_ci CSCD_SET, 4862306a36Sopenharmony_ci CSCD_SAVED 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cienum CDrxdState { 5262306a36Sopenharmony_ci DRXD_UNINITIALIZED = 0, 5362306a36Sopenharmony_ci DRXD_STOPPED, 5462306a36Sopenharmony_ci DRXD_STARTED 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cienum AGC_CTRL_MODE { 5862306a36Sopenharmony_ci AGC_CTRL_AUTO = 0, 5962306a36Sopenharmony_ci AGC_CTRL_USER, 6062306a36Sopenharmony_ci AGC_CTRL_OFF 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cienum OperationMode { 6462306a36Sopenharmony_ci OM_Default, 6562306a36Sopenharmony_ci OM_DVBT_Diversity_Front, 6662306a36Sopenharmony_ci OM_DVBT_Diversity_End 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct SCfgAgc { 7062306a36Sopenharmony_ci enum AGC_CTRL_MODE ctrlMode; 7162306a36Sopenharmony_ci u16 outputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 7262306a36Sopenharmony_ci u16 settleLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 7362306a36Sopenharmony_ci u16 minOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 7462306a36Sopenharmony_ci u16 maxOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 7562306a36Sopenharmony_ci u16 speed; /* range [0, ... , 1023], 1/n of fullscale range */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci u16 R1; 7862306a36Sopenharmony_ci u16 R2; 7962306a36Sopenharmony_ci u16 R3; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct SNoiseCal { 8362306a36Sopenharmony_ci int cpOpt; 8462306a36Sopenharmony_ci short cpNexpOfs; 8562306a36Sopenharmony_ci short tdCal2k; 8662306a36Sopenharmony_ci short tdCal8k; 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cienum app_env { 9062306a36Sopenharmony_ci APPENV_STATIC = 0, 9162306a36Sopenharmony_ci APPENV_PORTABLE = 1, 9262306a36Sopenharmony_ci APPENV_MOBILE = 2 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cienum EIFFilter { 9662306a36Sopenharmony_ci IFFILTER_SAW = 0, 9762306a36Sopenharmony_ci IFFILTER_DISCRETE = 1 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistruct drxd_state { 10162306a36Sopenharmony_ci struct dvb_frontend frontend; 10262306a36Sopenharmony_ci struct dvb_frontend_ops ops; 10362306a36Sopenharmony_ci struct dtv_frontend_properties props; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci const struct firmware *fw; 10662306a36Sopenharmony_ci struct device *dev; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci struct i2c_adapter *i2c; 10962306a36Sopenharmony_ci void *priv; 11062306a36Sopenharmony_ci struct drxd_config config; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci int i2c_access; 11362306a36Sopenharmony_ci int init_done; 11462306a36Sopenharmony_ci struct mutex mutex; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci u8 chip_adr; 11762306a36Sopenharmony_ci u16 hi_cfg_timing_div; 11862306a36Sopenharmony_ci u16 hi_cfg_bridge_delay; 11962306a36Sopenharmony_ci u16 hi_cfg_wakeup_key; 12062306a36Sopenharmony_ci u16 hi_cfg_ctrl; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci u16 intermediate_freq; 12362306a36Sopenharmony_ci u16 osc_clock_freq; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci enum CSCDState cscd_state; 12662306a36Sopenharmony_ci enum CDrxdState drxd_state; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci u16 sys_clock_freq; 12962306a36Sopenharmony_ci s16 osc_clock_deviation; 13062306a36Sopenharmony_ci u16 expected_sys_clock_freq; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci u16 insert_rs_byte; 13362306a36Sopenharmony_ci u16 enable_parallel; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci int operation_mode; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci struct SCfgAgc if_agc_cfg; 13862306a36Sopenharmony_ci struct SCfgAgc rf_agc_cfg; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci struct SNoiseCal noise_cal; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci u32 fe_fs_add_incr; 14362306a36Sopenharmony_ci u32 org_fe_fs_add_incr; 14462306a36Sopenharmony_ci u16 current_fe_if_incr; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci u16 m_FeAgRegAgPwd; 14762306a36Sopenharmony_ci u16 m_FeAgRegAgAgcSio; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci u16 m_EcOcRegOcModeLop; 15062306a36Sopenharmony_ci u16 m_EcOcRegSncSncLvl; 15162306a36Sopenharmony_ci u8 *m_InitAtomicRead; 15262306a36Sopenharmony_ci u8 *m_HiI2cPatch; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci u8 *m_ResetCEFR; 15562306a36Sopenharmony_ci u8 *m_InitFE_1; 15662306a36Sopenharmony_ci u8 *m_InitFE_2; 15762306a36Sopenharmony_ci u8 *m_InitCP; 15862306a36Sopenharmony_ci u8 *m_InitCE; 15962306a36Sopenharmony_ci u8 *m_InitEQ; 16062306a36Sopenharmony_ci u8 *m_InitSC; 16162306a36Sopenharmony_ci u8 *m_InitEC; 16262306a36Sopenharmony_ci u8 *m_ResetECRAM; 16362306a36Sopenharmony_ci u8 *m_InitDiversityFront; 16462306a36Sopenharmony_ci u8 *m_InitDiversityEnd; 16562306a36Sopenharmony_ci u8 *m_DisableDiversity; 16662306a36Sopenharmony_ci u8 *m_StartDiversityFront; 16762306a36Sopenharmony_ci u8 *m_StartDiversityEnd; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci u8 *m_DiversityDelay8MHZ; 17062306a36Sopenharmony_ci u8 *m_DiversityDelay6MHZ; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci u8 *microcode; 17362306a36Sopenharmony_ci u32 microcode_length; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci int type_A; 17662306a36Sopenharmony_ci int PGA; 17762306a36Sopenharmony_ci int diversity; 17862306a36Sopenharmony_ci int tuner_mirrors; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci enum app_env app_env_default; 18162306a36Sopenharmony_ci enum app_env app_env_diversity; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/****************************************************************************/ 18662306a36Sopenharmony_ci/* I2C **********************************************************************/ 18762306a36Sopenharmony_ci/****************************************************************************/ 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len }; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (i2c_transfer(adap, &msg, 1) != 1) 19462306a36Sopenharmony_ci return -1; 19562306a36Sopenharmony_ci return 0; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic int i2c_read(struct i2c_adapter *adap, 19962306a36Sopenharmony_ci u8 adr, u8 *msg, int len, u8 *answ, int alen) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct i2c_msg msgs[2] = { 20262306a36Sopenharmony_ci { 20362306a36Sopenharmony_ci .addr = adr, .flags = 0, 20462306a36Sopenharmony_ci .buf = msg, .len = len 20562306a36Sopenharmony_ci }, { 20662306a36Sopenharmony_ci .addr = adr, .flags = I2C_M_RD, 20762306a36Sopenharmony_ci .buf = answ, .len = alen 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci }; 21062306a36Sopenharmony_ci if (i2c_transfer(adap, msgs, 2) != 2) 21162306a36Sopenharmony_ci return -1; 21262306a36Sopenharmony_ci return 0; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic inline u32 MulDiv32(u32 a, u32 b, u32 c) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci u64 tmp64; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci tmp64 = (u64)a * (u64)b; 22062306a36Sopenharmony_ci do_div(tmp64, c); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci return (u32) tmp64; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci u8 adr = state->config.demod_address; 22862306a36Sopenharmony_ci u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, 22962306a36Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 23062306a36Sopenharmony_ci }; 23162306a36Sopenharmony_ci u8 mm2[2]; 23262306a36Sopenharmony_ci if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0) 23362306a36Sopenharmony_ci return -1; 23462306a36Sopenharmony_ci if (data) 23562306a36Sopenharmony_ci *data = mm2[0] | (mm2[1] << 8); 23662306a36Sopenharmony_ci return mm2[0] | (mm2[1] << 8); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci u8 adr = state->config.demod_address; 24262306a36Sopenharmony_ci u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, 24362306a36Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 24462306a36Sopenharmony_ci }; 24562306a36Sopenharmony_ci u8 mm2[4]; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0) 24862306a36Sopenharmony_ci return -1; 24962306a36Sopenharmony_ci if (data) 25062306a36Sopenharmony_ci *data = 25162306a36Sopenharmony_ci mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24); 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci u8 adr = state->config.demod_address; 25862306a36Sopenharmony_ci u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff, 25962306a36Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, 26062306a36Sopenharmony_ci data & 0xff, (data >> 8) & 0xff 26162306a36Sopenharmony_ci }; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 6) < 0) 26462306a36Sopenharmony_ci return -1; 26562306a36Sopenharmony_ci return 0; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci u8 adr = state->config.demod_address; 27162306a36Sopenharmony_ci u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff, 27262306a36Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, 27362306a36Sopenharmony_ci data & 0xff, (data >> 8) & 0xff, 27462306a36Sopenharmony_ci (data >> 16) & 0xff, (data >> 24) & 0xff 27562306a36Sopenharmony_ci }; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 8) < 0) 27862306a36Sopenharmony_ci return -1; 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int write_chunk(struct drxd_state *state, 28362306a36Sopenharmony_ci u32 reg, u8 *data, u32 len, u8 flags) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci u8 adr = state->config.demod_address; 28662306a36Sopenharmony_ci u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff, 28762306a36Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 28862306a36Sopenharmony_ci }; 28962306a36Sopenharmony_ci int i; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci for (i = 0; i < len; i++) 29262306a36Sopenharmony_ci mm[4 + i] = data[i]; 29362306a36Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) { 29462306a36Sopenharmony_ci printk(KERN_ERR "error in write_chunk\n"); 29562306a36Sopenharmony_ci return -1; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci return 0; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int WriteBlock(struct drxd_state *state, 30162306a36Sopenharmony_ci u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci while (BlockSize > 0) { 30462306a36Sopenharmony_ci u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0) 30762306a36Sopenharmony_ci return -1; 30862306a36Sopenharmony_ci pBlock += Chunk; 30962306a36Sopenharmony_ci Address += (Chunk >> 1); 31062306a36Sopenharmony_ci BlockSize -= Chunk; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci return 0; 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic int WriteTable(struct drxd_state *state, u8 * pTable) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci int status = 0; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (!pTable) 32062306a36Sopenharmony_ci return 0; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci while (!status) { 32362306a36Sopenharmony_ci u16 Length; 32462306a36Sopenharmony_ci u32 Address = pTable[0] | (pTable[1] << 8) | 32562306a36Sopenharmony_ci (pTable[2] << 16) | (pTable[3] << 24); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (Address == 0xFFFFFFFF) 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci pTable += sizeof(u32); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci Length = pTable[0] | (pTable[1] << 8); 33262306a36Sopenharmony_ci pTable += sizeof(u16); 33362306a36Sopenharmony_ci if (!Length) 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci status = WriteBlock(state, Address, Length * 2, pTable, 0); 33662306a36Sopenharmony_ci pTable += (Length * 2); 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci return status; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci/****************************************************************************/ 34262306a36Sopenharmony_ci/****************************************************************************/ 34362306a36Sopenharmony_ci/****************************************************************************/ 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int ResetCEFR(struct drxd_state *state) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci return WriteTable(state, state->m_ResetCEFR); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic int InitCP(struct drxd_state *state) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci return WriteTable(state, state->m_InitCP); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int InitCE(struct drxd_state *state) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci int status; 35862306a36Sopenharmony_ci enum app_env AppEnv = state->app_env_default; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci do { 36162306a36Sopenharmony_ci status = WriteTable(state, state->m_InitCE); 36262306a36Sopenharmony_ci if (status < 0) 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front || 36662306a36Sopenharmony_ci state->operation_mode == OM_DVBT_Diversity_End) { 36762306a36Sopenharmony_ci AppEnv = state->app_env_diversity; 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci if (AppEnv == APPENV_STATIC) { 37062306a36Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0); 37162306a36Sopenharmony_ci if (status < 0) 37262306a36Sopenharmony_ci break; 37362306a36Sopenharmony_ci } else if (AppEnv == APPENV_PORTABLE) { 37462306a36Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0); 37562306a36Sopenharmony_ci if (status < 0) 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci } else if (AppEnv == APPENV_MOBILE && state->type_A) { 37862306a36Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0); 37962306a36Sopenharmony_ci if (status < 0) 38062306a36Sopenharmony_ci break; 38162306a36Sopenharmony_ci } else if (AppEnv == APPENV_MOBILE && !state->type_A) { 38262306a36Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0); 38362306a36Sopenharmony_ci if (status < 0) 38462306a36Sopenharmony_ci break; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* start ce */ 38862306a36Sopenharmony_ci status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0); 38962306a36Sopenharmony_ci if (status < 0) 39062306a36Sopenharmony_ci break; 39162306a36Sopenharmony_ci } while (0); 39262306a36Sopenharmony_ci return status; 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic int StopOC(struct drxd_state *state) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci int status = 0; 39862306a36Sopenharmony_ci u16 ocSyncLvl = 0; 39962306a36Sopenharmony_ci u16 ocModeLop = state->m_EcOcRegOcModeLop; 40062306a36Sopenharmony_ci u16 dtoIncLop = 0; 40162306a36Sopenharmony_ci u16 dtoIncHip = 0; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci do { 40462306a36Sopenharmony_ci /* Store output configuration */ 40562306a36Sopenharmony_ci status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0); 40662306a36Sopenharmony_ci if (status < 0) 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci /* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */ 40962306a36Sopenharmony_ci state->m_EcOcRegSncSncLvl = ocSyncLvl; 41062306a36Sopenharmony_ci /* m_EcOcRegOcModeLop = ocModeLop; */ 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* Flush FIFO (byte-boundary) at fixed rate */ 41362306a36Sopenharmony_ci status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0); 41462306a36Sopenharmony_ci if (status < 0) 41562306a36Sopenharmony_ci break; 41662306a36Sopenharmony_ci status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0); 41762306a36Sopenharmony_ci if (status < 0) 41862306a36Sopenharmony_ci break; 41962306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0); 42062306a36Sopenharmony_ci if (status < 0) 42162306a36Sopenharmony_ci break; 42262306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0); 42362306a36Sopenharmony_ci if (status < 0) 42462306a36Sopenharmony_ci break; 42562306a36Sopenharmony_ci ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M); 42662306a36Sopenharmony_ci ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC; 42762306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); 42862306a36Sopenharmony_ci if (status < 0) 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); 43162306a36Sopenharmony_ci if (status < 0) 43262306a36Sopenharmony_ci break; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci msleep(1); 43562306a36Sopenharmony_ci /* Output pins to '0' */ 43662306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0); 43762306a36Sopenharmony_ci if (status < 0) 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* Force the OC out of sync */ 44162306a36Sopenharmony_ci ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M); 44262306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0); 44362306a36Sopenharmony_ci if (status < 0) 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M); 44662306a36Sopenharmony_ci ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE; 44762306a36Sopenharmony_ci ocModeLop |= 0x2; /* Magically-out-of-sync */ 44862306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); 44962306a36Sopenharmony_ci if (status < 0) 45062306a36Sopenharmony_ci break; 45162306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0); 45262306a36Sopenharmony_ci if (status < 0) 45362306a36Sopenharmony_ci break; 45462306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); 45562306a36Sopenharmony_ci if (status < 0) 45662306a36Sopenharmony_ci break; 45762306a36Sopenharmony_ci } while (0); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci return status; 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic int StartOC(struct drxd_state *state) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci int status = 0; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci do { 46762306a36Sopenharmony_ci /* Stop OC */ 46862306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); 46962306a36Sopenharmony_ci if (status < 0) 47062306a36Sopenharmony_ci break; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci /* Restore output configuration */ 47362306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0); 47462306a36Sopenharmony_ci if (status < 0) 47562306a36Sopenharmony_ci break; 47662306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0); 47762306a36Sopenharmony_ci if (status < 0) 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* Output pins active again */ 48162306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0); 48262306a36Sopenharmony_ci if (status < 0) 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* Start OC */ 48662306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); 48762306a36Sopenharmony_ci if (status < 0) 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci } while (0); 49062306a36Sopenharmony_ci return status; 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic int InitEQ(struct drxd_state *state) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci return WriteTable(state, state->m_InitEQ); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_cistatic int InitEC(struct drxd_state *state) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci return WriteTable(state, state->m_InitEC); 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_cistatic int InitSC(struct drxd_state *state) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci return WriteTable(state, state->m_InitSC); 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic int InitAtomicRead(struct drxd_state *state) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci return WriteTable(state, state->m_InitAtomicRead); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int CorrectSysClockDeviation(struct drxd_state *state); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci u16 ScRaRamLock = 0; 51862306a36Sopenharmony_ci const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M | 51962306a36Sopenharmony_ci SC_RA_RAM_LOCK_FEC__M | 52062306a36Sopenharmony_ci SC_RA_RAM_LOCK_DEMOD__M); 52162306a36Sopenharmony_ci const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M | 52262306a36Sopenharmony_ci SC_RA_RAM_LOCK_DEMOD__M); 52362306a36Sopenharmony_ci const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci int status; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci *pLockStatus = 0; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000); 53062306a36Sopenharmony_ci if (status < 0) { 53162306a36Sopenharmony_ci printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status); 53262306a36Sopenharmony_ci return status; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci if (state->drxd_state != DRXD_STARTED) 53662306a36Sopenharmony_ci return 0; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) { 53962306a36Sopenharmony_ci *pLockStatus |= DRX_LOCK_MPEG; 54062306a36Sopenharmony_ci CorrectSysClockDeviation(state); 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) 54462306a36Sopenharmony_ci *pLockStatus |= DRX_LOCK_FEC; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) 54762306a36Sopenharmony_ci *pLockStatus |= DRX_LOCK_DEMOD; 54862306a36Sopenharmony_ci return 0; 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci/****************************************************************************/ 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci int status; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (cfg->outputLevel > DRXD_FE_CTRL_MAX) 55862306a36Sopenharmony_ci return -1; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci if (cfg->ctrlMode == AGC_CTRL_USER) { 56162306a36Sopenharmony_ci do { 56262306a36Sopenharmony_ci u16 FeAgRegPm1AgcWri; 56362306a36Sopenharmony_ci u16 FeAgRegAgModeLop; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); 56662306a36Sopenharmony_ci if (status < 0) 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); 56962306a36Sopenharmony_ci FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC; 57062306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); 57162306a36Sopenharmony_ci if (status < 0) 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci FeAgRegPm1AgcWri = (u16) (cfg->outputLevel & 57562306a36Sopenharmony_ci FE_AG_REG_PM1_AGC_WRI__M); 57662306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0); 57762306a36Sopenharmony_ci if (status < 0) 57862306a36Sopenharmony_ci break; 57962306a36Sopenharmony_ci } while (0); 58062306a36Sopenharmony_ci } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { 58162306a36Sopenharmony_ci if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) || 58262306a36Sopenharmony_ci ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) || 58362306a36Sopenharmony_ci ((cfg->speed) > DRXD_FE_CTRL_MAX) || 58462306a36Sopenharmony_ci ((cfg->settleLevel) > DRXD_FE_CTRL_MAX) 58562306a36Sopenharmony_ci ) 58662306a36Sopenharmony_ci return -1; 58762306a36Sopenharmony_ci do { 58862306a36Sopenharmony_ci u16 FeAgRegAgModeLop; 58962306a36Sopenharmony_ci u16 FeAgRegEgcSetLvl; 59062306a36Sopenharmony_ci u16 slope, offset; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* == Mode == */ 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); 59562306a36Sopenharmony_ci if (status < 0) 59662306a36Sopenharmony_ci break; 59762306a36Sopenharmony_ci FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); 59862306a36Sopenharmony_ci FeAgRegAgModeLop |= 59962306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC; 60062306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); 60162306a36Sopenharmony_ci if (status < 0) 60262306a36Sopenharmony_ci break; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* == Settle level == */ 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) & 60762306a36Sopenharmony_ci FE_AG_REG_EGC_SET_LVL__M); 60862306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0); 60962306a36Sopenharmony_ci if (status < 0) 61062306a36Sopenharmony_ci break; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* == Min/Max == */ 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci slope = (u16) ((cfg->maxOutputLevel - 61562306a36Sopenharmony_ci cfg->minOutputLevel) / 2); 61662306a36Sopenharmony_ci offset = (u16) ((cfg->maxOutputLevel + 61762306a36Sopenharmony_ci cfg->minOutputLevel) / 2 - 511); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0); 62062306a36Sopenharmony_ci if (status < 0) 62162306a36Sopenharmony_ci break; 62262306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0); 62362306a36Sopenharmony_ci if (status < 0) 62462306a36Sopenharmony_ci break; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* == Speed == */ 62762306a36Sopenharmony_ci { 62862306a36Sopenharmony_ci const u16 maxRur = 8; 62962306a36Sopenharmony_ci static const u16 slowIncrDecLUT[] = { 63062306a36Sopenharmony_ci 3, 4, 4, 5, 6 }; 63162306a36Sopenharmony_ci static const u16 fastIncrDecLUT[] = { 63262306a36Sopenharmony_ci 14, 15, 15, 16, 63362306a36Sopenharmony_ci 17, 18, 18, 19, 63462306a36Sopenharmony_ci 20, 21, 22, 23, 63562306a36Sopenharmony_ci 24, 26, 27, 28, 63662306a36Sopenharmony_ci 29, 31 63762306a36Sopenharmony_ci }; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) / 64062306a36Sopenharmony_ci (maxRur + 1); 64162306a36Sopenharmony_ci u16 fineSpeed = (u16) (cfg->speed - 64262306a36Sopenharmony_ci ((cfg->speed / 64362306a36Sopenharmony_ci fineSteps) * 64462306a36Sopenharmony_ci fineSteps)); 64562306a36Sopenharmony_ci u16 invRurCount = (u16) (cfg->speed / 64662306a36Sopenharmony_ci fineSteps); 64762306a36Sopenharmony_ci u16 rurCount; 64862306a36Sopenharmony_ci if (invRurCount > maxRur) { 64962306a36Sopenharmony_ci rurCount = 0; 65062306a36Sopenharmony_ci fineSpeed += fineSteps; 65162306a36Sopenharmony_ci } else { 65262306a36Sopenharmony_ci rurCount = maxRur - invRurCount; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /* 65662306a36Sopenharmony_ci fastInc = default * 65762306a36Sopenharmony_ci (2^(fineSpeed/fineSteps)) 65862306a36Sopenharmony_ci => range[default...2*default> 65962306a36Sopenharmony_ci slowInc = default * 66062306a36Sopenharmony_ci (2^(fineSpeed/fineSteps)) 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_ci { 66362306a36Sopenharmony_ci u16 fastIncrDec = 66462306a36Sopenharmony_ci fastIncrDecLUT[fineSpeed / 66562306a36Sopenharmony_ci ((fineSteps / 66662306a36Sopenharmony_ci (14 + 1)) + 1)]; 66762306a36Sopenharmony_ci u16 slowIncrDec = 66862306a36Sopenharmony_ci slowIncrDecLUT[fineSpeed / 66962306a36Sopenharmony_ci (fineSteps / 67062306a36Sopenharmony_ci (3 + 1))]; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0); 67362306a36Sopenharmony_ci if (status < 0) 67462306a36Sopenharmony_ci break; 67562306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0); 67662306a36Sopenharmony_ci if (status < 0) 67762306a36Sopenharmony_ci break; 67862306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0); 67962306a36Sopenharmony_ci if (status < 0) 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0); 68262306a36Sopenharmony_ci if (status < 0) 68362306a36Sopenharmony_ci break; 68462306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0); 68562306a36Sopenharmony_ci if (status < 0) 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci } while (0); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci } else { 69262306a36Sopenharmony_ci /* No OFF mode for IF control */ 69362306a36Sopenharmony_ci return -1; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci return status; 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_cistatic int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci int status = 0; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (cfg->outputLevel > DRXD_FE_CTRL_MAX) 70362306a36Sopenharmony_ci return -1; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (cfg->ctrlMode == AGC_CTRL_USER) { 70662306a36Sopenharmony_ci do { 70762306a36Sopenharmony_ci u16 AgModeLop = 0; 70862306a36Sopenharmony_ci u16 level = (cfg->outputLevel); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (level == DRXD_FE_CTRL_MAX) 71162306a36Sopenharmony_ci level++; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000); 71462306a36Sopenharmony_ci if (status < 0) 71562306a36Sopenharmony_ci break; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /*==== Mode ====*/ 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* Powerdown PD2, WRI source */ 72062306a36Sopenharmony_ci state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 72162306a36Sopenharmony_ci state->m_FeAgRegAgPwd |= 72262306a36Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; 72362306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); 72462306a36Sopenharmony_ci if (status < 0) 72562306a36Sopenharmony_ci break; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 72862306a36Sopenharmony_ci if (status < 0) 72962306a36Sopenharmony_ci break; 73062306a36Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 73162306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 73262306a36Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 73362306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); 73462306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 73562306a36Sopenharmony_ci if (status < 0) 73662306a36Sopenharmony_ci break; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* enable AGC2 pin */ 73962306a36Sopenharmony_ci { 74062306a36Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 74162306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 74262306a36Sopenharmony_ci if (status < 0) 74362306a36Sopenharmony_ci break; 74462306a36Sopenharmony_ci FeAgRegAgAgcSio &= 74562306a36Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 74662306a36Sopenharmony_ci FeAgRegAgAgcSio |= 74762306a36Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; 74862306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 74962306a36Sopenharmony_ci if (status < 0) 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci } while (0); 75462306a36Sopenharmony_ci } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { 75562306a36Sopenharmony_ci u16 AgModeLop = 0; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci do { 75862306a36Sopenharmony_ci u16 level; 75962306a36Sopenharmony_ci /* Automatic control */ 76062306a36Sopenharmony_ci /* Powerup PD2, AGC2 as output, TGC source */ 76162306a36Sopenharmony_ci (state->m_FeAgRegAgPwd) &= 76262306a36Sopenharmony_ci ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 76362306a36Sopenharmony_ci (state->m_FeAgRegAgPwd) |= 76462306a36Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; 76562306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); 76662306a36Sopenharmony_ci if (status < 0) 76762306a36Sopenharmony_ci break; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 77062306a36Sopenharmony_ci if (status < 0) 77162306a36Sopenharmony_ci break; 77262306a36Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 77362306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 77462306a36Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 77562306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC); 77662306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 77762306a36Sopenharmony_ci if (status < 0) 77862306a36Sopenharmony_ci break; 77962306a36Sopenharmony_ci /* Settle level */ 78062306a36Sopenharmony_ci level = (((cfg->settleLevel) >> 4) & 78162306a36Sopenharmony_ci FE_AG_REG_TGC_SET_LVL__M); 78262306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000); 78362306a36Sopenharmony_ci if (status < 0) 78462306a36Sopenharmony_ci break; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci /* Min/max: don't care */ 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci /* Speed: TODO */ 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* enable AGC2 pin */ 79162306a36Sopenharmony_ci { 79262306a36Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 79362306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 79462306a36Sopenharmony_ci if (status < 0) 79562306a36Sopenharmony_ci break; 79662306a36Sopenharmony_ci FeAgRegAgAgcSio &= 79762306a36Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 79862306a36Sopenharmony_ci FeAgRegAgAgcSio |= 79962306a36Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; 80062306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 80162306a36Sopenharmony_ci if (status < 0) 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci } while (0); 80662306a36Sopenharmony_ci } else { 80762306a36Sopenharmony_ci u16 AgModeLop = 0; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci do { 81062306a36Sopenharmony_ci /* No RF AGC control */ 81162306a36Sopenharmony_ci /* Powerdown PD2, AGC2 as output, WRI source */ 81262306a36Sopenharmony_ci (state->m_FeAgRegAgPwd) &= 81362306a36Sopenharmony_ci ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 81462306a36Sopenharmony_ci (state->m_FeAgRegAgPwd) |= 81562306a36Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_ENABLE; 81662306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); 81762306a36Sopenharmony_ci if (status < 0) 81862306a36Sopenharmony_ci break; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 82162306a36Sopenharmony_ci if (status < 0) 82262306a36Sopenharmony_ci break; 82362306a36Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 82462306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 82562306a36Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 82662306a36Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); 82762306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 82862306a36Sopenharmony_ci if (status < 0) 82962306a36Sopenharmony_ci break; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* set FeAgRegAgAgcSio AGC2 (RF) as input */ 83262306a36Sopenharmony_ci { 83362306a36Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 83462306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 83562306a36Sopenharmony_ci if (status < 0) 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci FeAgRegAgAgcSio &= 83862306a36Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 83962306a36Sopenharmony_ci FeAgRegAgAgcSio |= 84062306a36Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT; 84162306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 84262306a36Sopenharmony_ci if (status < 0) 84362306a36Sopenharmony_ci break; 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci } while (0); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci return status; 84862306a36Sopenharmony_ci} 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_cistatic int ReadIFAgc(struct drxd_state *state, u32 * pValue) 85162306a36Sopenharmony_ci{ 85262306a36Sopenharmony_ci int status = 0; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci *pValue = 0; 85562306a36Sopenharmony_ci if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) { 85662306a36Sopenharmony_ci u16 Value; 85762306a36Sopenharmony_ci status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0); 85862306a36Sopenharmony_ci Value &= FE_AG_REG_GC1_AGC_DAT__M; 85962306a36Sopenharmony_ci if (status >= 0) { 86062306a36Sopenharmony_ci /* 3.3V 86162306a36Sopenharmony_ci | 86262306a36Sopenharmony_ci R1 86362306a36Sopenharmony_ci | 86462306a36Sopenharmony_ci Vin - R3 - * -- Vout 86562306a36Sopenharmony_ci | 86662306a36Sopenharmony_ci R2 86762306a36Sopenharmony_ci | 86862306a36Sopenharmony_ci GND 86962306a36Sopenharmony_ci */ 87062306a36Sopenharmony_ci u32 R1 = state->if_agc_cfg.R1; 87162306a36Sopenharmony_ci u32 R2 = state->if_agc_cfg.R2; 87262306a36Sopenharmony_ci u32 R3 = state->if_agc_cfg.R3; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci u32 Vmax, Rpar, Vmin, Vout; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci if (R2 == 0 && (R1 == 0 || R3 == 0)) 87762306a36Sopenharmony_ci return 0; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci Vmax = (3300 * R2) / (R1 + R2); 88062306a36Sopenharmony_ci Rpar = (R2 * R3) / (R3 + R2); 88162306a36Sopenharmony_ci Vmin = (3300 * Rpar) / (R1 + Rpar); 88262306a36Sopenharmony_ci Vout = Vmin + ((Vmax - Vmin) * Value) / 1024; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci *pValue = Vout; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci } 88762306a36Sopenharmony_ci return status; 88862306a36Sopenharmony_ci} 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cistatic int load_firmware(struct drxd_state *state, const char *fw_name) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci const struct firmware *fw; 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci if (request_firmware(&fw, fw_name, state->dev) < 0) { 89562306a36Sopenharmony_ci printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name); 89662306a36Sopenharmony_ci return -EIO; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL); 90062306a36Sopenharmony_ci if (!state->microcode) { 90162306a36Sopenharmony_ci release_firmware(fw); 90262306a36Sopenharmony_ci return -ENOMEM; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci state->microcode_length = fw->size; 90662306a36Sopenharmony_ci release_firmware(fw); 90762306a36Sopenharmony_ci return 0; 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_cistatic int DownloadMicrocode(struct drxd_state *state, 91162306a36Sopenharmony_ci const u8 *pMCImage, u32 Length) 91262306a36Sopenharmony_ci{ 91362306a36Sopenharmony_ci u8 *pSrc; 91462306a36Sopenharmony_ci u32 Address; 91562306a36Sopenharmony_ci u16 nBlocks; 91662306a36Sopenharmony_ci u16 BlockSize; 91762306a36Sopenharmony_ci int i, status = 0; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci pSrc = (u8 *) pMCImage; 92062306a36Sopenharmony_ci /* We're not using Flags */ 92162306a36Sopenharmony_ci /* Flags = (pSrc[0] << 8) | pSrc[1]; */ 92262306a36Sopenharmony_ci pSrc += sizeof(u16); 92362306a36Sopenharmony_ci nBlocks = (pSrc[0] << 8) | pSrc[1]; 92462306a36Sopenharmony_ci pSrc += sizeof(u16); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci for (i = 0; i < nBlocks; i++) { 92762306a36Sopenharmony_ci Address = (pSrc[0] << 24) | (pSrc[1] << 16) | 92862306a36Sopenharmony_ci (pSrc[2] << 8) | pSrc[3]; 92962306a36Sopenharmony_ci pSrc += sizeof(u32); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); 93262306a36Sopenharmony_ci pSrc += sizeof(u16); 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci /* We're not using Flags */ 93562306a36Sopenharmony_ci /* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */ 93662306a36Sopenharmony_ci pSrc += sizeof(u16); 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci /* We're not using BlockCRC */ 93962306a36Sopenharmony_ci /* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */ 94062306a36Sopenharmony_ci pSrc += sizeof(u16); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci status = WriteBlock(state, Address, BlockSize, 94362306a36Sopenharmony_ci pSrc, DRX_I2C_CLEARCRC); 94462306a36Sopenharmony_ci if (status < 0) 94562306a36Sopenharmony_ci break; 94662306a36Sopenharmony_ci pSrc += BlockSize; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci return status; 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_cistatic int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci u32 nrRetries = 0; 95562306a36Sopenharmony_ci int status; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0); 95862306a36Sopenharmony_ci if (status < 0) 95962306a36Sopenharmony_ci return status; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci do { 96262306a36Sopenharmony_ci nrRetries += 1; 96362306a36Sopenharmony_ci if (nrRetries > DRXD_MAX_RETRIES) { 96462306a36Sopenharmony_ci status = -1; 96562306a36Sopenharmony_ci break; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci status = Read16(state, HI_RA_RAM_SRV_CMD__A, NULL, 0); 96862306a36Sopenharmony_ci } while (status != 0); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci if (status >= 0) 97162306a36Sopenharmony_ci status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0); 97262306a36Sopenharmony_ci return status; 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic int HI_CfgCommand(struct drxd_state *state) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci int status = 0; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci mutex_lock(&state->mutex); 98062306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); 98162306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0); 98262306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0); 98362306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0); 98462306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) == 98962306a36Sopenharmony_ci HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) 99062306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CMD__A, 99162306a36Sopenharmony_ci HI_RA_RAM_SRV_CMD_CONFIG, 0); 99262306a36Sopenharmony_ci else 99362306a36Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, NULL); 99462306a36Sopenharmony_ci mutex_unlock(&state->mutex); 99562306a36Sopenharmony_ci return status; 99662306a36Sopenharmony_ci} 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_cistatic int InitHI(struct drxd_state *state) 99962306a36Sopenharmony_ci{ 100062306a36Sopenharmony_ci state->hi_cfg_wakeup_key = (state->chip_adr); 100162306a36Sopenharmony_ci /* port/bridge/power down ctrl */ 100262306a36Sopenharmony_ci state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON; 100362306a36Sopenharmony_ci return HI_CfgCommand(state); 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic int HI_ResetCommand(struct drxd_state *state) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci int status; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci mutex_lock(&state->mutex); 101162306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A, 101262306a36Sopenharmony_ci HI_RA_RAM_SRV_RST_KEY_ACT, 0); 101362306a36Sopenharmony_ci if (status == 0) 101462306a36Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, NULL); 101562306a36Sopenharmony_ci mutex_unlock(&state->mutex); 101662306a36Sopenharmony_ci msleep(1); 101762306a36Sopenharmony_ci return status; 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_cistatic int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge) 102162306a36Sopenharmony_ci{ 102262306a36Sopenharmony_ci state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M); 102362306a36Sopenharmony_ci if (bEnableBridge) 102462306a36Sopenharmony_ci state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON; 102562306a36Sopenharmony_ci else 102662306a36Sopenharmony_ci state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci return HI_CfgCommand(state); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci#define HI_TR_WRITE 0x9 103262306a36Sopenharmony_ci#define HI_TR_READ 0xA 103362306a36Sopenharmony_ci#define HI_TR_READ_WRITE 0xB 103462306a36Sopenharmony_ci#define HI_TR_BROADCAST 0x4 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci#if 0 103762306a36Sopenharmony_cistatic int AtomicReadBlock(struct drxd_state *state, 103862306a36Sopenharmony_ci u32 Addr, u16 DataSize, u8 *pData, u8 Flags) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci int status; 104162306a36Sopenharmony_ci int i = 0; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* Parameter check */ 104462306a36Sopenharmony_ci if ((!pData) || ((DataSize & 1) != 0)) 104562306a36Sopenharmony_ci return -1; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci mutex_lock(&state->mutex); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci do { 105062306a36Sopenharmony_ci /* Instruct HI to read n bytes */ 105162306a36Sopenharmony_ci /* TODO use proper names forthese egisters */ 105262306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0); 105362306a36Sopenharmony_ci if (status < 0) 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0); 105662306a36Sopenharmony_ci if (status < 0) 105762306a36Sopenharmony_ci break; 105862306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0); 105962306a36Sopenharmony_ci if (status < 0) 106062306a36Sopenharmony_ci break; 106162306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0); 106262306a36Sopenharmony_ci if (status < 0) 106362306a36Sopenharmony_ci break; 106462306a36Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0); 106562306a36Sopenharmony_ci if (status < 0) 106662306a36Sopenharmony_ci break; 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0); 106962306a36Sopenharmony_ci if (status < 0) 107062306a36Sopenharmony_ci break; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci } while (0); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci if (status >= 0) { 107562306a36Sopenharmony_ci for (i = 0; i < (DataSize / 2); i += 1) { 107662306a36Sopenharmony_ci u16 word; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i), 107962306a36Sopenharmony_ci &word, 0); 108062306a36Sopenharmony_ci if (status < 0) 108162306a36Sopenharmony_ci break; 108262306a36Sopenharmony_ci pData[2 * i] = (u8) (word & 0xFF); 108362306a36Sopenharmony_ci pData[(2 * i) + 1] = (u8) (word >> 8); 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci mutex_unlock(&state->mutex); 108762306a36Sopenharmony_ci return status; 108862306a36Sopenharmony_ci} 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cistatic int AtomicReadReg32(struct drxd_state *state, 109162306a36Sopenharmony_ci u32 Addr, u32 *pData, u8 Flags) 109262306a36Sopenharmony_ci{ 109362306a36Sopenharmony_ci u8 buf[sizeof(u32)]; 109462306a36Sopenharmony_ci int status; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci if (!pData) 109762306a36Sopenharmony_ci return -1; 109862306a36Sopenharmony_ci status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags); 109962306a36Sopenharmony_ci *pData = (((u32) buf[0]) << 0) + 110062306a36Sopenharmony_ci (((u32) buf[1]) << 8) + 110162306a36Sopenharmony_ci (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24); 110262306a36Sopenharmony_ci return status; 110362306a36Sopenharmony_ci} 110462306a36Sopenharmony_ci#endif 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic int StopAllProcessors(struct drxd_state *state) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci return Write16(state, HI_COMM_EXEC__A, 110962306a36Sopenharmony_ci SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST); 111062306a36Sopenharmony_ci} 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic int EnableAndResetMB(struct drxd_state *state) 111362306a36Sopenharmony_ci{ 111462306a36Sopenharmony_ci if (state->type_A) { 111562306a36Sopenharmony_ci /* disable? monitor bus observe @ EC_OC */ 111662306a36Sopenharmony_ci Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000); 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* do inverse broadcast, followed by explicit write to HI */ 112062306a36Sopenharmony_ci Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST); 112162306a36Sopenharmony_ci Write16(state, HI_COMM_MB__A, 0x0000, 0x0000); 112262306a36Sopenharmony_ci return 0; 112362306a36Sopenharmony_ci} 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_cistatic int InitCC(struct drxd_state *state) 112662306a36Sopenharmony_ci{ 112762306a36Sopenharmony_ci int status = 0; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci if (state->osc_clock_freq == 0 || 113062306a36Sopenharmony_ci state->osc_clock_freq > 20000 || 113162306a36Sopenharmony_ci (state->osc_clock_freq % 4000) != 0) { 113262306a36Sopenharmony_ci printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq); 113362306a36Sopenharmony_ci return -1; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci status |= Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0); 113762306a36Sopenharmony_ci status |= Write16(state, CC_REG_PLL_MODE__A, 113862306a36Sopenharmony_ci CC_REG_PLL_MODE_BYPASS_PLL | 113962306a36Sopenharmony_ci CC_REG_PLL_MODE_PUMP_CUR_12, 0); 114062306a36Sopenharmony_ci status |= Write16(state, CC_REG_REF_DIVIDE__A, 114162306a36Sopenharmony_ci state->osc_clock_freq / 4000, 0); 114262306a36Sopenharmony_ci status |= Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 114362306a36Sopenharmony_ci 0); 114462306a36Sopenharmony_ci status |= Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci return status; 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic int ResetECOD(struct drxd_state *state) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci int status = 0; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci if (state->type_A) 115462306a36Sopenharmony_ci status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0); 115562306a36Sopenharmony_ci else 115662306a36Sopenharmony_ci status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci if (!(status < 0)) 115962306a36Sopenharmony_ci status = WriteTable(state, state->m_ResetECRAM); 116062306a36Sopenharmony_ci if (!(status < 0)) 116162306a36Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0); 116262306a36Sopenharmony_ci return status; 116362306a36Sopenharmony_ci} 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci/* Configure PGA switch */ 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_cistatic int SetCfgPga(struct drxd_state *state, int pgaSwitch) 116862306a36Sopenharmony_ci{ 116962306a36Sopenharmony_ci int status; 117062306a36Sopenharmony_ci u16 AgModeLop = 0; 117162306a36Sopenharmony_ci u16 AgModeHip = 0; 117262306a36Sopenharmony_ci do { 117362306a36Sopenharmony_ci if (pgaSwitch) { 117462306a36Sopenharmony_ci /* PGA on */ 117562306a36Sopenharmony_ci /* fine gain */ 117662306a36Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 117762306a36Sopenharmony_ci if (status < 0) 117862306a36Sopenharmony_ci break; 117962306a36Sopenharmony_ci AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); 118062306a36Sopenharmony_ci AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC; 118162306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 118262306a36Sopenharmony_ci if (status < 0) 118362306a36Sopenharmony_ci break; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci /* coarse gain */ 118662306a36Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); 118762306a36Sopenharmony_ci if (status < 0) 118862306a36Sopenharmony_ci break; 118962306a36Sopenharmony_ci AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); 119062306a36Sopenharmony_ci AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC; 119162306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); 119262306a36Sopenharmony_ci if (status < 0) 119362306a36Sopenharmony_ci break; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci /* enable fine and coarse gain, enable AAF, 119662306a36Sopenharmony_ci no ext resistor */ 119762306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000); 119862306a36Sopenharmony_ci if (status < 0) 119962306a36Sopenharmony_ci break; 120062306a36Sopenharmony_ci } else { 120162306a36Sopenharmony_ci /* PGA off, bypass */ 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci /* fine gain */ 120462306a36Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 120562306a36Sopenharmony_ci if (status < 0) 120662306a36Sopenharmony_ci break; 120762306a36Sopenharmony_ci AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); 120862306a36Sopenharmony_ci AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC; 120962306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 121062306a36Sopenharmony_ci if (status < 0) 121162306a36Sopenharmony_ci break; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci /* coarse gain */ 121462306a36Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); 121562306a36Sopenharmony_ci if (status < 0) 121662306a36Sopenharmony_ci break; 121762306a36Sopenharmony_ci AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); 121862306a36Sopenharmony_ci AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC; 121962306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); 122062306a36Sopenharmony_ci if (status < 0) 122162306a36Sopenharmony_ci break; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci /* disable fine and coarse gain, enable AAF, 122462306a36Sopenharmony_ci no ext resistor */ 122562306a36Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000); 122662306a36Sopenharmony_ci if (status < 0) 122762306a36Sopenharmony_ci break; 122862306a36Sopenharmony_ci } 122962306a36Sopenharmony_ci } while (0); 123062306a36Sopenharmony_ci return status; 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_cistatic int InitFE(struct drxd_state *state) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci int status; 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci do { 123862306a36Sopenharmony_ci status = WriteTable(state, state->m_InitFE_1); 123962306a36Sopenharmony_ci if (status < 0) 124062306a36Sopenharmony_ci break; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci if (state->type_A) { 124362306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PGA_MODE__A, 124462306a36Sopenharmony_ci FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 124562306a36Sopenharmony_ci 0); 124662306a36Sopenharmony_ci } else { 124762306a36Sopenharmony_ci if (state->PGA) 124862306a36Sopenharmony_ci status = SetCfgPga(state, 0); 124962306a36Sopenharmony_ci else 125062306a36Sopenharmony_ci status = 125162306a36Sopenharmony_ci Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, 125262306a36Sopenharmony_ci B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 125362306a36Sopenharmony_ci 0); 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci if (status < 0) 125762306a36Sopenharmony_ci break; 125862306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000); 125962306a36Sopenharmony_ci if (status < 0) 126062306a36Sopenharmony_ci break; 126162306a36Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); 126262306a36Sopenharmony_ci if (status < 0) 126362306a36Sopenharmony_ci break; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci status = WriteTable(state, state->m_InitFE_2); 126662306a36Sopenharmony_ci if (status < 0) 126762306a36Sopenharmony_ci break; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci } while (0); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci return status; 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_cistatic int InitFT(struct drxd_state *state) 127562306a36Sopenharmony_ci{ 127662306a36Sopenharmony_ci /* 127762306a36Sopenharmony_ci norm OFFSET, MB says =2 voor 8K en =3 voor 2K waarschijnlijk 127862306a36Sopenharmony_ci SC stuff 127962306a36Sopenharmony_ci */ 128062306a36Sopenharmony_ci return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000); 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic int SC_WaitForReady(struct drxd_state *state) 128462306a36Sopenharmony_ci{ 128562306a36Sopenharmony_ci int i; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci for (i = 0; i < DRXD_MAX_RETRIES; i += 1) { 128862306a36Sopenharmony_ci int status = Read16(state, SC_RA_RAM_CMD__A, NULL, 0); 128962306a36Sopenharmony_ci if (status == 0) 129062306a36Sopenharmony_ci return status; 129162306a36Sopenharmony_ci } 129262306a36Sopenharmony_ci return -1; 129362306a36Sopenharmony_ci} 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_cistatic int SC_SendCommand(struct drxd_state *state, u16 cmd) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci int status = 0, ret; 129862306a36Sopenharmony_ci u16 errCode; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_CMD__A, cmd, 0); 130162306a36Sopenharmony_ci if (status < 0) 130262306a36Sopenharmony_ci return status; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci SC_WaitForReady(state); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci ret = Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if (ret < 0 || errCode == 0xFFFF) { 130962306a36Sopenharmony_ci printk(KERN_ERR "Command Error\n"); 131062306a36Sopenharmony_ci status = -1; 131162306a36Sopenharmony_ci } 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci return status; 131462306a36Sopenharmony_ci} 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_cistatic int SC_ProcStartCommand(struct drxd_state *state, 131762306a36Sopenharmony_ci u16 subCmd, u16 param0, u16 param1) 131862306a36Sopenharmony_ci{ 131962306a36Sopenharmony_ci int ret, status = 0; 132062306a36Sopenharmony_ci u16 scExec; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci mutex_lock(&state->mutex); 132362306a36Sopenharmony_ci do { 132462306a36Sopenharmony_ci ret = Read16(state, SC_COMM_EXEC__A, &scExec, 0); 132562306a36Sopenharmony_ci if (ret < 0 || scExec != 1) { 132662306a36Sopenharmony_ci status = -1; 132762306a36Sopenharmony_ci break; 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci SC_WaitForReady(state); 133062306a36Sopenharmony_ci status |= Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); 133162306a36Sopenharmony_ci status |= Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); 133262306a36Sopenharmony_ci status |= Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START); 133562306a36Sopenharmony_ci } while (0); 133662306a36Sopenharmony_ci mutex_unlock(&state->mutex); 133762306a36Sopenharmony_ci return status; 133862306a36Sopenharmony_ci} 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_cistatic int SC_SetPrefParamCommand(struct drxd_state *state, 134162306a36Sopenharmony_ci u16 subCmd, u16 param0, u16 param1) 134262306a36Sopenharmony_ci{ 134362306a36Sopenharmony_ci int status; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci mutex_lock(&state->mutex); 134662306a36Sopenharmony_ci do { 134762306a36Sopenharmony_ci status = SC_WaitForReady(state); 134862306a36Sopenharmony_ci if (status < 0) 134962306a36Sopenharmony_ci break; 135062306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); 135162306a36Sopenharmony_ci if (status < 0) 135262306a36Sopenharmony_ci break; 135362306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); 135462306a36Sopenharmony_ci if (status < 0) 135562306a36Sopenharmony_ci break; 135662306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); 135762306a36Sopenharmony_ci if (status < 0) 135862306a36Sopenharmony_ci break; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM); 136162306a36Sopenharmony_ci if (status < 0) 136262306a36Sopenharmony_ci break; 136362306a36Sopenharmony_ci } while (0); 136462306a36Sopenharmony_ci mutex_unlock(&state->mutex); 136562306a36Sopenharmony_ci return status; 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci#if 0 136962306a36Sopenharmony_cistatic int SC_GetOpParamCommand(struct drxd_state *state, u16 * result) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci int status = 0; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci mutex_lock(&state->mutex); 137462306a36Sopenharmony_ci do { 137562306a36Sopenharmony_ci status = SC_WaitForReady(state); 137662306a36Sopenharmony_ci if (status < 0) 137762306a36Sopenharmony_ci break; 137862306a36Sopenharmony_ci status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM); 137962306a36Sopenharmony_ci if (status < 0) 138062306a36Sopenharmony_ci break; 138162306a36Sopenharmony_ci status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0); 138262306a36Sopenharmony_ci if (status < 0) 138362306a36Sopenharmony_ci break; 138462306a36Sopenharmony_ci } while (0); 138562306a36Sopenharmony_ci mutex_unlock(&state->mutex); 138662306a36Sopenharmony_ci return status; 138762306a36Sopenharmony_ci} 138862306a36Sopenharmony_ci#endif 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_cistatic int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput) 139162306a36Sopenharmony_ci{ 139262306a36Sopenharmony_ci int status; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci do { 139562306a36Sopenharmony_ci u16 EcOcRegIprInvMpg = 0; 139662306a36Sopenharmony_ci u16 EcOcRegOcModeLop = 0; 139762306a36Sopenharmony_ci u16 EcOcRegOcModeHip = 0; 139862306a36Sopenharmony_ci u16 EcOcRegOcMpgSio = 0; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci /*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */ 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front) { 140362306a36Sopenharmony_ci if (bEnableOutput) { 140462306a36Sopenharmony_ci EcOcRegOcModeHip |= 140562306a36Sopenharmony_ci B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR; 140662306a36Sopenharmony_ci } else 140762306a36Sopenharmony_ci EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; 140862306a36Sopenharmony_ci EcOcRegOcModeLop |= 140962306a36Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; 141062306a36Sopenharmony_ci } else { 141162306a36Sopenharmony_ci EcOcRegOcModeLop = state->m_EcOcRegOcModeLop; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (bEnableOutput) 141462306a36Sopenharmony_ci EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M)); 141562306a36Sopenharmony_ci else 141662306a36Sopenharmony_ci EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* Don't Insert RS Byte */ 141962306a36Sopenharmony_ci if (state->insert_rs_byte) { 142062306a36Sopenharmony_ci EcOcRegOcModeLop &= 142162306a36Sopenharmony_ci (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M)); 142262306a36Sopenharmony_ci EcOcRegOcModeHip &= 142362306a36Sopenharmony_ci (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); 142462306a36Sopenharmony_ci EcOcRegOcModeHip |= 142562306a36Sopenharmony_ci EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE; 142662306a36Sopenharmony_ci } else { 142762306a36Sopenharmony_ci EcOcRegOcModeLop |= 142862306a36Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; 142962306a36Sopenharmony_ci EcOcRegOcModeHip &= 143062306a36Sopenharmony_ci (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); 143162306a36Sopenharmony_ci EcOcRegOcModeHip |= 143262306a36Sopenharmony_ci EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE; 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci /* Mode = Parallel */ 143662306a36Sopenharmony_ci if (state->enable_parallel) 143762306a36Sopenharmony_ci EcOcRegOcModeLop &= 143862306a36Sopenharmony_ci (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M)); 143962306a36Sopenharmony_ci else 144062306a36Sopenharmony_ci EcOcRegOcModeLop |= 144162306a36Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL; 144262306a36Sopenharmony_ci } 144362306a36Sopenharmony_ci /* Invert Data */ 144462306a36Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x00FF; */ 144562306a36Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x00FF)); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci /* Invert Error ( we don't use the pin ) */ 144862306a36Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0100; */ 144962306a36Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0100)); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci /* Invert Start ( we don't use the pin ) */ 145262306a36Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0200; */ 145362306a36Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0200)); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* Invert Valid ( we don't use the pin ) */ 145662306a36Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0400; */ 145762306a36Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0400)); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci /* Invert Clock */ 146062306a36Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0800; */ 146162306a36Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0800)); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci /* EcOcRegOcModeLop =0x05; */ 146462306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0); 146562306a36Sopenharmony_ci if (status < 0) 146662306a36Sopenharmony_ci break; 146762306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0); 146862306a36Sopenharmony_ci if (status < 0) 146962306a36Sopenharmony_ci break; 147062306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000); 147162306a36Sopenharmony_ci if (status < 0) 147262306a36Sopenharmony_ci break; 147362306a36Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0); 147462306a36Sopenharmony_ci if (status < 0) 147562306a36Sopenharmony_ci break; 147662306a36Sopenharmony_ci } while (0); 147762306a36Sopenharmony_ci return status; 147862306a36Sopenharmony_ci} 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_cistatic int SetDeviceTypeId(struct drxd_state *state) 148162306a36Sopenharmony_ci{ 148262306a36Sopenharmony_ci int status = 0; 148362306a36Sopenharmony_ci u16 deviceId = 0; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci do { 148662306a36Sopenharmony_ci status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); 148762306a36Sopenharmony_ci if (status < 0) 148862306a36Sopenharmony_ci break; 148962306a36Sopenharmony_ci /* TODO: why twice? */ 149062306a36Sopenharmony_ci status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); 149162306a36Sopenharmony_ci if (status < 0) 149262306a36Sopenharmony_ci break; 149362306a36Sopenharmony_ci printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci state->type_A = 0; 149662306a36Sopenharmony_ci state->PGA = 0; 149762306a36Sopenharmony_ci state->diversity = 0; 149862306a36Sopenharmony_ci if (deviceId == 0) { /* on A2 only 3975 available */ 149962306a36Sopenharmony_ci state->type_A = 1; 150062306a36Sopenharmony_ci printk(KERN_INFO "DRX3975D-A2\n"); 150162306a36Sopenharmony_ci } else { 150262306a36Sopenharmony_ci deviceId >>= 12; 150362306a36Sopenharmony_ci printk(KERN_INFO "DRX397%dD-B1\n", deviceId); 150462306a36Sopenharmony_ci switch (deviceId) { 150562306a36Sopenharmony_ci case 4: 150662306a36Sopenharmony_ci state->diversity = 1; 150762306a36Sopenharmony_ci fallthrough; 150862306a36Sopenharmony_ci case 3: 150962306a36Sopenharmony_ci case 7: 151062306a36Sopenharmony_ci state->PGA = 1; 151162306a36Sopenharmony_ci break; 151262306a36Sopenharmony_ci case 6: 151362306a36Sopenharmony_ci state->diversity = 1; 151462306a36Sopenharmony_ci fallthrough; 151562306a36Sopenharmony_ci case 5: 151662306a36Sopenharmony_ci case 8: 151762306a36Sopenharmony_ci break; 151862306a36Sopenharmony_ci default: 151962306a36Sopenharmony_ci status = -1; 152062306a36Sopenharmony_ci break; 152162306a36Sopenharmony_ci } 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci } while (0); 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci if (status < 0) 152662306a36Sopenharmony_ci return status; 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci /* Init Table selection */ 152962306a36Sopenharmony_ci state->m_InitAtomicRead = DRXD_InitAtomicRead; 153062306a36Sopenharmony_ci state->m_InitSC = DRXD_InitSC; 153162306a36Sopenharmony_ci state->m_ResetECRAM = DRXD_ResetECRAM; 153262306a36Sopenharmony_ci if (state->type_A) { 153362306a36Sopenharmony_ci state->m_ResetCEFR = DRXD_ResetCEFR; 153462306a36Sopenharmony_ci state->m_InitFE_1 = DRXD_InitFEA2_1; 153562306a36Sopenharmony_ci state->m_InitFE_2 = DRXD_InitFEA2_2; 153662306a36Sopenharmony_ci state->m_InitCP = DRXD_InitCPA2; 153762306a36Sopenharmony_ci state->m_InitCE = DRXD_InitCEA2; 153862306a36Sopenharmony_ci state->m_InitEQ = DRXD_InitEQA2; 153962306a36Sopenharmony_ci state->m_InitEC = DRXD_InitECA2; 154062306a36Sopenharmony_ci if (load_firmware(state, DRX_FW_FILENAME_A2)) 154162306a36Sopenharmony_ci return -EIO; 154262306a36Sopenharmony_ci } else { 154362306a36Sopenharmony_ci state->m_ResetCEFR = NULL; 154462306a36Sopenharmony_ci state->m_InitFE_1 = DRXD_InitFEB1_1; 154562306a36Sopenharmony_ci state->m_InitFE_2 = DRXD_InitFEB1_2; 154662306a36Sopenharmony_ci state->m_InitCP = DRXD_InitCPB1; 154762306a36Sopenharmony_ci state->m_InitCE = DRXD_InitCEB1; 154862306a36Sopenharmony_ci state->m_InitEQ = DRXD_InitEQB1; 154962306a36Sopenharmony_ci state->m_InitEC = DRXD_InitECB1; 155062306a36Sopenharmony_ci if (load_firmware(state, DRX_FW_FILENAME_B1)) 155162306a36Sopenharmony_ci return -EIO; 155262306a36Sopenharmony_ci } 155362306a36Sopenharmony_ci if (state->diversity) { 155462306a36Sopenharmony_ci state->m_InitDiversityFront = DRXD_InitDiversityFront; 155562306a36Sopenharmony_ci state->m_InitDiversityEnd = DRXD_InitDiversityEnd; 155662306a36Sopenharmony_ci state->m_DisableDiversity = DRXD_DisableDiversity; 155762306a36Sopenharmony_ci state->m_StartDiversityFront = DRXD_StartDiversityFront; 155862306a36Sopenharmony_ci state->m_StartDiversityEnd = DRXD_StartDiversityEnd; 155962306a36Sopenharmony_ci state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ; 156062306a36Sopenharmony_ci state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ; 156162306a36Sopenharmony_ci } else { 156262306a36Sopenharmony_ci state->m_InitDiversityFront = NULL; 156362306a36Sopenharmony_ci state->m_InitDiversityEnd = NULL; 156462306a36Sopenharmony_ci state->m_DisableDiversity = NULL; 156562306a36Sopenharmony_ci state->m_StartDiversityFront = NULL; 156662306a36Sopenharmony_ci state->m_StartDiversityEnd = NULL; 156762306a36Sopenharmony_ci state->m_DiversityDelay8MHZ = NULL; 156862306a36Sopenharmony_ci state->m_DiversityDelay6MHZ = NULL; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci return status; 157262306a36Sopenharmony_ci} 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_cistatic int CorrectSysClockDeviation(struct drxd_state *state) 157562306a36Sopenharmony_ci{ 157662306a36Sopenharmony_ci int status; 157762306a36Sopenharmony_ci s32 incr = 0; 157862306a36Sopenharmony_ci s32 nomincr = 0; 157962306a36Sopenharmony_ci u32 bandwidth = 0; 158062306a36Sopenharmony_ci u32 sysClockInHz = 0; 158162306a36Sopenharmony_ci u32 sysClockFreq = 0; /* in kHz */ 158262306a36Sopenharmony_ci s16 oscClockDeviation; 158362306a36Sopenharmony_ci s16 Diff; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci do { 158662306a36Sopenharmony_ci /* Retrieve bandwidth and incr, sanity check */ 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci /* These accesses should be AtomicReadReg32, but that 158962306a36Sopenharmony_ci causes trouble (at least for diversity */ 159062306a36Sopenharmony_ci status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0); 159162306a36Sopenharmony_ci if (status < 0) 159262306a36Sopenharmony_ci break; 159362306a36Sopenharmony_ci status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0); 159462306a36Sopenharmony_ci if (status < 0) 159562306a36Sopenharmony_ci break; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (state->type_A) { 159862306a36Sopenharmony_ci if ((nomincr - incr < -500) || (nomincr - incr > 500)) 159962306a36Sopenharmony_ci break; 160062306a36Sopenharmony_ci } else { 160162306a36Sopenharmony_ci if ((nomincr - incr < -2000) || (nomincr - incr > 2000)) 160262306a36Sopenharmony_ci break; 160362306a36Sopenharmony_ci } 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci switch (state->props.bandwidth_hz) { 160662306a36Sopenharmony_ci case 8000000: 160762306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; 160862306a36Sopenharmony_ci break; 160962306a36Sopenharmony_ci case 7000000: 161062306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; 161162306a36Sopenharmony_ci break; 161262306a36Sopenharmony_ci case 6000000: 161362306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; 161462306a36Sopenharmony_ci break; 161562306a36Sopenharmony_ci default: 161662306a36Sopenharmony_ci return -1; 161762306a36Sopenharmony_ci } 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci /* Compute new sysclock value 162062306a36Sopenharmony_ci sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */ 162162306a36Sopenharmony_ci incr += (1 << 23); 162262306a36Sopenharmony_ci sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21); 162362306a36Sopenharmony_ci sysClockFreq = (u32) (sysClockInHz / 1000); 162462306a36Sopenharmony_ci /* rounding */ 162562306a36Sopenharmony_ci if ((sysClockInHz % 1000) > 500) 162662306a36Sopenharmony_ci sysClockFreq++; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci /* Compute clock deviation in ppm */ 162962306a36Sopenharmony_ci oscClockDeviation = (u16) ((((s32) (sysClockFreq) - 163062306a36Sopenharmony_ci (s32) 163162306a36Sopenharmony_ci (state->expected_sys_clock_freq)) * 163262306a36Sopenharmony_ci 1000000L) / 163362306a36Sopenharmony_ci (s32) 163462306a36Sopenharmony_ci (state->expected_sys_clock_freq)); 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci Diff = oscClockDeviation - state->osc_clock_deviation; 163762306a36Sopenharmony_ci /*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */ 163862306a36Sopenharmony_ci if (Diff >= -200 && Diff <= 200) { 163962306a36Sopenharmony_ci state->sys_clock_freq = (u16) sysClockFreq; 164062306a36Sopenharmony_ci if (oscClockDeviation != state->osc_clock_deviation) { 164162306a36Sopenharmony_ci if (state->config.osc_deviation) { 164262306a36Sopenharmony_ci state->config.osc_deviation(state->priv, 164362306a36Sopenharmony_ci oscClockDeviation, 164462306a36Sopenharmony_ci 1); 164562306a36Sopenharmony_ci state->osc_clock_deviation = 164662306a36Sopenharmony_ci oscClockDeviation; 164762306a36Sopenharmony_ci } 164862306a36Sopenharmony_ci } 164962306a36Sopenharmony_ci /* switch OFF SRMM scan in SC */ 165062306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0); 165162306a36Sopenharmony_ci if (status < 0) 165262306a36Sopenharmony_ci break; 165362306a36Sopenharmony_ci /* overrule FE_IF internal value for 165462306a36Sopenharmony_ci proper re-locking */ 165562306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0); 165662306a36Sopenharmony_ci if (status < 0) 165762306a36Sopenharmony_ci break; 165862306a36Sopenharmony_ci state->cscd_state = CSCD_SAVED; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci } while (0); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci return status; 166362306a36Sopenharmony_ci} 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_cistatic int DRX_Stop(struct drxd_state *state) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci int status; 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci if (state->drxd_state != DRXD_STARTED) 167062306a36Sopenharmony_ci return 0; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci do { 167362306a36Sopenharmony_ci if (state->cscd_state != CSCD_SAVED) { 167462306a36Sopenharmony_ci u32 lock; 167562306a36Sopenharmony_ci status = DRX_GetLockStatus(state, &lock); 167662306a36Sopenharmony_ci if (status < 0) 167762306a36Sopenharmony_ci break; 167862306a36Sopenharmony_ci } 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci status = StopOC(state); 168162306a36Sopenharmony_ci if (status < 0) 168262306a36Sopenharmony_ci break; 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci state->drxd_state = DRXD_STOPPED; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci status = ConfigureMPEGOutput(state, 0); 168762306a36Sopenharmony_ci if (status < 0) 168862306a36Sopenharmony_ci break; 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci if (state->type_A) { 169162306a36Sopenharmony_ci /* Stop relevant processors off the device */ 169262306a36Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000); 169362306a36Sopenharmony_ci if (status < 0) 169462306a36Sopenharmony_ci break; 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 169762306a36Sopenharmony_ci if (status < 0) 169862306a36Sopenharmony_ci break; 169962306a36Sopenharmony_ci status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 170062306a36Sopenharmony_ci if (status < 0) 170162306a36Sopenharmony_ci break; 170262306a36Sopenharmony_ci } else { 170362306a36Sopenharmony_ci /* Stop all processors except HI & CC & FE */ 170462306a36Sopenharmony_ci status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 170562306a36Sopenharmony_ci if (status < 0) 170662306a36Sopenharmony_ci break; 170762306a36Sopenharmony_ci status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 170862306a36Sopenharmony_ci if (status < 0) 170962306a36Sopenharmony_ci break; 171062306a36Sopenharmony_ci status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 171162306a36Sopenharmony_ci if (status < 0) 171262306a36Sopenharmony_ci break; 171362306a36Sopenharmony_ci status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 171462306a36Sopenharmony_ci if (status < 0) 171562306a36Sopenharmony_ci break; 171662306a36Sopenharmony_ci status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 171762306a36Sopenharmony_ci if (status < 0) 171862306a36Sopenharmony_ci break; 171962306a36Sopenharmony_ci status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 172062306a36Sopenharmony_ci if (status < 0) 172162306a36Sopenharmony_ci break; 172262306a36Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0); 172362306a36Sopenharmony_ci if (status < 0) 172462306a36Sopenharmony_ci break; 172562306a36Sopenharmony_ci } 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci } while (0); 172862306a36Sopenharmony_ci return status; 172962306a36Sopenharmony_ci} 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci#if 0 /* Currently unused */ 173262306a36Sopenharmony_cistatic int SetOperationMode(struct drxd_state *state, int oMode) 173362306a36Sopenharmony_ci{ 173462306a36Sopenharmony_ci int status; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci do { 173762306a36Sopenharmony_ci if (state->drxd_state != DRXD_STOPPED) { 173862306a36Sopenharmony_ci status = -1; 173962306a36Sopenharmony_ci break; 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci if (oMode == state->operation_mode) { 174362306a36Sopenharmony_ci status = 0; 174462306a36Sopenharmony_ci break; 174562306a36Sopenharmony_ci } 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci if (oMode != OM_Default && !state->diversity) { 174862306a36Sopenharmony_ci status = -1; 174962306a36Sopenharmony_ci break; 175062306a36Sopenharmony_ci } 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci switch (oMode) { 175362306a36Sopenharmony_ci case OM_DVBT_Diversity_Front: 175462306a36Sopenharmony_ci status = WriteTable(state, state->m_InitDiversityFront); 175562306a36Sopenharmony_ci break; 175662306a36Sopenharmony_ci case OM_DVBT_Diversity_End: 175762306a36Sopenharmony_ci status = WriteTable(state, state->m_InitDiversityEnd); 175862306a36Sopenharmony_ci break; 175962306a36Sopenharmony_ci case OM_Default: 176062306a36Sopenharmony_ci /* We need to check how to 176162306a36Sopenharmony_ci get DRXD out of diversity */ 176262306a36Sopenharmony_ci default: 176362306a36Sopenharmony_ci status = WriteTable(state, state->m_DisableDiversity); 176462306a36Sopenharmony_ci break; 176562306a36Sopenharmony_ci } 176662306a36Sopenharmony_ci } while (0); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci if (!status) 176962306a36Sopenharmony_ci state->operation_mode = oMode; 177062306a36Sopenharmony_ci return status; 177162306a36Sopenharmony_ci} 177262306a36Sopenharmony_ci#endif 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_cistatic int StartDiversity(struct drxd_state *state) 177562306a36Sopenharmony_ci{ 177662306a36Sopenharmony_ci int status = 0; 177762306a36Sopenharmony_ci u16 rcControl; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci do { 178062306a36Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front) { 178162306a36Sopenharmony_ci status = WriteTable(state, state->m_StartDiversityFront); 178262306a36Sopenharmony_ci if (status < 0) 178362306a36Sopenharmony_ci break; 178462306a36Sopenharmony_ci } else if (state->operation_mode == OM_DVBT_Diversity_End) { 178562306a36Sopenharmony_ci status = WriteTable(state, state->m_StartDiversityEnd); 178662306a36Sopenharmony_ci if (status < 0) 178762306a36Sopenharmony_ci break; 178862306a36Sopenharmony_ci if (state->props.bandwidth_hz == 8000000) { 178962306a36Sopenharmony_ci status = WriteTable(state, state->m_DiversityDelay8MHZ); 179062306a36Sopenharmony_ci if (status < 0) 179162306a36Sopenharmony_ci break; 179262306a36Sopenharmony_ci } else { 179362306a36Sopenharmony_ci status = WriteTable(state, state->m_DiversityDelay6MHZ); 179462306a36Sopenharmony_ci if (status < 0) 179562306a36Sopenharmony_ci break; 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0); 179962306a36Sopenharmony_ci if (status < 0) 180062306a36Sopenharmony_ci break; 180162306a36Sopenharmony_ci rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M); 180262306a36Sopenharmony_ci rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON | 180362306a36Sopenharmony_ci /* combining enabled */ 180462306a36Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | 180562306a36Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_PASS_A_CC | 180662306a36Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC; 180762306a36Sopenharmony_ci status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0); 180862306a36Sopenharmony_ci if (status < 0) 180962306a36Sopenharmony_ci break; 181062306a36Sopenharmony_ci } 181162306a36Sopenharmony_ci } while (0); 181262306a36Sopenharmony_ci return status; 181362306a36Sopenharmony_ci} 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_cistatic int SetFrequencyShift(struct drxd_state *state, 181662306a36Sopenharmony_ci u32 offsetFreq, int channelMirrored) 181762306a36Sopenharmony_ci{ 181862306a36Sopenharmony_ci int negativeShift = (state->tuner_mirrors == channelMirrored); 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci /* Handle all mirroring 182162306a36Sopenharmony_ci * 182262306a36Sopenharmony_ci * Note: ADC mirroring (aliasing) is implictly handled by limiting 182362306a36Sopenharmony_ci * feFsRegAddInc to 28 bits below 182462306a36Sopenharmony_ci * (if the result before masking is more than 28 bits, this means 182562306a36Sopenharmony_ci * that the ADC is mirroring. 182662306a36Sopenharmony_ci * The masking is in fact the aliasing of the ADC) 182762306a36Sopenharmony_ci * 182862306a36Sopenharmony_ci */ 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci /* Compute register value, unsigned computation */ 183162306a36Sopenharmony_ci state->fe_fs_add_incr = MulDiv32(state->intermediate_freq + 183262306a36Sopenharmony_ci offsetFreq, 183362306a36Sopenharmony_ci 1 << 28, state->sys_clock_freq); 183462306a36Sopenharmony_ci /* Remove integer part */ 183562306a36Sopenharmony_ci state->fe_fs_add_incr &= 0x0FFFFFFFL; 183662306a36Sopenharmony_ci if (negativeShift) 183762306a36Sopenharmony_ci state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr); 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci /* Save the frequency shift without tunerOffset compensation 184062306a36Sopenharmony_ci for CtrlGetChannel. */ 184162306a36Sopenharmony_ci state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq, 184262306a36Sopenharmony_ci 1 << 28, state->sys_clock_freq); 184362306a36Sopenharmony_ci /* Remove integer part */ 184462306a36Sopenharmony_ci state->org_fe_fs_add_incr &= 0x0FFFFFFFL; 184562306a36Sopenharmony_ci if (negativeShift) 184662306a36Sopenharmony_ci state->org_fe_fs_add_incr = ((1L << 28) - 184762306a36Sopenharmony_ci state->org_fe_fs_add_incr); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci return Write32(state, FE_FS_REG_ADD_INC_LOP__A, 185062306a36Sopenharmony_ci state->fe_fs_add_incr, 0); 185162306a36Sopenharmony_ci} 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_cistatic int SetCfgNoiseCalibration(struct drxd_state *state, 185462306a36Sopenharmony_ci struct SNoiseCal *noiseCal) 185562306a36Sopenharmony_ci{ 185662306a36Sopenharmony_ci u16 beOptEna; 185762306a36Sopenharmony_ci int status = 0; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci do { 186062306a36Sopenharmony_ci status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0); 186162306a36Sopenharmony_ci if (status < 0) 186262306a36Sopenharmony_ci break; 186362306a36Sopenharmony_ci if (noiseCal->cpOpt) { 186462306a36Sopenharmony_ci beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); 186562306a36Sopenharmony_ci } else { 186662306a36Sopenharmony_ci beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); 186762306a36Sopenharmony_ci status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0); 186862306a36Sopenharmony_ci if (status < 0) 186962306a36Sopenharmony_ci break; 187062306a36Sopenharmony_ci } 187162306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0); 187262306a36Sopenharmony_ci if (status < 0) 187362306a36Sopenharmony_ci break; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci if (!state->type_A) { 187662306a36Sopenharmony_ci status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0); 187762306a36Sopenharmony_ci if (status < 0) 187862306a36Sopenharmony_ci break; 187962306a36Sopenharmony_ci status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0); 188062306a36Sopenharmony_ci if (status < 0) 188162306a36Sopenharmony_ci break; 188262306a36Sopenharmony_ci } 188362306a36Sopenharmony_ci } while (0); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci return status; 188662306a36Sopenharmony_ci} 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_cistatic int DRX_Start(struct drxd_state *state, s32 off) 188962306a36Sopenharmony_ci{ 189062306a36Sopenharmony_ci struct dtv_frontend_properties *p = &state->props; 189162306a36Sopenharmony_ci int status; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci u16 transmissionParams = 0; 189462306a36Sopenharmony_ci u16 operationMode = 0; 189562306a36Sopenharmony_ci u16 qpskTdTpsPwr = 0; 189662306a36Sopenharmony_ci u16 qam16TdTpsPwr = 0; 189762306a36Sopenharmony_ci u16 qam64TdTpsPwr = 0; 189862306a36Sopenharmony_ci u32 feIfIncr = 0; 189962306a36Sopenharmony_ci u32 bandwidth = 0; 190062306a36Sopenharmony_ci int mirrorFreqSpect; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci u16 qpskSnCeGain = 0; 190362306a36Sopenharmony_ci u16 qam16SnCeGain = 0; 190462306a36Sopenharmony_ci u16 qam64SnCeGain = 0; 190562306a36Sopenharmony_ci u16 qpskIsGainMan = 0; 190662306a36Sopenharmony_ci u16 qam16IsGainMan = 0; 190762306a36Sopenharmony_ci u16 qam64IsGainMan = 0; 190862306a36Sopenharmony_ci u16 qpskIsGainExp = 0; 190962306a36Sopenharmony_ci u16 qam16IsGainExp = 0; 191062306a36Sopenharmony_ci u16 qam64IsGainExp = 0; 191162306a36Sopenharmony_ci u16 bandwidthParam = 0; 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci if (off < 0) 191462306a36Sopenharmony_ci off = (off - 500) / 1000; 191562306a36Sopenharmony_ci else 191662306a36Sopenharmony_ci off = (off + 500) / 1000; 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci do { 191962306a36Sopenharmony_ci if (state->drxd_state != DRXD_STOPPED) 192062306a36Sopenharmony_ci return -1; 192162306a36Sopenharmony_ci status = ResetECOD(state); 192262306a36Sopenharmony_ci if (status < 0) 192362306a36Sopenharmony_ci break; 192462306a36Sopenharmony_ci if (state->type_A) { 192562306a36Sopenharmony_ci status = InitSC(state); 192662306a36Sopenharmony_ci if (status < 0) 192762306a36Sopenharmony_ci break; 192862306a36Sopenharmony_ci } else { 192962306a36Sopenharmony_ci status = InitFT(state); 193062306a36Sopenharmony_ci if (status < 0) 193162306a36Sopenharmony_ci break; 193262306a36Sopenharmony_ci status = InitCP(state); 193362306a36Sopenharmony_ci if (status < 0) 193462306a36Sopenharmony_ci break; 193562306a36Sopenharmony_ci status = InitCE(state); 193662306a36Sopenharmony_ci if (status < 0) 193762306a36Sopenharmony_ci break; 193862306a36Sopenharmony_ci status = InitEQ(state); 193962306a36Sopenharmony_ci if (status < 0) 194062306a36Sopenharmony_ci break; 194162306a36Sopenharmony_ci status = InitSC(state); 194262306a36Sopenharmony_ci if (status < 0) 194362306a36Sopenharmony_ci break; 194462306a36Sopenharmony_ci } 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci /* Restore current IF & RF AGC settings */ 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci status = SetCfgIfAgc(state, &state->if_agc_cfg); 194962306a36Sopenharmony_ci if (status < 0) 195062306a36Sopenharmony_ci break; 195162306a36Sopenharmony_ci status = SetCfgRfAgc(state, &state->rf_agc_cfg); 195262306a36Sopenharmony_ci if (status < 0) 195362306a36Sopenharmony_ci break; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci mirrorFreqSpect = (state->props.inversion == INVERSION_ON); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci switch (p->transmission_mode) { 195862306a36Sopenharmony_ci default: /* Not set, detect it automatically */ 195962306a36Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; 196062306a36Sopenharmony_ci fallthrough; /* try first guess DRX_FFTMODE_8K */ 196162306a36Sopenharmony_ci case TRANSMISSION_MODE_8K: 196262306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; 196362306a36Sopenharmony_ci if (state->type_A) { 196462306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000); 196562306a36Sopenharmony_ci if (status < 0) 196662306a36Sopenharmony_ci break; 196762306a36Sopenharmony_ci qpskSnCeGain = 99; 196862306a36Sopenharmony_ci qam16SnCeGain = 83; 196962306a36Sopenharmony_ci qam64SnCeGain = 67; 197062306a36Sopenharmony_ci } 197162306a36Sopenharmony_ci break; 197262306a36Sopenharmony_ci case TRANSMISSION_MODE_2K: 197362306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K; 197462306a36Sopenharmony_ci if (state->type_A) { 197562306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000); 197662306a36Sopenharmony_ci if (status < 0) 197762306a36Sopenharmony_ci break; 197862306a36Sopenharmony_ci qpskSnCeGain = 97; 197962306a36Sopenharmony_ci qam16SnCeGain = 71; 198062306a36Sopenharmony_ci qam64SnCeGain = 65; 198162306a36Sopenharmony_ci } 198262306a36Sopenharmony_ci break; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci switch (p->guard_interval) { 198662306a36Sopenharmony_ci case GUARD_INTERVAL_1_4: 198762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; 198862306a36Sopenharmony_ci break; 198962306a36Sopenharmony_ci case GUARD_INTERVAL_1_8: 199062306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8; 199162306a36Sopenharmony_ci break; 199262306a36Sopenharmony_ci case GUARD_INTERVAL_1_16: 199362306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16; 199462306a36Sopenharmony_ci break; 199562306a36Sopenharmony_ci case GUARD_INTERVAL_1_32: 199662306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32; 199762306a36Sopenharmony_ci break; 199862306a36Sopenharmony_ci default: /* Not set, detect it automatically */ 199962306a36Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M; 200062306a36Sopenharmony_ci /* try first guess 1/4 */ 200162306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; 200262306a36Sopenharmony_ci break; 200362306a36Sopenharmony_ci } 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci switch (p->hierarchy) { 200662306a36Sopenharmony_ci case HIERARCHY_1: 200762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1; 200862306a36Sopenharmony_ci if (state->type_A) { 200962306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000); 201062306a36Sopenharmony_ci if (status < 0) 201162306a36Sopenharmony_ci break; 201262306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000); 201362306a36Sopenharmony_ci if (status < 0) 201462306a36Sopenharmony_ci break; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 201762306a36Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1; 201862306a36Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1; 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci qpskIsGainMan = 202162306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 202262306a36Sopenharmony_ci qam16IsGainMan = 202362306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; 202462306a36Sopenharmony_ci qam64IsGainMan = 202562306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci qpskIsGainExp = 202862306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 202962306a36Sopenharmony_ci qam16IsGainExp = 203062306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; 203162306a36Sopenharmony_ci qam64IsGainExp = 203262306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci break; 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci case HIERARCHY_2: 203762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2; 203862306a36Sopenharmony_ci if (state->type_A) { 203962306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000); 204062306a36Sopenharmony_ci if (status < 0) 204162306a36Sopenharmony_ci break; 204262306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000); 204362306a36Sopenharmony_ci if (status < 0) 204462306a36Sopenharmony_ci break; 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 204762306a36Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2; 204862306a36Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2; 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci qpskIsGainMan = 205162306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 205262306a36Sopenharmony_ci qam16IsGainMan = 205362306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE; 205462306a36Sopenharmony_ci qam64IsGainMan = 205562306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE; 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci qpskIsGainExp = 205862306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 205962306a36Sopenharmony_ci qam16IsGainExp = 206062306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE; 206162306a36Sopenharmony_ci qam64IsGainExp = 206262306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci break; 206562306a36Sopenharmony_ci case HIERARCHY_4: 206662306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4; 206762306a36Sopenharmony_ci if (state->type_A) { 206862306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000); 206962306a36Sopenharmony_ci if (status < 0) 207062306a36Sopenharmony_ci break; 207162306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000); 207262306a36Sopenharmony_ci if (status < 0) 207362306a36Sopenharmony_ci break; 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 207662306a36Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4; 207762306a36Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4; 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci qpskIsGainMan = 208062306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 208162306a36Sopenharmony_ci qam16IsGainMan = 208262306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE; 208362306a36Sopenharmony_ci qam64IsGainMan = 208462306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE; 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci qpskIsGainExp = 208762306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 208862306a36Sopenharmony_ci qam16IsGainExp = 208962306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE; 209062306a36Sopenharmony_ci qam64IsGainExp = 209162306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE; 209262306a36Sopenharmony_ci } 209362306a36Sopenharmony_ci break; 209462306a36Sopenharmony_ci case HIERARCHY_AUTO: 209562306a36Sopenharmony_ci default: 209662306a36Sopenharmony_ci /* Not set, detect it automatically, start with none */ 209762306a36Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_HIER__M; 209862306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO; 209962306a36Sopenharmony_ci if (state->type_A) { 210062306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000); 210162306a36Sopenharmony_ci if (status < 0) 210262306a36Sopenharmony_ci break; 210362306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000); 210462306a36Sopenharmony_ci if (status < 0) 210562306a36Sopenharmony_ci break; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK; 210862306a36Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN; 210962306a36Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN; 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci qpskIsGainMan = 211262306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE; 211362306a36Sopenharmony_ci qam16IsGainMan = 211462306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; 211562306a36Sopenharmony_ci qam64IsGainMan = 211662306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci qpskIsGainExp = 211962306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE; 212062306a36Sopenharmony_ci qam16IsGainExp = 212162306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; 212262306a36Sopenharmony_ci qam64IsGainExp = 212362306a36Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; 212462306a36Sopenharmony_ci } 212562306a36Sopenharmony_ci break; 212662306a36Sopenharmony_ci } 212762306a36Sopenharmony_ci if (status < 0) 212862306a36Sopenharmony_ci break; 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci switch (p->modulation) { 213162306a36Sopenharmony_ci default: 213262306a36Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; 213362306a36Sopenharmony_ci fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */ 213462306a36Sopenharmony_ci case QAM_64: 213562306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; 213662306a36Sopenharmony_ci if (state->type_A) { 213762306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000); 213862306a36Sopenharmony_ci if (status < 0) 213962306a36Sopenharmony_ci break; 214062306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000); 214162306a36Sopenharmony_ci if (status < 0) 214262306a36Sopenharmony_ci break; 214362306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000); 214462306a36Sopenharmony_ci if (status < 0) 214562306a36Sopenharmony_ci break; 214662306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000); 214762306a36Sopenharmony_ci if (status < 0) 214862306a36Sopenharmony_ci break; 214962306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000); 215062306a36Sopenharmony_ci if (status < 0) 215162306a36Sopenharmony_ci break; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000); 215462306a36Sopenharmony_ci if (status < 0) 215562306a36Sopenharmony_ci break; 215662306a36Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000); 215762306a36Sopenharmony_ci if (status < 0) 215862306a36Sopenharmony_ci break; 215962306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000); 216062306a36Sopenharmony_ci if (status < 0) 216162306a36Sopenharmony_ci break; 216262306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000); 216362306a36Sopenharmony_ci if (status < 0) 216462306a36Sopenharmony_ci break; 216562306a36Sopenharmony_ci } 216662306a36Sopenharmony_ci break; 216762306a36Sopenharmony_ci case QPSK: 216862306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK; 216962306a36Sopenharmony_ci if (state->type_A) { 217062306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000); 217162306a36Sopenharmony_ci if (status < 0) 217262306a36Sopenharmony_ci break; 217362306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000); 217462306a36Sopenharmony_ci if (status < 0) 217562306a36Sopenharmony_ci break; 217662306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); 217762306a36Sopenharmony_ci if (status < 0) 217862306a36Sopenharmony_ci break; 217962306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000); 218062306a36Sopenharmony_ci if (status < 0) 218162306a36Sopenharmony_ci break; 218262306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); 218362306a36Sopenharmony_ci if (status < 0) 218462306a36Sopenharmony_ci break; 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000); 218762306a36Sopenharmony_ci if (status < 0) 218862306a36Sopenharmony_ci break; 218962306a36Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000); 219062306a36Sopenharmony_ci if (status < 0) 219162306a36Sopenharmony_ci break; 219262306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000); 219362306a36Sopenharmony_ci if (status < 0) 219462306a36Sopenharmony_ci break; 219562306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000); 219662306a36Sopenharmony_ci if (status < 0) 219762306a36Sopenharmony_ci break; 219862306a36Sopenharmony_ci } 219962306a36Sopenharmony_ci break; 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ci case QAM_16: 220262306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16; 220362306a36Sopenharmony_ci if (state->type_A) { 220462306a36Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000); 220562306a36Sopenharmony_ci if (status < 0) 220662306a36Sopenharmony_ci break; 220762306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000); 220862306a36Sopenharmony_ci if (status < 0) 220962306a36Sopenharmony_ci break; 221062306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); 221162306a36Sopenharmony_ci if (status < 0) 221262306a36Sopenharmony_ci break; 221362306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000); 221462306a36Sopenharmony_ci if (status < 0) 221562306a36Sopenharmony_ci break; 221662306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); 221762306a36Sopenharmony_ci if (status < 0) 221862306a36Sopenharmony_ci break; 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000); 222162306a36Sopenharmony_ci if (status < 0) 222262306a36Sopenharmony_ci break; 222362306a36Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000); 222462306a36Sopenharmony_ci if (status < 0) 222562306a36Sopenharmony_ci break; 222662306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000); 222762306a36Sopenharmony_ci if (status < 0) 222862306a36Sopenharmony_ci break; 222962306a36Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000); 223062306a36Sopenharmony_ci if (status < 0) 223162306a36Sopenharmony_ci break; 223262306a36Sopenharmony_ci } 223362306a36Sopenharmony_ci break; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci } 223662306a36Sopenharmony_ci if (status < 0) 223762306a36Sopenharmony_ci break; 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci switch (DRX_CHANNEL_HIGH) { 224062306a36Sopenharmony_ci default: 224162306a36Sopenharmony_ci case DRX_CHANNEL_AUTO: 224262306a36Sopenharmony_ci case DRX_CHANNEL_LOW: 224362306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO; 224462306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000); 224562306a36Sopenharmony_ci break; 224662306a36Sopenharmony_ci case DRX_CHANNEL_HIGH: 224762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI; 224862306a36Sopenharmony_ci status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000); 224962306a36Sopenharmony_ci break; 225062306a36Sopenharmony_ci } 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci switch (p->code_rate_HP) { 225362306a36Sopenharmony_ci case FEC_1_2: 225462306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2; 225562306a36Sopenharmony_ci if (state->type_A) 225662306a36Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000); 225762306a36Sopenharmony_ci break; 225862306a36Sopenharmony_ci default: 225962306a36Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; 226062306a36Sopenharmony_ci fallthrough; 226162306a36Sopenharmony_ci case FEC_2_3: 226262306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; 226362306a36Sopenharmony_ci if (state->type_A) 226462306a36Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000); 226562306a36Sopenharmony_ci break; 226662306a36Sopenharmony_ci case FEC_3_4: 226762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4; 226862306a36Sopenharmony_ci if (state->type_A) 226962306a36Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000); 227062306a36Sopenharmony_ci break; 227162306a36Sopenharmony_ci case FEC_5_6: 227262306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6; 227362306a36Sopenharmony_ci if (state->type_A) 227462306a36Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000); 227562306a36Sopenharmony_ci break; 227662306a36Sopenharmony_ci case FEC_7_8: 227762306a36Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8; 227862306a36Sopenharmony_ci if (state->type_A) 227962306a36Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000); 228062306a36Sopenharmony_ci break; 228162306a36Sopenharmony_ci } 228262306a36Sopenharmony_ci if (status < 0) 228362306a36Sopenharmony_ci break; 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci /* First determine real bandwidth (Hz) */ 228662306a36Sopenharmony_ci /* Also set delay for impulse noise cruncher (only A2) */ 228762306a36Sopenharmony_ci /* Also set parameters for EC_OC fix, note 228862306a36Sopenharmony_ci EC_OC_REG_TMD_HIL_MAR is changed 228962306a36Sopenharmony_ci by SC for fix for some 8K,1/8 guard but is restored by 229062306a36Sopenharmony_ci InitEC and ResetEC 229162306a36Sopenharmony_ci functions */ 229262306a36Sopenharmony_ci switch (p->bandwidth_hz) { 229362306a36Sopenharmony_ci case 0: 229462306a36Sopenharmony_ci p->bandwidth_hz = 8000000; 229562306a36Sopenharmony_ci fallthrough; 229662306a36Sopenharmony_ci case 8000000: 229762306a36Sopenharmony_ci /* (64/7)*(8/8)*1000000 */ 229862306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; 229962306a36Sopenharmony_ci 230062306a36Sopenharmony_ci bandwidthParam = 0; 230162306a36Sopenharmony_ci status = Write16(state, 230262306a36Sopenharmony_ci FE_AG_REG_IND_DEL__A, 50, 0x0000); 230362306a36Sopenharmony_ci break; 230462306a36Sopenharmony_ci case 7000000: 230562306a36Sopenharmony_ci /* (64/7)*(7/8)*1000000 */ 230662306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; 230762306a36Sopenharmony_ci bandwidthParam = 0x4807; /*binary:0100 1000 0000 0111 */ 230862306a36Sopenharmony_ci status = Write16(state, 230962306a36Sopenharmony_ci FE_AG_REG_IND_DEL__A, 59, 0x0000); 231062306a36Sopenharmony_ci break; 231162306a36Sopenharmony_ci case 6000000: 231262306a36Sopenharmony_ci /* (64/7)*(6/8)*1000000 */ 231362306a36Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; 231462306a36Sopenharmony_ci bandwidthParam = 0x0F07; /*binary: 0000 1111 0000 0111 */ 231562306a36Sopenharmony_ci status = Write16(state, 231662306a36Sopenharmony_ci FE_AG_REG_IND_DEL__A, 71, 0x0000); 231762306a36Sopenharmony_ci break; 231862306a36Sopenharmony_ci default: 231962306a36Sopenharmony_ci status = -EINVAL; 232062306a36Sopenharmony_ci } 232162306a36Sopenharmony_ci if (status < 0) 232262306a36Sopenharmony_ci break; 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000); 232562306a36Sopenharmony_ci if (status < 0) 232662306a36Sopenharmony_ci break; 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci { 232962306a36Sopenharmony_ci u16 sc_config; 233062306a36Sopenharmony_ci status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0); 233162306a36Sopenharmony_ci if (status < 0) 233262306a36Sopenharmony_ci break; 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci /* enable SLAVE mode in 2k 1/32 to 233562306a36Sopenharmony_ci prevent timing change glitches */ 233662306a36Sopenharmony_ci if ((p->transmission_mode == TRANSMISSION_MODE_2K) && 233762306a36Sopenharmony_ci (p->guard_interval == GUARD_INTERVAL_1_32)) { 233862306a36Sopenharmony_ci /* enable slave */ 233962306a36Sopenharmony_ci sc_config |= SC_RA_RAM_CONFIG_SLAVE__M; 234062306a36Sopenharmony_ci } else { 234162306a36Sopenharmony_ci /* disable slave */ 234262306a36Sopenharmony_ci sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M; 234362306a36Sopenharmony_ci } 234462306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0); 234562306a36Sopenharmony_ci if (status < 0) 234662306a36Sopenharmony_ci break; 234762306a36Sopenharmony_ci } 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_ci status = SetCfgNoiseCalibration(state, &state->noise_cal); 235062306a36Sopenharmony_ci if (status < 0) 235162306a36Sopenharmony_ci break; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci if (state->cscd_state == CSCD_INIT) { 235462306a36Sopenharmony_ci /* switch on SRMM scan in SC */ 235562306a36Sopenharmony_ci status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000); 235662306a36Sopenharmony_ci if (status < 0) 235762306a36Sopenharmony_ci break; 235862306a36Sopenharmony_ci/* CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/ 235962306a36Sopenharmony_ci state->cscd_state = CSCD_SET; 236062306a36Sopenharmony_ci } 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci /* Now compute FE_IF_REG_INCR */ 236362306a36Sopenharmony_ci /*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) => 236462306a36Sopenharmony_ci ((SysFreq / BandWidth) * (2^21) ) - (2^23) */ 236562306a36Sopenharmony_ci feIfIncr = MulDiv32(state->sys_clock_freq * 1000, 236662306a36Sopenharmony_ci (1ULL << 21), bandwidth) - (1 << 23); 236762306a36Sopenharmony_ci status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000); 236862306a36Sopenharmony_ci if (status < 0) 236962306a36Sopenharmony_ci break; 237062306a36Sopenharmony_ci status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000); 237162306a36Sopenharmony_ci if (status < 0) 237262306a36Sopenharmony_ci break; 237362306a36Sopenharmony_ci /* Bandwidth setting done */ 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci /* Mirror & frequency offset */ 237662306a36Sopenharmony_ci SetFrequencyShift(state, off, mirrorFreqSpect); 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci /* Start SC, write channel settings to SC */ 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci /* Enable SC after setting all other parameters */ 238162306a36Sopenharmony_ci status = Write16(state, SC_COMM_STATE__A, 0, 0x0000); 238262306a36Sopenharmony_ci if (status < 0) 238362306a36Sopenharmony_ci break; 238462306a36Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000); 238562306a36Sopenharmony_ci if (status < 0) 238662306a36Sopenharmony_ci break; 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci /* Write SC parameter registers, operation mode */ 238962306a36Sopenharmony_ci#if 1 239062306a36Sopenharmony_ci operationMode = (SC_RA_RAM_OP_AUTO_MODE__M | 239162306a36Sopenharmony_ci SC_RA_RAM_OP_AUTO_GUARD__M | 239262306a36Sopenharmony_ci SC_RA_RAM_OP_AUTO_CONST__M | 239362306a36Sopenharmony_ci SC_RA_RAM_OP_AUTO_HIER__M | 239462306a36Sopenharmony_ci SC_RA_RAM_OP_AUTO_RATE__M); 239562306a36Sopenharmony_ci#endif 239662306a36Sopenharmony_ci status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode); 239762306a36Sopenharmony_ci if (status < 0) 239862306a36Sopenharmony_ci break; 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci /* Start correct processes to get in lock */ 240162306a36Sopenharmony_ci status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN); 240262306a36Sopenharmony_ci if (status < 0) 240362306a36Sopenharmony_ci break; 240462306a36Sopenharmony_ci 240562306a36Sopenharmony_ci status = StartOC(state); 240662306a36Sopenharmony_ci if (status < 0) 240762306a36Sopenharmony_ci break; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (state->operation_mode != OM_Default) { 241062306a36Sopenharmony_ci status = StartDiversity(state); 241162306a36Sopenharmony_ci if (status < 0) 241262306a36Sopenharmony_ci break; 241362306a36Sopenharmony_ci } 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_ci state->drxd_state = DRXD_STARTED; 241662306a36Sopenharmony_ci } while (0); 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci return status; 241962306a36Sopenharmony_ci} 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_cistatic int CDRXD(struct drxd_state *state, u32 IntermediateFrequency) 242262306a36Sopenharmony_ci{ 242362306a36Sopenharmony_ci u32 ulRfAgcOutputLevel = 0xffffffff; 242462306a36Sopenharmony_ci u32 ulRfAgcSettleLevel = 528; /* Optimum value for MT2060 */ 242562306a36Sopenharmony_ci u32 ulRfAgcMinLevel = 0; /* Currently unused */ 242662306a36Sopenharmony_ci u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX; /* Currently unused */ 242762306a36Sopenharmony_ci u32 ulRfAgcSpeed = 0; /* Currently unused */ 242862306a36Sopenharmony_ci u32 ulRfAgcMode = 0; /*2; Off */ 242962306a36Sopenharmony_ci u32 ulRfAgcR1 = 820; 243062306a36Sopenharmony_ci u32 ulRfAgcR2 = 2200; 243162306a36Sopenharmony_ci u32 ulRfAgcR3 = 150; 243262306a36Sopenharmony_ci u32 ulIfAgcMode = 0; /* Auto */ 243362306a36Sopenharmony_ci u32 ulIfAgcOutputLevel = 0xffffffff; 243462306a36Sopenharmony_ci u32 ulIfAgcSettleLevel = 0xffffffff; 243562306a36Sopenharmony_ci u32 ulIfAgcMinLevel = 0xffffffff; 243662306a36Sopenharmony_ci u32 ulIfAgcMaxLevel = 0xffffffff; 243762306a36Sopenharmony_ci u32 ulIfAgcSpeed = 0xffffffff; 243862306a36Sopenharmony_ci u32 ulIfAgcR1 = 820; 243962306a36Sopenharmony_ci u32 ulIfAgcR2 = 2200; 244062306a36Sopenharmony_ci u32 ulIfAgcR3 = 150; 244162306a36Sopenharmony_ci u32 ulClock = state->config.clock; 244262306a36Sopenharmony_ci u32 ulSerialMode = 0; 244362306a36Sopenharmony_ci u32 ulEcOcRegOcModeLop = 4; /* Dynamic DTO source */ 244462306a36Sopenharmony_ci u32 ulHiI2cDelay = HI_I2C_DELAY; 244562306a36Sopenharmony_ci u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY; 244662306a36Sopenharmony_ci u32 ulHiI2cPatch = 0; 244762306a36Sopenharmony_ci u32 ulEnvironment = APPENV_PORTABLE; 244862306a36Sopenharmony_ci u32 ulEnvironmentDiversity = APPENV_MOBILE; 244962306a36Sopenharmony_ci u32 ulIFFilter = IFFILTER_SAW; 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 245262306a36Sopenharmony_ci state->if_agc_cfg.outputLevel = 0; 245362306a36Sopenharmony_ci state->if_agc_cfg.settleLevel = 140; 245462306a36Sopenharmony_ci state->if_agc_cfg.minOutputLevel = 0; 245562306a36Sopenharmony_ci state->if_agc_cfg.maxOutputLevel = 1023; 245662306a36Sopenharmony_ci state->if_agc_cfg.speed = 904; 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { 245962306a36Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_USER; 246062306a36Sopenharmony_ci state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel); 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci if (ulIfAgcMode == 0 && 246462306a36Sopenharmony_ci ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX && 246562306a36Sopenharmony_ci ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX && 246662306a36Sopenharmony_ci ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX && 246762306a36Sopenharmony_ci ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) { 246862306a36Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 246962306a36Sopenharmony_ci state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel); 247062306a36Sopenharmony_ci state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel); 247162306a36Sopenharmony_ci state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel); 247262306a36Sopenharmony_ci state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed); 247362306a36Sopenharmony_ci } 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci state->if_agc_cfg.R1 = (u16) (ulIfAgcR1); 247662306a36Sopenharmony_ci state->if_agc_cfg.R2 = (u16) (ulIfAgcR2); 247762306a36Sopenharmony_ci state->if_agc_cfg.R3 = (u16) (ulIfAgcR3); 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1); 248062306a36Sopenharmony_ci state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2); 248162306a36Sopenharmony_ci state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3); 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 248462306a36Sopenharmony_ci /* rest of the RFAgcCfg structure currently unused */ 248562306a36Sopenharmony_ci if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { 248662306a36Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER; 248762306a36Sopenharmony_ci state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel); 248862306a36Sopenharmony_ci } 248962306a36Sopenharmony_ci 249062306a36Sopenharmony_ci if (ulRfAgcMode == 0 && 249162306a36Sopenharmony_ci ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX && 249262306a36Sopenharmony_ci ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX && 249362306a36Sopenharmony_ci ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX && 249462306a36Sopenharmony_ci ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) { 249562306a36Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 249662306a36Sopenharmony_ci state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel); 249762306a36Sopenharmony_ci state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel); 249862306a36Sopenharmony_ci state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel); 249962306a36Sopenharmony_ci state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed); 250062306a36Sopenharmony_ci } 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci if (ulRfAgcMode == 2) 250362306a36Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF; 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci if (ulEnvironment <= 2) 250662306a36Sopenharmony_ci state->app_env_default = (enum app_env) 250762306a36Sopenharmony_ci (ulEnvironment); 250862306a36Sopenharmony_ci if (ulEnvironmentDiversity <= 2) 250962306a36Sopenharmony_ci state->app_env_diversity = (enum app_env) 251062306a36Sopenharmony_ci (ulEnvironmentDiversity); 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci if (ulIFFilter == IFFILTER_DISCRETE) { 251362306a36Sopenharmony_ci /* discrete filter */ 251462306a36Sopenharmony_ci state->noise_cal.cpOpt = 0; 251562306a36Sopenharmony_ci state->noise_cal.cpNexpOfs = 40; 251662306a36Sopenharmony_ci state->noise_cal.tdCal2k = -40; 251762306a36Sopenharmony_ci state->noise_cal.tdCal8k = -24; 251862306a36Sopenharmony_ci } else { 251962306a36Sopenharmony_ci /* SAW filter */ 252062306a36Sopenharmony_ci state->noise_cal.cpOpt = 1; 252162306a36Sopenharmony_ci state->noise_cal.cpNexpOfs = 0; 252262306a36Sopenharmony_ci state->noise_cal.tdCal2k = -21; 252362306a36Sopenharmony_ci state->noise_cal.tdCal8k = -24; 252462306a36Sopenharmony_ci } 252562306a36Sopenharmony_ci state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop); 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci state->chip_adr = (state->config.demod_address << 1) | 1; 252862306a36Sopenharmony_ci switch (ulHiI2cPatch) { 252962306a36Sopenharmony_ci case 1: 253062306a36Sopenharmony_ci state->m_HiI2cPatch = DRXD_HiI2cPatch_1; 253162306a36Sopenharmony_ci break; 253262306a36Sopenharmony_ci case 3: 253362306a36Sopenharmony_ci state->m_HiI2cPatch = DRXD_HiI2cPatch_3; 253462306a36Sopenharmony_ci break; 253562306a36Sopenharmony_ci default: 253662306a36Sopenharmony_ci state->m_HiI2cPatch = NULL; 253762306a36Sopenharmony_ci } 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci /* modify tuner and clock attributes */ 254062306a36Sopenharmony_ci state->intermediate_freq = (u16) (IntermediateFrequency / 1000); 254162306a36Sopenharmony_ci /* expected system clock frequency in kHz */ 254262306a36Sopenharmony_ci state->expected_sys_clock_freq = 48000; 254362306a36Sopenharmony_ci /* real system clock frequency in kHz */ 254462306a36Sopenharmony_ci state->sys_clock_freq = 48000; 254562306a36Sopenharmony_ci state->osc_clock_freq = (u16) ulClock; 254662306a36Sopenharmony_ci state->osc_clock_deviation = 0; 254762306a36Sopenharmony_ci state->cscd_state = CSCD_INIT; 254862306a36Sopenharmony_ci state->drxd_state = DRXD_UNINITIALIZED; 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci state->PGA = 0; 255162306a36Sopenharmony_ci state->type_A = 0; 255262306a36Sopenharmony_ci state->tuner_mirrors = 0; 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci /* modify MPEG output attributes */ 255562306a36Sopenharmony_ci state->insert_rs_byte = state->config.insert_rs_byte; 255662306a36Sopenharmony_ci state->enable_parallel = (ulSerialMode != 1); 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci /* Timing div, 250ns/Psys */ 255962306a36Sopenharmony_ci /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) * 256262306a36Sopenharmony_ci ulHiI2cDelay) / 1000; 256362306a36Sopenharmony_ci /* Bridge delay, uses oscilator clock */ 256462306a36Sopenharmony_ci /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ 256562306a36Sopenharmony_ci state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) * 256662306a36Sopenharmony_ci ulHiI2cBridgeDelay) / 1000; 256762306a36Sopenharmony_ci 256862306a36Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; 256962306a36Sopenharmony_ci /* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */ 257062306a36Sopenharmony_ci state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; 257162306a36Sopenharmony_ci return 0; 257262306a36Sopenharmony_ci} 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_cistatic int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size) 257562306a36Sopenharmony_ci{ 257662306a36Sopenharmony_ci int status = 0; 257762306a36Sopenharmony_ci u32 driverVersion; 257862306a36Sopenharmony_ci 257962306a36Sopenharmony_ci if (state->init_done) 258062306a36Sopenharmony_ci return 0; 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_ci CDRXD(state, state->config.IF ? state->config.IF : 36000000); 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci do { 258562306a36Sopenharmony_ci state->operation_mode = OM_Default; 258662306a36Sopenharmony_ci 258762306a36Sopenharmony_ci status = SetDeviceTypeId(state); 258862306a36Sopenharmony_ci if (status < 0) 258962306a36Sopenharmony_ci break; 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci /* Apply I2c address patch to B1 */ 259262306a36Sopenharmony_ci if (!state->type_A && state->m_HiI2cPatch) { 259362306a36Sopenharmony_ci status = WriteTable(state, state->m_HiI2cPatch); 259462306a36Sopenharmony_ci if (status < 0) 259562306a36Sopenharmony_ci break; 259662306a36Sopenharmony_ci } 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci if (state->type_A) { 259962306a36Sopenharmony_ci /* HI firmware patch for UIO readout, 260062306a36Sopenharmony_ci avoid clearing of result register */ 260162306a36Sopenharmony_ci status = Write16(state, 0x43012D, 0x047f, 0); 260262306a36Sopenharmony_ci if (status < 0) 260362306a36Sopenharmony_ci break; 260462306a36Sopenharmony_ci } 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci status = HI_ResetCommand(state); 260762306a36Sopenharmony_ci if (status < 0) 260862306a36Sopenharmony_ci break; 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci status = StopAllProcessors(state); 261162306a36Sopenharmony_ci if (status < 0) 261262306a36Sopenharmony_ci break; 261362306a36Sopenharmony_ci status = InitCC(state); 261462306a36Sopenharmony_ci if (status < 0) 261562306a36Sopenharmony_ci break; 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ci state->osc_clock_deviation = 0; 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_ci if (state->config.osc_deviation) 262062306a36Sopenharmony_ci state->osc_clock_deviation = 262162306a36Sopenharmony_ci state->config.osc_deviation(state->priv, 0, 0); 262262306a36Sopenharmony_ci { 262362306a36Sopenharmony_ci /* Handle clock deviation */ 262462306a36Sopenharmony_ci s32 devB; 262562306a36Sopenharmony_ci s32 devA = (s32) (state->osc_clock_deviation) * 262662306a36Sopenharmony_ci (s32) (state->expected_sys_clock_freq); 262762306a36Sopenharmony_ci /* deviation in kHz */ 262862306a36Sopenharmony_ci s32 deviation = (devA / (1000000L)); 262962306a36Sopenharmony_ci /* rounding, signed */ 263062306a36Sopenharmony_ci if (devA > 0) 263162306a36Sopenharmony_ci devB = (2); 263262306a36Sopenharmony_ci else 263362306a36Sopenharmony_ci devB = (-2); 263462306a36Sopenharmony_ci if ((devB * (devA % 1000000L) > 1000000L)) { 263562306a36Sopenharmony_ci /* add +1 or -1 */ 263662306a36Sopenharmony_ci deviation += (devB / 2); 263762306a36Sopenharmony_ci } 263862306a36Sopenharmony_ci 263962306a36Sopenharmony_ci state->sys_clock_freq = 264062306a36Sopenharmony_ci (u16) ((state->expected_sys_clock_freq) + 264162306a36Sopenharmony_ci deviation); 264262306a36Sopenharmony_ci } 264362306a36Sopenharmony_ci status = InitHI(state); 264462306a36Sopenharmony_ci if (status < 0) 264562306a36Sopenharmony_ci break; 264662306a36Sopenharmony_ci status = InitAtomicRead(state); 264762306a36Sopenharmony_ci if (status < 0) 264862306a36Sopenharmony_ci break; 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci status = EnableAndResetMB(state); 265162306a36Sopenharmony_ci if (status < 0) 265262306a36Sopenharmony_ci break; 265362306a36Sopenharmony_ci if (state->type_A) { 265462306a36Sopenharmony_ci status = ResetCEFR(state); 265562306a36Sopenharmony_ci if (status < 0) 265662306a36Sopenharmony_ci break; 265762306a36Sopenharmony_ci } 265862306a36Sopenharmony_ci if (fw) { 265962306a36Sopenharmony_ci status = DownloadMicrocode(state, fw, fw_size); 266062306a36Sopenharmony_ci if (status < 0) 266162306a36Sopenharmony_ci break; 266262306a36Sopenharmony_ci } else { 266362306a36Sopenharmony_ci status = DownloadMicrocode(state, state->microcode, state->microcode_length); 266462306a36Sopenharmony_ci if (status < 0) 266562306a36Sopenharmony_ci break; 266662306a36Sopenharmony_ci } 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci if (state->PGA) { 266962306a36Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; 267062306a36Sopenharmony_ci SetCfgPga(state, 0); /* PGA = 0 dB */ 267162306a36Sopenharmony_ci } else { 267262306a36Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; 267362306a36Sopenharmony_ci } 267462306a36Sopenharmony_ci 267562306a36Sopenharmony_ci state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci status = InitFE(state); 267862306a36Sopenharmony_ci if (status < 0) 267962306a36Sopenharmony_ci break; 268062306a36Sopenharmony_ci status = InitFT(state); 268162306a36Sopenharmony_ci if (status < 0) 268262306a36Sopenharmony_ci break; 268362306a36Sopenharmony_ci status = InitCP(state); 268462306a36Sopenharmony_ci if (status < 0) 268562306a36Sopenharmony_ci break; 268662306a36Sopenharmony_ci status = InitCE(state); 268762306a36Sopenharmony_ci if (status < 0) 268862306a36Sopenharmony_ci break; 268962306a36Sopenharmony_ci status = InitEQ(state); 269062306a36Sopenharmony_ci if (status < 0) 269162306a36Sopenharmony_ci break; 269262306a36Sopenharmony_ci status = InitEC(state); 269362306a36Sopenharmony_ci if (status < 0) 269462306a36Sopenharmony_ci break; 269562306a36Sopenharmony_ci status = InitSC(state); 269662306a36Sopenharmony_ci if (status < 0) 269762306a36Sopenharmony_ci break; 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci status = SetCfgIfAgc(state, &state->if_agc_cfg); 270062306a36Sopenharmony_ci if (status < 0) 270162306a36Sopenharmony_ci break; 270262306a36Sopenharmony_ci status = SetCfgRfAgc(state, &state->rf_agc_cfg); 270362306a36Sopenharmony_ci if (status < 0) 270462306a36Sopenharmony_ci break; 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci state->cscd_state = CSCD_INIT; 270762306a36Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 270862306a36Sopenharmony_ci if (status < 0) 270962306a36Sopenharmony_ci break; 271062306a36Sopenharmony_ci status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 271162306a36Sopenharmony_ci if (status < 0) 271262306a36Sopenharmony_ci break; 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci driverVersion = (((VERSION_MAJOR / 10) << 4) + 271562306a36Sopenharmony_ci (VERSION_MAJOR % 10)) << 24; 271662306a36Sopenharmony_ci driverVersion += (((VERSION_MINOR / 10) << 4) + 271762306a36Sopenharmony_ci (VERSION_MINOR % 10)) << 16; 271862306a36Sopenharmony_ci driverVersion += ((VERSION_PATCH / 1000) << 12) + 271962306a36Sopenharmony_ci ((VERSION_PATCH / 100) << 8) + 272062306a36Sopenharmony_ci ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10); 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0); 272362306a36Sopenharmony_ci if (status < 0) 272462306a36Sopenharmony_ci break; 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci status = StopOC(state); 272762306a36Sopenharmony_ci if (status < 0) 272862306a36Sopenharmony_ci break; 272962306a36Sopenharmony_ci 273062306a36Sopenharmony_ci state->drxd_state = DRXD_STOPPED; 273162306a36Sopenharmony_ci state->init_done = 1; 273262306a36Sopenharmony_ci status = 0; 273362306a36Sopenharmony_ci } while (0); 273462306a36Sopenharmony_ci return status; 273562306a36Sopenharmony_ci} 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_cistatic int DRXD_status(struct drxd_state *state, u32 *pLockStatus) 273862306a36Sopenharmony_ci{ 273962306a36Sopenharmony_ci DRX_GetLockStatus(state, pLockStatus); 274062306a36Sopenharmony_ci 274162306a36Sopenharmony_ci /*if (*pLockStatus&DRX_LOCK_MPEG) */ 274262306a36Sopenharmony_ci if (*pLockStatus & DRX_LOCK_FEC) { 274362306a36Sopenharmony_ci ConfigureMPEGOutput(state, 1); 274462306a36Sopenharmony_ci /* Get status again, in case we have MPEG lock now */ 274562306a36Sopenharmony_ci /*DRX_GetLockStatus(state, pLockStatus); */ 274662306a36Sopenharmony_ci } 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci return 0; 274962306a36Sopenharmony_ci} 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci/****************************************************************************/ 275262306a36Sopenharmony_ci/****************************************************************************/ 275362306a36Sopenharmony_ci/****************************************************************************/ 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_cistatic int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength) 275662306a36Sopenharmony_ci{ 275762306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 275862306a36Sopenharmony_ci u32 value; 275962306a36Sopenharmony_ci int res; 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci res = ReadIFAgc(state, &value); 276262306a36Sopenharmony_ci if (res < 0) 276362306a36Sopenharmony_ci *strength = 0; 276462306a36Sopenharmony_ci else 276562306a36Sopenharmony_ci *strength = 0xffff - (value << 4); 276662306a36Sopenharmony_ci return 0; 276762306a36Sopenharmony_ci} 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_cistatic int drxd_read_status(struct dvb_frontend *fe, enum fe_status *status) 277062306a36Sopenharmony_ci{ 277162306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 277262306a36Sopenharmony_ci u32 lock; 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ci DRXD_status(state, &lock); 277562306a36Sopenharmony_ci *status = 0; 277662306a36Sopenharmony_ci /* No MPEG lock in V255 firmware, bug ? */ 277762306a36Sopenharmony_ci#if 1 277862306a36Sopenharmony_ci if (lock & DRX_LOCK_MPEG) 277962306a36Sopenharmony_ci *status |= FE_HAS_LOCK; 278062306a36Sopenharmony_ci#else 278162306a36Sopenharmony_ci if (lock & DRX_LOCK_FEC) 278262306a36Sopenharmony_ci *status |= FE_HAS_LOCK; 278362306a36Sopenharmony_ci#endif 278462306a36Sopenharmony_ci if (lock & DRX_LOCK_FEC) 278562306a36Sopenharmony_ci *status |= FE_HAS_VITERBI | FE_HAS_SYNC; 278662306a36Sopenharmony_ci if (lock & DRX_LOCK_DEMOD) 278762306a36Sopenharmony_ci *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci return 0; 279062306a36Sopenharmony_ci} 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_cistatic int drxd_init(struct dvb_frontend *fe) 279362306a36Sopenharmony_ci{ 279462306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_ci return DRXD_init(state, NULL, 0); 279762306a36Sopenharmony_ci} 279862306a36Sopenharmony_ci 279962306a36Sopenharmony_cistatic int drxd_config_i2c(struct dvb_frontend *fe, int onoff) 280062306a36Sopenharmony_ci{ 280162306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 280262306a36Sopenharmony_ci 280362306a36Sopenharmony_ci if (state->config.disable_i2c_gate_ctrl == 1) 280462306a36Sopenharmony_ci return 0; 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci return DRX_ConfigureI2CBridge(state, onoff); 280762306a36Sopenharmony_ci} 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_cistatic int drxd_get_tune_settings(struct dvb_frontend *fe, 281062306a36Sopenharmony_ci struct dvb_frontend_tune_settings *sets) 281162306a36Sopenharmony_ci{ 281262306a36Sopenharmony_ci sets->min_delay_ms = 10000; 281362306a36Sopenharmony_ci sets->max_drift = 0; 281462306a36Sopenharmony_ci sets->step_size = 0; 281562306a36Sopenharmony_ci return 0; 281662306a36Sopenharmony_ci} 281762306a36Sopenharmony_ci 281862306a36Sopenharmony_cistatic int drxd_read_ber(struct dvb_frontend *fe, u32 * ber) 281962306a36Sopenharmony_ci{ 282062306a36Sopenharmony_ci *ber = 0; 282162306a36Sopenharmony_ci return 0; 282262306a36Sopenharmony_ci} 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_cistatic int drxd_read_snr(struct dvb_frontend *fe, u16 * snr) 282562306a36Sopenharmony_ci{ 282662306a36Sopenharmony_ci *snr = 0; 282762306a36Sopenharmony_ci return 0; 282862306a36Sopenharmony_ci} 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_cistatic int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) 283162306a36Sopenharmony_ci{ 283262306a36Sopenharmony_ci *ucblocks = 0; 283362306a36Sopenharmony_ci return 0; 283462306a36Sopenharmony_ci} 283562306a36Sopenharmony_ci 283662306a36Sopenharmony_cistatic int drxd_sleep(struct dvb_frontend *fe) 283762306a36Sopenharmony_ci{ 283862306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 283962306a36Sopenharmony_ci 284062306a36Sopenharmony_ci ConfigureMPEGOutput(state, 0); 284162306a36Sopenharmony_ci return 0; 284262306a36Sopenharmony_ci} 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_cistatic int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 284562306a36Sopenharmony_ci{ 284662306a36Sopenharmony_ci return drxd_config_i2c(fe, enable); 284762306a36Sopenharmony_ci} 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_cistatic int drxd_set_frontend(struct dvb_frontend *fe) 285062306a36Sopenharmony_ci{ 285162306a36Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 285262306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 285362306a36Sopenharmony_ci s32 off = 0; 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_ci state->props = *p; 285662306a36Sopenharmony_ci DRX_Stop(state); 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 285962306a36Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 286062306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 286162306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 286262306a36Sopenharmony_ci } 286362306a36Sopenharmony_ci 286462306a36Sopenharmony_ci msleep(200); 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci return DRX_Start(state, off); 286762306a36Sopenharmony_ci} 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_cistatic void drxd_release(struct dvb_frontend *fe) 287062306a36Sopenharmony_ci{ 287162306a36Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci kfree(state); 287462306a36Sopenharmony_ci} 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_cistatic const struct dvb_frontend_ops drxd_ops = { 287762306a36Sopenharmony_ci .delsys = { SYS_DVBT}, 287862306a36Sopenharmony_ci .info = { 287962306a36Sopenharmony_ci .name = "Micronas DRXD DVB-T", 288062306a36Sopenharmony_ci .frequency_min_hz = 47125 * kHz, 288162306a36Sopenharmony_ci .frequency_max_hz = 855250 * kHz, 288262306a36Sopenharmony_ci .frequency_stepsize_hz = 166667, 288362306a36Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 288462306a36Sopenharmony_ci FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | 288562306a36Sopenharmony_ci FE_CAN_FEC_AUTO | 288662306a36Sopenharmony_ci FE_CAN_QAM_16 | FE_CAN_QAM_64 | 288762306a36Sopenharmony_ci FE_CAN_QAM_AUTO | 288862306a36Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 288962306a36Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 289062306a36Sopenharmony_ci FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS}, 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci .release = drxd_release, 289362306a36Sopenharmony_ci .init = drxd_init, 289462306a36Sopenharmony_ci .sleep = drxd_sleep, 289562306a36Sopenharmony_ci .i2c_gate_ctrl = drxd_i2c_gate_ctrl, 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci .set_frontend = drxd_set_frontend, 289862306a36Sopenharmony_ci .get_tune_settings = drxd_get_tune_settings, 289962306a36Sopenharmony_ci 290062306a36Sopenharmony_ci .read_status = drxd_read_status, 290162306a36Sopenharmony_ci .read_ber = drxd_read_ber, 290262306a36Sopenharmony_ci .read_signal_strength = drxd_read_signal_strength, 290362306a36Sopenharmony_ci .read_snr = drxd_read_snr, 290462306a36Sopenharmony_ci .read_ucblocks = drxd_read_ucblocks, 290562306a36Sopenharmony_ci}; 290662306a36Sopenharmony_ci 290762306a36Sopenharmony_cistruct dvb_frontend *drxd_attach(const struct drxd_config *config, 290862306a36Sopenharmony_ci void *priv, struct i2c_adapter *i2c, 290962306a36Sopenharmony_ci struct device *dev) 291062306a36Sopenharmony_ci{ 291162306a36Sopenharmony_ci struct drxd_state *state = NULL; 291262306a36Sopenharmony_ci 291362306a36Sopenharmony_ci state = kzalloc(sizeof(*state), GFP_KERNEL); 291462306a36Sopenharmony_ci if (!state) 291562306a36Sopenharmony_ci return NULL; 291662306a36Sopenharmony_ci 291762306a36Sopenharmony_ci state->ops = drxd_ops; 291862306a36Sopenharmony_ci state->dev = dev; 291962306a36Sopenharmony_ci state->config = *config; 292062306a36Sopenharmony_ci state->i2c = i2c; 292162306a36Sopenharmony_ci state->priv = priv; 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci mutex_init(&state->mutex); 292462306a36Sopenharmony_ci 292562306a36Sopenharmony_ci if (Read16(state, 0, NULL, 0) < 0) 292662306a36Sopenharmony_ci goto error; 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci state->frontend.ops = drxd_ops; 292962306a36Sopenharmony_ci state->frontend.demodulator_priv = state; 293062306a36Sopenharmony_ci ConfigureMPEGOutput(state, 0); 293162306a36Sopenharmony_ci /* add few initialization to allow gate control */ 293262306a36Sopenharmony_ci CDRXD(state, state->config.IF ? state->config.IF : 36000000); 293362306a36Sopenharmony_ci InitHI(state); 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci return &state->frontend; 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_cierror: 293862306a36Sopenharmony_ci printk(KERN_ERR "drxd: not found\n"); 293962306a36Sopenharmony_ci kfree(state); 294062306a36Sopenharmony_ci return NULL; 294162306a36Sopenharmony_ci} 294262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drxd_attach); 294362306a36Sopenharmony_ci 294462306a36Sopenharmony_ciMODULE_DESCRIPTION("DRXD driver"); 294562306a36Sopenharmony_ciMODULE_AUTHOR("Micronas"); 294662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2947